diff options
122 files changed, 2949 insertions, 1067 deletions
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 4a3109b2884..356fd86f4ea 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -42,80 +42,81 @@ struct dev_pm_ops { ... }; -The ->runtime_suspend() callback is executed by the PM core for the bus type of -the device being suspended. The bus type's callback is then _entirely_ -_responsible_ for handling the device as appropriate, which may, but need not -include executing the device driver's own ->runtime_suspend() callback (from the +The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are +executed by the PM core for either the bus type, or device type (if the bus +type's callback is not defined), or device class (if the bus type's and device +type's callbacks are not defined) of given device. The bus type, device type +and device class callbacks are referred to as subsystem-level callbacks in what +follows. + +The subsystem-level suspend callback is _entirely_ _responsible_ for handling +the suspend of the device as appropriate, which may, but need not include +executing the device driver's own ->runtime_suspend() callback (from the PM core's point of view it is not necessary to implement a ->runtime_suspend() -callback in a device driver as long as the bus type's ->runtime_suspend() knows -what to do to handle the device). +callback in a device driver as long as the subsystem-level suspend callback +knows what to do to handle the device). - * Once the bus type's ->runtime_suspend() callback has completed successfully + * Once the subsystem-level suspend callback has completed successfully for given device, the PM core regards the device as suspended, which need not mean that the device has been put into a low power state. It is supposed to mean, however, that the device will not process data and will - not communicate with the CPU(s) and RAM until its bus type's - ->runtime_resume() callback is executed for it. The run-time PM status of - a device after successful execution of its bus type's ->runtime_suspend() - callback is 'suspended'. - - * If the bus type's ->runtime_suspend() callback returns -EBUSY or -EAGAIN, - the device's run-time PM status is supposed to be 'active', which means that - the device _must_ be fully operational afterwards. - - * If the bus type's ->runtime_suspend() callback returns an error code - different from -EBUSY or -EAGAIN, the PM core regards this as a fatal - error and will refuse to run the helper functions described in Section 4 - for the device, until the status of it is directly set either to 'active' - or to 'suspended' (the PM core provides special helper functions for this - purpose). - -In particular, if the driver requires remote wakeup capability for proper -functioning and device_run_wake() returns 'false' for the device, then -->runtime_suspend() should return -EBUSY. On the other hand, if -device_run_wake() returns 'true' for the device and the device is put -into a low power state during the execution of its bus type's -->runtime_suspend(), it is expected that remote wake-up (i.e. hardware mechanism -allowing the device to request a change of its power state, such as PCI PME) -will be enabled for the device. Generally, remote wake-up should be enabled -for all input devices put into a low power state at run time. - -The ->runtime_resume() callback is executed by the PM core for the bus type of -the device being woken up. The bus type's callback is then _entirely_ -_responsible_ for handling the device as appropriate, which may, but need not -include executing the device driver's own ->runtime_resume() callback (from the -PM core's point of view it is not necessary to implement a ->runtime_resume() -callback in a device driver as long as the bus type's ->runtime_resume() knows -what to do to handle the device). - - * Once the bus type's ->runtime_resume() callback has completed successfully, - the PM core regards the device as fully operational, which means that the - device _must_ be able to complete I/O operations as needed. The run-time - PM status of the device is then 'active'. - - * If the bus type's ->runtime_resume() callback returns an error code, the PM - core regards this as a fatal error and will refuse to run the helper - functions described in Section 4 for the device, until its status is - directly set either to 'active' or to 'suspended' (the PM core provides - special helper functions for this purpose). - -The ->runtime_idle() callback is executed by the PM core for the bus type of -given device whenever the device appears to be idle, which is indicated to the -PM core by two counters, the device's usage counter and the counter of 'active' -children of the device. + not communicate with the CPU(s) and RAM until the subsystem-level resume + callback is executed for it. The run-time PM status of a device after + successful execution of the subsystem-level suspend callback is 'suspended'. + + * If the subsystem-level suspend callback returns -EBUSY or -EAGAIN, + the device's run-time PM status is 'active', which means that the device + _must_ be fully operational afterwards. + + * If the subsystem-level suspend callback returns an error code different + from -EBUSY or -EAGAIN, the PM core regards this as a fatal error and will + refuse to run the helper functions described in Section 4 for the device, + until the status of it is directly set either to 'active', or to 'suspended' + (the PM core provides special helper functions for this purpose). + +In particular, if the driver requires remote wake-up capability (i.e. hardware +mechanism allowing the device to request a change of its power state, such as +PCI PME) for proper functioning and device_run_wake() returns 'false' for the +device, then ->runtime_suspend() should return -EBUSY. On the other hand, if +device_run_wake() returns 'true' for the device and the device is put into a low +power state during the execution of the subsystem-level suspend callback, it is +expected that remote wake-up will be enabled for the device. Generally, remote +wake-up should be enabled for all input devices put into a low power state at +run time. + +The subsystem-level resume callback is _entirely_ _responsible_ for handling the +resume of the device as appropriate, which may, but need not include executing +the device driver's own ->runtime_resume() callback (from the PM core's point of +view it is not necessary to implement a ->runtime_resume() callback in a device +driver as long as the subsystem-level resume callback knows what to do to handle +the device). + + * Once the subsystem-level resume callback has completed successfully, the PM + core regards the device as fully operational, which means that the device + _must_ be able to complete I/O operations as needed. The run-time PM status + of the device is then 'active'. + + * If the subsystem-level resume callback returns an error code, the PM core + regards this as a fatal error and will refuse to run the helper functions + described in Section 4 for the device, until its status is directly set + either to 'active' or to 'suspended' (the PM core provides special helper + functions for this purpose). + +The subsystem-level idle callback is executed by the PM core whenever the device +appears to be idle, which is indicated to the PM core by two counters, the +device's usage counter and the counter of 'active' children of the device. * If any of these counters is decreased using a helper function provided by the PM core and it turns out to be equal to zero, the other counter is checked. If that counter also is equal to zero, the PM core executes the - device bus type's ->runtime_idle() callback (with the device as an - argument). + subsystem-level idle callback with the device as an argument. -The action performed by a bus type's ->runtime_idle() callback is totally -dependent on the bus type in question, but the expected and recommended action -is to check if the device can be suspended (i.e. if all of the conditions -necessary for suspending the device are satisfied) and to queue up a suspend -request for the device in that case. The value returned by this callback is -ignored by the PM core. +The action performed by a subsystem-level idle callback is totally dependent on +the subsystem in question, but the expected and recommended action is to check +if the device can be suspended (i.e. if all of the conditions necessary for +suspending the device are satisfied) and to queue up a suspend request for the +device in that case. The value returned by this callback is ignored by the PM +core. The helper functions provided by the PM core, described in Section 4, guarantee that the following constraints are met with respect to the bus type's run-time @@ -238,41 +239,41 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: removing the device from device hierarchy int pm_runtime_idle(struct device *dev); - - execute ->runtime_idle() for the device's bus type; returns 0 on success - or error code on failure, where -EINPROGRESS means that ->runtime_idle() - is already being executed + - execute the subsystem-level idle callback for the device; returns 0 on + success or error code on failure, where -EINPROGRESS means that + ->runtime_idle() is already being executed int pm_runtime_suspend(struct device *dev); - - execute ->runtime_suspend() for the device's bus type; returns 0 on + - execute the subsystem-level suspend callback for the device; returns 0 on success, 1 if the device's run-time PM status was already 'suspended', or error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt to suspend the device again in future int pm_runtime_resume(struct device *dev); - - execute ->runtime_resume() for the device's bus type; returns 0 on + - execute the subsystem-leve resume callback for the device; returns 0 on success, 1 if the device's run-time PM status was already 'active' or error code on failure, where -EAGAIN means it may be safe to attempt to resume the device again in future, but 'power.runtime_error' should be checked additionally int pm_request_idle(struct device *dev); - - submit a request to execute ->runtime_idle() for the device's bus type - (the request is represented by a work item in pm_wq); returns 0 on success - or error code if the request has not been queued up + - submit a request to execute the subsystem-level idle callback for the + device (the request is represented by a work item in pm_wq); returns 0 on + success or error code if the request has not been queued up int pm_schedule_suspend(struct device *dev, unsigned int delay); - - schedule the execution of ->runtime_suspend() for the device's bus type - in future, where 'delay' is the time to wait before queuing up a suspend - work item in pm_wq, in milliseconds (if 'delay' is zero, the work item is - queued up immediately); returns 0 on success, 1 if the device's PM + - schedule the execution of the subsystem-level suspend callback for the + device in future, where 'delay' is the time to wait before queuing up a + suspend work item in pm_wq, in milliseconds (if 'delay' is zero, the work + item is queued up immediately); returns 0 on success, 1 if the device's PM run-time status was already 'suspended', or error code if the request hasn't been scheduled (or queued up if 'delay' is 0); if the execution of ->runtime_suspend() is already scheduled and not yet expired, the new value of 'delay' will be used as the time to wait int pm_request_resume(struct device *dev); - - submit a request to execute ->runtime_resume() for the device's bus type - (the request is represented by a work item in pm_wq); returns 0 on + - submit a request to execute the subsystem-level resume callback for the + device (the request is represented by a work item in pm_wq); returns 0 on success, 1 if the device's run-time PM status was already 'active', or error code if the request hasn't been queued up @@ -303,12 +304,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: run-time PM callbacks described in Section 2 int pm_runtime_disable(struct device *dev); - - prevent the run-time PM helper functions from running the device bus - type's run-time PM callbacks, make sure that all of the pending run-time - PM operations on the device are either completed or canceled; returns - 1 if there was a resume request pending and it was necessary to execute - ->runtime_resume() for the device's bus type to satisfy that request, - otherwise 0 is returned + - prevent the run-time PM helper functions from running subsystem-level + run-time PM callbacks for the device, make sure that all of the pending + run-time PM operations on the device are either completed or canceled; + returns 1 if there was a resume request pending and it was necessary to + execute the subsystem-level resume callback for the device to satisfy that + request, otherwise 0 is returned void pm_suspend_ignore_children(struct device *dev, bool enable); - set/unset the power.ignore_children flag of the device @@ -378,5 +379,55 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has -finished, so the PM core uses pm_runtime_idle_sync() to invoke the device bus -type's ->runtime_idle() callback at that time. +finished, so the PM core uses pm_runtime_idle_sync() to invoke the +subsystem-level idle callback for the device at that time. + +6. Run-time PM and System Sleep + +Run-time PM and system sleep (i.e., system suspend and hibernation, also known +as suspend-to-RAM and suspend-to-disk) interact with each other in a couple of +ways. If a device is active when a system sleep starts, everything is +straightforward. But what should happen if the device is already suspended? + +The device may have different wake-up settings for run-time PM and system sleep. +For example, remote wake-up may be enabled for run-time suspend but disallowed +for system sleep (device_may_wakeup(dev) returns 'false'). When this happens, +the subsystem-level system suspend callback is responsible for changing the +device's wake-up setting (it may leave that to the device driver's system +suspend routine). It may be necessary to resume the device and suspend it again +in order to do so. The same is true if the driver uses different power levels +or other settings for run-time suspend and system sleep. + +During system resume, devices generally should be brought back to full power, +even if they were suspended before the system sleep began. There are several +reasons for this, including: + + * The device might need to switch power levels, wake-up settings, etc. + + * Remote wake-up events might have been lost by the firmware. + + * The device's children may need the device to be at full power in order + to resume themselves. + + * The driver's idea of the device state may not agree with the device's + physical state. This can happen during resume from hibernation. + + * The device might need to be reset. + + * Even though the device was suspended, if its usage counter was > 0 then most + likely it would need a run-time resume in the near future anyway. + + * Always going back to full power is simplest. + +If the device was suspended before the sleep began, then its run-time PM status +will have to be updated to reflect the actual post-system sleep status. The way +to do this is: + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + +The PM core always increments the run-time usage counter before calling the +->prepare() callback and decrements it after calling the ->complete() callback. +Hence disabling run-time PM temporarily like this will not cause any run-time +suspend callbacks to be lost. diff --git a/Documentation/powerpc/dts-bindings/fsl/mpic.txt b/Documentation/powerpc/dts-bindings/fsl/mpic.txt new file mode 100644 index 00000000000..71e39cf3215 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/fsl/mpic.txt @@ -0,0 +1,42 @@ +* OpenPIC and its interrupt numbers on Freescale's e500/e600 cores + +The OpenPIC specification does not specify which interrupt source has to +become which interrupt number. This is up to the software implementation +of the interrupt controller. The only requirement is that every +interrupt source has to have an unique interrupt number / vector number. +To accomplish this the current implementation assigns the number zero to +the first source, the number one to the second source and so on until +all interrupt sources have their unique number. +Usually the assigned vector number equals the interrupt number mentioned +in the documentation for a given core / CPU. This is however not true +for the e500 cores (MPC85XX CPUs) where the documentation distinguishes +between internal and external interrupt sources and starts counting at +zero for both of them. + +So what to write for external interrupt source X or internal interrupt +source Y into the device tree? Here is an example: + +The memory map for the interrupt controller in the MPC8544[0] shows, +that the first interrupt source starts at 0x5_0000 (PIC Register Address +Map-Interrupt Source Configuration Registers). This source becomes the +number zero therefore: + External interrupt 0 = interrupt number 0 + External interrupt 1 = interrupt number 1 + External interrupt 2 = interrupt number 2 + ... +Every interrupt number allocates 0x20 bytes register space. So to get +its number it is sufficient to shift the lower 16bits to right by five. +So for the external interrupt 10 we have: + 0x0140 >> 5 = 10 + +After the external sources, the internal sources follow. The in core I2C +controller on the MPC8544 for instance has the internal source number +27. Oo obtain its interrupt number we take the lower 16bits of its memory +address (0x5_0560) and shift it right: + 0x0560 >> 5 = 43 + +Therefore the I2C device node for the MPC8544 CPU has to have the +interrupt number 43 specified in the device tree. + +[0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual + MPC8544ERM Rev. 1 10/2007 diff --git a/Documentation/trace/events-kmem.txt b/Documentation/trace/events-kmem.txt index 6ef2a8652e1..aa82ee4a5a8 100644 --- a/Documentation/trace/events-kmem.txt +++ b/Documentation/trace/events-kmem.txt @@ -1,7 +1,7 @@ Subsystem Trace Points: kmem -The tracing system kmem captures events related to object and page allocation -within the kernel. Broadly speaking there are four major subheadings. +The kmem tracing system captures events related to object and page allocation +within the kernel. Broadly speaking there are five major subheadings. o Slab allocation of small objects of unknown type (kmalloc) o Slab allocation of small objects of known type @@ -9,7 +9,7 @@ within the kernel. Broadly speaking there are four major subheadings. o Per-CPU Allocator Activity o External Fragmentation -This document will describe what each of the tracepoints are and why they +This document describes what each of the tracepoints is and why they might be useful. 1. Slab allocation of small objects of unknown type @@ -34,7 +34,7 @@ kmem_cache_free call_site=%lx ptr=%p These events are similar in usage to the kmalloc-related events except that it is likely easier to pin the event down to a specific cache. At the time of writing, no information is available on what slab is being allocated from, -but the call_site can usually be used to extrapolate that information +but the call_site can usually be used to extrapolate that information. 3. Page allocation ================== @@ -80,9 +80,9 @@ event indicating whether it is for a percpu_refill or not. When the per-CPU list is too full, a number of pages are freed, each one which triggers a mm_page_pcpu_drain event. -The individual nature of the events are so that pages can be tracked +The individual nature of the events is so that pages can be tracked between allocation and freeing. A number of drain or refill pages that occur -consecutively imply the zone->lock being taken once. Large amounts of PCP +consecutively imply the zone->lock being taken once. Large amounts of per-CPU refills and drains could imply an imbalance between CPUs where too much work is being concentrated in one place. It could also indicate that the per-CPU lists should be a larger size. Finally, large amounts of refills on one CPU @@ -102,6 +102,6 @@ is important. Large numbers of this event implies that memory is fragmenting and high-order allocations will start failing at some time in the future. One -means of reducing the occurange of this event is to increase the size of +means of reducing the occurrence of this event is to increase the size of min_free_kbytes in increments of 3*pageblock_size*nr_online_nodes where pageblock_size is usually the size of the default hugepage size. diff --git a/MAINTAINERS b/MAINTAINERS index efd2ef2c266..d5244f1580b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1402,6 +1402,8 @@ L: linux-usb@vger.kernel.org S: Supported F: Documentation/usb/WUSB-Design-overview.txt F: Documentation/usb/wusb-cbaf +F: drivers/usb/host/hwa-hc.c +F: drivers/usb/host/whci/ F: drivers/usb/wusbcore/ F: include/linux/usb/wusb* @@ -5430,7 +5432,10 @@ ULTRA-WIDEBAND (UWB) SUBSYSTEM: M: David Vrabel <david.vrabel@csr.com> L: linux-usb@vger.kernel.org S: Supported -F: drivers/uwb/* +F: drivers/uwb/ +X: drivers/uwb/wlp/ +X: drivers/uwb/i1480/i1480u-wlp/ +X: drivers/uwb/i1480/i1480-wlp.h F: include/linux/uwb.h F: include/linux/uwb/ @@ -5943,9 +5948,12 @@ W: http://linuxwimax.org WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM M: David Vrabel <david.vrabel@csr.com> +L: netdev@vger.kernel.org S: Maintained F: include/linux/wlp.h F: drivers/uwb/wlp/ +F: drivers/uwb/i1480/i1480u-wlp/ +F: drivers/uwb/i1480/i1480-wlp.h WISTRON LAPTOP BUTTON DRIVER M: Miloslav Trmac <mitr@volny.cz> diff --git a/arch/powerpc/boot/dts/katmai.dts b/arch/powerpc/boot/dts/katmai.dts index 51eb6ed5da2..8f345de960c 100644 --- a/arch/powerpc/boot/dts/katmai.dts +++ b/arch/powerpc/boot/dts/katmai.dts @@ -108,12 +108,19 @@ dcr-reg = <0x00c 0x002>; }; + MQ0: mq { + compatible = "ibm,mq-440spe"; + dcr-reg = <0x040 0x020>; + }; + plb { compatible = "ibm,plb-440spe", "ibm,plb-440gp", "ibm,plb4"; #address-cells = <2>; #size-cells = <1>; /* addr-child addr-parent size */ - ranges = <0x4 0xe0000000 0x4 0xe0000000 0x20000000 + ranges = <0x4 0x00100000 0x4 0x00100000 0x00001000 + 0x4 0x00200000 0x4 0x00200000 0x00000400 + 0x4 0xe0000000 0x4 0xe0000000 0x20000000 0xc 0x00000000 0xc 0x00000000 0x20000000 0xd 0x00000000 0xd 0x00000000 0x80000000 0xd 0x80000000 0xd 0x80000000 0x80000000 @@ -400,6 +407,49 @@ 0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */ 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; }; + + I2O: i2o@400100000 { + compatible = "ibm,i2o-440spe"; + reg = <0x00000004 0x00100000 0x100>; + dcr-reg = <0x060 0x020>; + }; + + DMA0: dma0@400100100 { + compatible = "ibm,dma-440spe"; + cell-index = <0>; + reg = <0x00000004 0x00100100 0x100>; + dcr-reg = <0x060 0x020>; + interrupt-parent = <&DMA0>; + interrupts = <0 1>; + #interrupt-cells = <1>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-map = < + 0 &UIC0 0x14 4 + 1 &UIC1 0x16 4>; + }; + + DMA1: dma1@400100200 { + compatible = "ibm,dma-440spe"; + cell-index = <1>; + reg = <0x00000004 0x00100200 0x100>; + dcr-reg = <0x060 0x020>; + interrupt-parent = <&DMA1>; + interrupts = <0 1>; + #interrupt-cells = <1>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-map = < + 0 &UIC0 0x16 4 + 1 &UIC1 0x16 4>; + }; + + xor-accel@400200000 { + compatible = "amcc,xor-accelerator"; + reg = <0x00000004 0x00200000 0x400>; + interrupt-parent = <&UIC1>; + interrupts = <0x1f 4>; + }; }; chosen { diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts index 32e10f588c1..8a3a4f3ef83 100644 --- a/arch/powerpc/boot/dts/mpc8315erdb.dts +++ b/arch/powerpc/boot/dts/mpc8315erdb.dts @@ -204,6 +204,7 @@ interrupt-parent = <&ipic>; tbi-handle = <&tbi0>; phy-handle = < &phy0 >; + fsl,magic-packet; mdio@520 { #address-cells = <1>; @@ -246,6 +247,7 @@ interrupt-parent = <&ipic>; tbi-handle = <&tbi1>; phy-handle = < &phy1 >; + fsl,magic-packet; mdio@520 { #address-cells = <1>; @@ -309,6 +311,22 @@ interrupt-parent = <&ipic>; }; + gtm1: timer@500 { + compatible = "fsl,mpc8315-gtm", "fsl,gtm"; + reg = <0x500 0x100>; + interrupts = <90 8 78 8 84 8 72 8>; + interrupt-parent = <&ipic>; + clock-frequency = <133333333>; + }; + + timer@600 { + compatible = "fsl,mpc8315-gtm", "fsl,gtm"; + reg = <0x600 0x100>; + interrupts = <91 8 79 8 85 8 73 8>; + interrupt-parent = <&ipic>; + clock-frequency = <133333333>; + }; + /* IPIC * interrupts cell = <intr #, sense> * sense values match linux IORESOURCE_IRQ_* defines: @@ -337,6 +355,15 @@ 0x59 0x8>; interrupt-parent = < &ipic >; }; + + pmc: power@b00 { + compatible = "fsl,mpc8315-pmc", "fsl,mpc8313-pmc", + "fsl,mpc8349-pmc"; + reg = <0xb00 0x100 0xa00 0x100>; + interrupts = <80 8>; + interrupt-parent = <&ipic>; + fsl,mpc8313-wakeup-timer = <>m1>; + }; }; pci0: pci@e0008500 { diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index feeeb7f9d60..b53d1df11e2 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts @@ -63,6 +63,24 @@ reg = <0x200 0x100>; }; + gpio1: gpio-controller@c00 { + #gpio-cells = <2>; + compatible = "fsl,mpc8349-gpio"; + reg = <0xc00 0x100>; + interrupts = <74 0x8>; + interrupt-parent = <&ipic>; + gpio-controller; + }; + + gpio2: gpio-controller@d00 { + #gpio-cells = <2>; + compatible = "fsl,mpc8349-gpio"; + reg = <0xd00 0x100>; + interrupts = <75 0x8>; + interrupt-parent = <&ipic>; + gpio-controller; + }; + i2c@3000 { #address-cells = <1>; #size-cells = <0>; @@ -72,6 +90,12 @@ interrupts = <14 0x8>; interrupt-parent = <&ipic>; dfsrr; + + eeprom: at24@50 { + compatible = "st-micro,24c256"; + reg = <0x50>; + }; + }; i2c@3100 { @@ -91,6 +115,25 @@ interrupt-parent = <&ipic>; }; + pcf1: iexp@38 { + #gpio-cells = <2>; + compatible = "ti,pcf8574a"; + reg = <0x38>; + gpio-controller; + }; + + pcf2: iexp@39 { + #gpio-cells = <2>; + compatible = "ti,pcf8574a"; + reg = <0x39>; + gpio-controller; + }; + + spd: at24@51 { + compatible = "at24,spd"; + reg = <0x51>; + }; + mcu_pio: mcu@a { #gpio-cells = <2>; compatible = "fsl,mc9s08qg8-mpc8349emitx", @@ -275,6 +318,24 @@ reg = <0x700 0x100>; device_type = "ipic"; }; + + gpio-leds { + compatible = "gpio-leds"; + + green { + label = "Green"; + gpios = <&pcf1 0 1>; + linux,default-trigger = "heartbeat"; + }; + + yellow { + label = "Yellow"; + gpios = <&pcf1 1 1>; + /* linux,default-trigger = "heartbeat"; */ + default-state = "on"; + }; + }; + }; pci0: pci@e0008500 { @@ -331,7 +392,26 @@ compatible = "fsl,mpc8349e-localbus", "fsl,pq2pro-localbus"; reg = <0xe0005000 0xd8>; - ranges = <0x3 0x0 0xf0000000 0x210>; + ranges = <0x0 0x0 0xfe000000 0x1000000 /* flash */ + 0x1 0x0 0xf8000000 0x20000 /* VSC 7385 */ + 0x2 0x0 0xf9000000 0x200000 /* exp slot */ + 0x3 0x0 0xf0000000 0x210>; /* CF slot */ + + flash@0,0 { + compatible = "cfi-flash"; + reg = <0x0 0x0 0x800000>; + bank-width = <2>; + device-width = <1>; + }; + + flash@0,800000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "cfi-flash"; + reg = <0x0 0x800000 0x800000>; + bank-width = <2>; + device-width = <1>; + }; pata@3,0 { compatible = "fsl,mpc8349emitx-pata", "ata-generic"; diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts index 31605ee4afb..e576ee85c42 100644 --- a/arch/powerpc/boot/dts/warp.dts +++ b/arch/powerpc/boot/dts/warp.dts @@ -146,7 +146,7 @@ fpga@2,4000 { compatible = "pika,fpga-sd"; - reg = <0x00000002 0x00004000 0x00000A00>; + reg = <0x00000002 0x00004000 0x00004000>; }; nor@0,0 { diff --git a/arch/powerpc/boot/ugecon.c b/arch/powerpc/boot/ugecon.c index 50609ea6ddf..8f2a6b31153 100644 --- a/arch/powerpc/boot/ugecon.c +++ b/arch/powerpc/boot/ugecon.c @@ -86,7 +86,7 @@ static void ug_putc(char ch) while (!ug_is_txfifo_ready() && count--) barrier(); - if (count) + if (count >= 0) ug_raw_putc(ch); } diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index fc905924c02..826a65d3f00 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -757,7 +757,7 @@ CONFIG_SUNGEM=y # CONFIG_B44 is not set # CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y -CONFIG_ACENIC=y +CONFIG_ACENIC=m CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y @@ -794,8 +794,8 @@ CONFIG_NETDEV_10000=y # CONFIG_BNX2X is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set -CONFIG_TR=y -CONFIG_IBMOL=y +# CONFIG_TR is not set +# CONFIG_IBMOL is not set # CONFIG_3C359 is not set # CONFIG_TMS380TR is not set diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig index f925c555508..76982c51a4c 100644 --- a/arch/powerpc/configs/iseries_defconfig +++ b/arch/powerpc/configs/iseries_defconfig @@ -714,8 +714,8 @@ CONFIG_NETDEV_10000=y # CONFIG_BNX2X is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set -CONFIG_TR=y -CONFIG_IBMOL=y +# CONFIG_TR is not set +# CONFIG_IBMOL is not set # CONFIG_3C359 is not set # CONFIG_TMS380TR is not set diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 25240182457..7b3804a6e36 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -304,11 +304,11 @@ CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set -CONFIG_HZ=250 +CONFIG_HZ=100 CONFIG_SCHED_HRTICK=y CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set @@ -980,7 +980,7 @@ CONFIG_E100=y # CONFIG_SC92031 is not set # CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y -CONFIG_ACENIC=y +CONFIG_ACENIC=m CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y @@ -1023,8 +1023,8 @@ CONFIG_PASEMI_MAC=y # CONFIG_BNX2X is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set -CONFIG_TR=y -CONFIG_IBMOL=y +# CONFIG_TR is not set +# CONFIG_IBMOL is not set # CONFIG_3C359 is not set # CONFIG_TMS380TR is not set @@ -1863,7 +1863,7 @@ CONFIG_HFSPLUS_FS=m # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -CONFIG_CRAMFS=y +CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 18af4603625..8195f1650cb 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig @@ -1008,8 +1008,8 @@ CONFIG_IXGB=m # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set -CONFIG_TR=y -CONFIG_IBMOL=y +# CONFIG_TR is not set +# CONFIG_IBMOL is not set # CONFIG_3C359 is not set # CONFIG_TMS380TR is not set CONFIG_WLAN=y diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index c568329723b..ca9ff9aad74 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -230,11 +230,11 @@ CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -# CONFIG_HZ_100 is not set -CONFIG_HZ_250=y +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set -CONFIG_HZ=250 +CONFIG_HZ=100 CONFIG_SCHED_HRTICK=y CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set @@ -796,7 +796,7 @@ CONFIG_E100=y # CONFIG_NET_POCKET is not set # CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y -CONFIG_ACENIC=y +CONFIG_ACENIC=m CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y @@ -834,8 +834,8 @@ CONFIG_S2IO=m # CONFIG_BNX2X is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set -CONFIG_TR=y -CONFIG_IBMOL=y +# CONFIG_TR is not set +# CONFIG_IBMOL is not set # CONFIG_3C359 is not set # CONFIG_TMS380TR is not set @@ -1494,7 +1494,7 @@ CONFIG_CONFIGFS_FS=m # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -CONFIG_CRAMFS=y +CONFIG_CRAMFS=m # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 64e1fdca233..2c15212e170 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -68,7 +68,7 @@ _EMIT_BUG_ENTRY \ : : "i" (__FILE__), "i" (__LINE__), \ "i" (0), "i" (sizeof(struct bug_entry))); \ - for(;;) ; \ + unreachable(); \ } while (0) #define BUG_ON(x) do { \ diff --git a/arch/powerpc/include/asm/gpio.h b/arch/powerpc/include/asm/gpio.h index ea04632399d..38762edb5e5 100644 --- a/arch/powerpc/include/asm/gpio.h +++ b/arch/powerpc/include/asm/gpio.h @@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio) return __gpio_cansleep(gpio); } -/* - * Not implemented, yet. - */ static inline int gpio_to_irq(unsigned int gpio) { - return -ENOSYS; + return __gpio_to_irq(gpio); } static inline int irq_to_gpio(unsigned int irq) diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 3839839f83c..b876e989220 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg, */ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, unsigned int areg, struct pt_regs *regs, - unsigned int flags, unsigned int length) + unsigned int flags, unsigned int length, + unsigned int elsize) { char *ptr; + unsigned long *lptr; int ret = 0; + int sw = 0; + int i, j; flush_vsx_to_thread(current); @@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, else ptr = (char *) ¤t->thread.vr[reg - 32]; - if (flags & ST) - ret = __copy_to_user(addr, ptr, length); - else { - if (flags & SPLT){ - ret = __copy_from_user(ptr, addr, length); - ptr += length; + lptr = (unsigned long *) ptr; + + if (flags & SW) + sw = elsize-1; + + for (j = 0; j < length; j += elsize) { + for (i = 0; i < elsize; ++i) { + if (flags & ST) + ret |= __put_user(ptr[i^sw], addr + i); + else + ret |= __get_user(ptr[i^sw], addr + i); } - ret |= __copy_from_user(ptr, addr, length); + ptr += elsize; + addr += elsize; } - if (flags & U) - regs->gpr[areg] = regs->dar; - if (ret) + + if (!ret) { + if (flags & U) + regs->gpr[areg] = regs->dar; + + /* Splat load copies the same data to top and bottom 8 bytes */ + if (flags & SPLT) + lptr[1] = lptr[0]; + /* For 8 byte loads, zero the top 8 bytes */ + else if (!(flags & ST) && (8 == length)) + lptr[1] = 0; + } else return -EFAULT; + return 1; } #endif @@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs) #ifdef CONFIG_VSX if ((instruction & 0xfc00003e) == 0x7c000018) { - /* Additional register addressing bit (64 VSX vs 32 FPR/GPR */ + unsigned int elsize; + + /* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */ reg |= (instruction & 0x1) << 5; /* Simple inline decoder instead of a table */ + /* VSX has only 8 and 16 byte memory accesses */ + nb = 8; if (instruction & 0x200) nb = 16; - else if (instruction & 0x080) - nb = 8; - else - nb = 4; + + /* Vector stores in little-endian mode swap individual + elements, so process them separately */ + elsize = 4; + if (instruction & 0x80) + elsize = 8; + flags = 0; + if (regs->msr & MSR_LE) + flags |= SW; if (instruction & 0x100) flags |= ST; if (instruction & 0x040) @@ -787,7 +816,7 @@ int fix_alignment(struct pt_regs *regs) nb = 8; } PPC_WARN_ALIGNMENT(vsx, regs); - return emulate_vsx(addr, reg, areg, regs, flags, nb); + return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize); } #endif /* A size of 0 indicates an instruction we don't support, with diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 50f867d657d..3ecdcec0a39 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -340,7 +340,7 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, else def->tlbiel = 0; - DBG(" %d: shift=%02x, sllp=%04x, avpnm=%08x, " + DBG(" %d: shift=%02x, sllp=%04lx, avpnm=%08lx, " "tlbiel=%d, penc=%d\n", idx, shift, def->sllp, def->avpnm, def->tlbiel, def->penc); @@ -663,7 +663,7 @@ static void __init htab_initialize(void) base = (unsigned long)__va(lmb.memory.region[i].base); size = lmb.memory.region[i].size; - DBG("creating mapping for region: %lx..%lx (prot: %x)\n", + DBG("creating mapping for region: %lx..%lx (prot: %lx)\n", base, size, prot); #ifdef CONFIG_U3_DART @@ -879,7 +879,7 @@ static inline int subpage_protection(struct mm_struct *mm, unsigned long ea) */ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) { - void *pgdir; + pgd_t *pgdir; unsigned long vsid; struct mm_struct *mm; pte_t *ptep; @@ -1025,7 +1025,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) else #endif /* CONFIG_PPC_HAS_HASH_64K */ { - int spp = subpage_protection(pgdir, ea); + int spp = subpage_protection(mm, ea); if (access & spp) rc = -2; else @@ -1115,7 +1115,7 @@ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize, { unsigned long hash, index, shift, hidx, slot; - DBG_LOW("flush_hash_page(va=%016x)\n", va); + DBG_LOW("flush_hash_page(va=%016lx)\n", va); pte_iterate_hashed_subpages(pte, psize, va, index, shift) { hash = hpt_hash(va, shift, ssize); hidx = __rpte_to_hidx(pte, index); @@ -1123,7 +1123,7 @@ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize, hash = ~hash; slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; slot += hidx & _PTEIDX_GROUP_IX; - DBG_LOW(" sub %d: hash=%x, hidx=%x\n", index, slot, hidx); + DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx); ppc_md.hpte_invalidate(slot, va, psize, ssize, local); } pte_iterate_hashed_end(); } diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index be4f34c30a0..1044a634b6d 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c @@ -353,7 +353,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, read_lock(&tasklist_lock); for_each_process(p) { if (p->mm) - cpu_mask_clear_cpu(cpu, mm_cpumask(p->mm)); + cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); } read_unlock(&tasklist_lock); break; diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 177e4038b43..573b3bd1c45 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -382,7 +382,7 @@ static int __change_page_attr(struct page *page, pgprot_t prot) return 0; if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) return -EINVAL; - set_pte_at(&init_mm, address, kpte, mk_pte(page, prot)); + __set_pte_at(&init_mm, address, kpte, mk_pte(page, prot), 0); wmb(); #ifdef CONFIG_PPC_STD_MMU flush_hash_pages(0, address, pmd_val(*kpmd), 1); diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c index d306f07b9aa..43805348b81 100644 --- a/arch/powerpc/platforms/83xx/suspend.c +++ b/arch/powerpc/platforms/83xx/suspend.c @@ -32,6 +32,7 @@ #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ #define PMCCR1_NEXT_STATE_SHIFT 2 #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ +#define IMMR_SYSCR_OFFSET 0x100 #define IMMR_RCW_OFFSET 0x900 #define RCW_PCI_HOST 0x80000000 @@ -78,6 +79,22 @@ struct mpc83xx_clock { u32 sccr; }; +struct mpc83xx_syscr { + __be32 sgprl; + __be32 sgprh; + __be32 spridr; + __be32 :32; + __be32 spcr; + __be32 sicrl; + __be32 sicrh; +}; + +struct mpc83xx_saved { + u32 sicrl; + u32 sicrh; + u32 sccr; +}; + struct pmc_type { int has_deep_sleep; }; @@ -87,6 +104,8 @@ static int has_deep_sleep, deep_sleeping; static int pmc_irq; static struct mpc83xx_pmc __iomem *pmc_regs; static struct mpc83xx_clock __iomem *clock_regs; +static struct mpc83xx_syscr __iomem *syscr_regs; +static struct mpc83xx_saved saved_regs; static int is_pci_agent, wake_from_pci; static phys_addr_t immrbase; static int pci_pm_state; @@ -137,6 +156,20 @@ static irqreturn_t pmc_irq_handler(int irq, void *dev_id) return ret; } +static void mpc83xx_suspend_restore_regs(void) +{ + out_be32(&syscr_regs->sicrl, saved_regs.sicrl); + out_be32(&syscr_regs->sicrh, saved_regs.sicrh); + out_be32(&clock_regs->sccr, saved_regs.sccr); +} + +static void mpc83xx_suspend_save_regs(void) +{ + saved_regs.sicrl = in_be32(&syscr_regs->sicrl); + saved_regs.sicrh = in_be32(&syscr_regs->sicrh); + saved_regs.sccr = in_be32(&clock_regs->sccr); +} + static int mpc83xx_suspend_enter(suspend_state_t state) { int ret = -EAGAIN; @@ -166,6 +199,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) */ if (deep_sleeping) { + mpc83xx_suspend_save_regs(); + out_be32(&pmc_regs->mask, PMCER_ALL); out_be32(&pmc_regs->config1, @@ -179,6 +214,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); out_be32(&pmc_regs->mask, PMCER_PMCI); + + mpc83xx_suspend_restore_regs(); } else { out_be32(&pmc_regs->mask, PMCER_PMCI); @@ -194,7 +231,7 @@ out: return ret; } -static void mpc83xx_suspend_finish(void) +static void mpc83xx_suspend_end(void) { deep_sleeping = 0; } @@ -278,7 +315,7 @@ static struct platform_suspend_ops mpc83xx_suspend_ops = { .valid = mpc83xx_suspend_valid, .begin = mpc83xx_suspend_begin, .enter = mpc83xx_suspend_enter, - .finish = mpc83xx_suspend_finish, + .end = mpc83xx_suspend_end, }; static int pmc_probe(struct of_device *ofdev, @@ -333,12 +370,23 @@ static int pmc_probe(struct of_device *ofdev, goto out_pmc; } + if (has_deep_sleep) { + syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET, + sizeof(*syscr_regs)); + if (!syscr_regs) { + ret = -ENOMEM; + goto out_syscr; + } + } + if (is_pci_agent) mpc83xx_set_agent(); suspend_set_ops(&mpc83xx_suspend_ops); return 0; +out_syscr: + iounmap(clock_regs); out_pmc: iounmap(pmc_regs); out: diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index c5028a2e5a5..21f61b8c445 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -86,7 +86,7 @@ static int mpc8568_fixup_125_clock(struct phy_device *phydev) scr = phy_read(phydev, MV88E1111_SCR); if (scr < 0) - return err; + return scr; err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008); diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c index d5963285e3b..c278bd3a8fe 100644 --- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c @@ -102,7 +102,7 @@ static int flipper_pic_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hwirq) { set_irq_chip_data(virq, h->host_data); - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq); return 0; } diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c index dd20bff3320..a771f91e215 100644 --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c @@ -95,7 +95,7 @@ static int hlwd_pic_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hwirq) { set_irq_chip_data(virq, h->host_data); - get_irq_desc(virq)->status |= IRQ_LEVEL; + irq_to_desc(virq)->status |= IRQ_LEVEL; set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq); return 0; } @@ -132,9 +132,9 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq, struct irq_host *irq_host = get_irq_data(cascade_virq); unsigned int virq; - spin_lock(&desc->lock); + raw_spin_lock(&desc->lock); desc->chip->mask(cascade_virq); /* IRQ_LEVEL */ - spin_unlock(&desc->lock); + raw_spin_unlock(&desc->lock); virq = __hlwd_pic_get_irq(irq_host); if (virq != NO_IRQ) @@ -142,11 +142,11 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq, else pr_err("spurious interrupt!\n"); - spin_lock(&desc->lock); + raw_spin_lock(&desc->lock); desc->chip->ack(cascade_virq); /* IRQ_LEVEL */ if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) desc->chip->unmask(cascade_virq); - spin_unlock(&desc->lock); + raw_spin_unlock(&desc->lock); } /* diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c index edc956cc8b1..20a8ed91962 100644 --- a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c +++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c @@ -120,7 +120,7 @@ static void ug_putc(char ch) while (!ug_is_txfifo_ready() && count--) barrier(); - if (count) + if (count >= 0) ug_raw_putc(ch); } diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 0d9343df35b..6617915bcb1 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -855,59 +855,58 @@ static int mf_get_boot_rtc(struct rtc_time *tm) } #ifdef CONFIG_PROC_FS - -static int proc_mf_dump_cmdline(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int mf_cmdline_proc_show(struct seq_file *m, void *v) { - int len; - char *p; + char *page, *p; struct vsp_cmd_data vsp_cmd; int rc; dma_addr_t dma_addr; /* The HV appears to return no more than 256 bytes of command line */ - if (off >= 256) - return 0; - if ((off + count) > 256) - count = 256 - off; + page = kmalloc(256, GFP_KERNEL); + if (!page) + return -ENOMEM; - dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE); - if (dma_addr == DMA_ERROR_CODE) + dma_addr = iseries_hv_map(page, 256, DMA_FROM_DEVICE); + if (dma_addr == DMA_ERROR_CODE) { + kfree(page); return -ENOMEM; - memset(page, 0, off + count); + } + memset(page, 0, 256); memset(&vsp_cmd, 0, sizeof(vsp_cmd)); vsp_cmd.cmd = 33; vsp_cmd.sub_data.kern.token = dma_addr; vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; - vsp_cmd.sub_data.kern.side = (u64)data; - vsp_cmd.sub_data.kern.length = off + count; + vsp_cmd.sub_data.kern.side = (u64)m->private; + vsp_cmd.sub_data.kern.length = 256; mb(); rc = signal_vsp_instruction(&vsp_cmd); - iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE); - if (rc) + iseries_hv_unmap(dma_addr, 256, DMA_FROM_DEVICE); + if (rc) { + kfree(page); return rc; - if (vsp_cmd.result_code != 0) + } + if (vsp_cmd.result_code != 0) { + kfree(page); return -ENOMEM; + } p = page; - len = 0; - while (len < (off + count)) { - if ((*p == '\0') || (*p == '\n')) { - if (*p == '\0') - *p = '\n'; - p++; - len++; - *eof = 1; + while (p - page < 256) { + if (*p == '\0' || *p == '\n') { + *p = '\n'; break; } p++; - len++; - } - if (len < off) { - *eof = 1; - len = 0; } - return len; + seq_write(m, page, p - page); + kfree(page); + return 0; +} + +static int mf_cmdline_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, mf_cmdline_proc_show, PDE(inode)->data); } #if 0 @@ -962,10 +961,8 @@ static int proc_mf_dump_vmlinux(char *page, char **start, off_t off, } #endif -static int proc_mf_dump_side(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int mf_side_proc_show(struct seq_file *m, void *v) { - int len; char mf_current_side = ' '; struct vsp_cmd_data vsp_cmd; @@ -989,21 +986,17 @@ static int proc_mf_dump_side(char *page, char **start, off_t off, } } - len = sprintf(page, "%c\n", mf_current_side); + seq_printf(m, "%c\n", mf_current_side); + return 0; +} - if (len <= (off + count)) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; +static int mf_side_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, mf_side_proc_show, NULL); } -static int proc_mf_change_side(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static ssize_t mf_side_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { char side; u64 newSide; @@ -1041,6 +1034,15 @@ static int proc_mf_change_side(struct file *file, const char __user *buffer, return count; } +static const struct file_operations mf_side_proc_fops = { + .owner = THIS_MODULE, + .open = mf_side_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = mf_side_proc_write, +}; + #if 0 static void mf_getSrcHistory(char *buffer, int size) { @@ -1087,8 +1089,7 @@ static void mf_getSrcHistory(char *buffer, int size) } #endif -static int proc_mf_dump_src(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int mf_src_proc_show(struct seq_file *m, void *v) { #if 0 int len; @@ -1109,8 +1110,13 @@ static int proc_mf_dump_src(char *page, char **start, off_t off, #endif } -static int proc_mf_change_src(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int mf_src_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, mf_src_proc_show, NULL); +} + +static ssize_t mf_src_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { char stkbuf[10]; @@ -1135,9 +1141,19 @@ static int proc_mf_change_src(struct file *file, const char __user *buffer, return count; } -static int proc_mf_change_cmdline(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static const struct file_operations mf_src_proc_fops = { + .owner = THIS_MODULE, + .open = mf_src_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = mf_src_proc_write, +}; + +static ssize_t mf_cmdline_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { + void *data = PDE(file->f_path.dentry->d_inode)->data; struct vsp_cmd_data vsp_cmd; dma_addr_t dma_addr; char *page; @@ -1172,6 +1188,15 @@ out: return ret; } +static const struct file_operations mf_cmdline_proc_fops = { + .owner = THIS_MODULE, + .open = mf_cmdline_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = mf_cmdline_proc_write, +}; + static ssize_t proc_mf_change_vmlinux(struct file *file, const char __user *buf, size_t count, loff_t *ppos) @@ -1246,12 +1271,10 @@ static int __init mf_proc_init(void) if (!mf) return 1; - ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf); + ent = proc_create_data("cmdline", S_IRUSR|S_IWUSR, mf, + &mf_cmdline_proc_fops, (void *)(long)i); if (!ent) return 1; - ent->data = (void *)(long)i; - ent->read_proc = proc_mf_dump_cmdline; - ent->write_proc = proc_mf_change_cmdline; if (i == 3) /* no vmlinux entry for 'D' */ continue; @@ -1263,19 +1286,15 @@ static int __init mf_proc_init(void) return 1; } - ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); + ent = proc_create("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root, + &mf_side_proc_fops); if (!ent) return 1; - ent->data = (void *)0; - ent->read_proc = proc_mf_dump_side; - ent->write_proc = proc_mf_change_side; - ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); + ent = proc_create("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root, + &mf_src_proc_fops); if (!ent) return 1; - ent->data = (void *)0; - ent->read_proc = proc_mf_dump_src; - ent->write_proc = proc_mf_change_src; return 0; } diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 49ff4dc422b..5aea94f3083 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -116,7 +116,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) u16 vlanMap; dma_addr_t handle; HvLpEvent_Rc hvrc; - DECLARE_COMPLETION(done); + DECLARE_COMPLETION_ONSTACK(done); struct device_node *node; const char *sysid; diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 27554c807fd..c667f0f02c3 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -2,6 +2,8 @@ config PPC_PSERIES depends on PPC64 && PPC_BOOK3S bool "IBM pSeries & new (POWER5-based) iSeries" select MPIC + select PCI_MSI + select XICS select PPC_I8259 select PPC_RTAS select PPC_RTAS_DAEMON diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c index bcdcf0ccc8d..a277f2e28db 100644 --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c @@ -38,19 +38,28 @@ #include <asm/mmu.h> #include <asm/pgalloc.h> #include <asm/uaccess.h> +#include <linux/memory.h> #include "plpar_wrappers.h" #define CMM_DRIVER_VERSION "1.0.0" #define CMM_DEFAULT_DELAY 1 +#define CMM_HOTPLUG_DELAY 5 #define CMM_DEBUG 0 #define CMM_DISABLE 0 #define CMM_OOM_KB 1024 #define CMM_MIN_MEM_MB 256 #define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10)) #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) +/* + * The priority level tries to ensure that this notifier is called as + * late as possible to reduce thrashing in the shared memory pool. + */ +#define CMM_MEM_HOTPLUG_PRI 1 +#define CMM_MEM_ISOLATE_PRI 15 static unsigned int delay = CMM_DEFAULT_DELAY; +static unsigned int hotplug_delay = CMM_HOTPLUG_DELAY; static unsigned int oom_kb = CMM_OOM_KB; static unsigned int cmm_debug = CMM_DEBUG; static unsigned int cmm_disabled = CMM_DISABLE; @@ -65,6 +74,10 @@ MODULE_VERSION(CMM_DRIVER_VERSION); module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. " "[Default=" __stringify(CMM_DEFAULT_DELAY) "]"); +module_param_named(hotplug_delay, hotplug_delay, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(delay, "Delay (in seconds) after memory hotplug remove " + "before loaning resumes. " + "[Default=" __stringify(CMM_HOTPLUG_DELAY) "]"); module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " "[Default=" __stringify(CMM_OOM_KB) "]"); @@ -92,6 +105,9 @@ static unsigned long oom_freed_pages; static struct cmm_page_array *cmm_page_list; static DEFINE_SPINLOCK(cmm_lock); +static DEFINE_MUTEX(hotplug_mutex); +static int hotplug_occurred; /* protected by the hotplug mutex */ + static struct task_struct *cmm_thread_ptr; /** @@ -110,6 +126,17 @@ static long cmm_alloc_pages(long nr) cmm_dbg("Begin request for %ld pages\n", nr); while (nr) { + /* Exit if a hotplug operation is in progress or occurred */ + if (mutex_trylock(&hotplug_mutex)) { + if (hotplug_occurred) { + mutex_unlock(&hotplug_mutex); + break; + } + mutex_unlock(&hotplug_mutex); + } else { + break; + } + addr = __get_free_page(GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC); if (!addr) @@ -119,8 +146,9 @@ static long cmm_alloc_pages(long nr) if (!pa || pa->index >= CMM_NR_PAGES) { /* Need a new page for the page list. */ spin_unlock(&cmm_lock); - npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN | - __GFP_NORETRY | __GFP_NOMEMALLOC); + npa = (struct cmm_page_array *)__get_free_page( + GFP_NOIO | __GFP_NOWARN | + __GFP_NORETRY | __GFP_NOMEMALLOC); if (!npa) { pr_info("%s: Can not allocate new page list\n", __func__); free_page(addr); @@ -282,9 +310,28 @@ static int cmm_thread(void *dummy) while (1) { timeleft = msleep_interruptible(delay * 1000); - if (kthread_should_stop() || timeleft) { - loaned_pages_target = loaned_pages; + if (kthread_should_stop() || timeleft) break; + + if (mutex_trylock(&hotplug_mutex)) { + if (hotplug_occurred) { + hotplug_occurred = 0; + mutex_unlock(&hotplug_mutex); + cmm_dbg("Hotplug operation has occurred, " + "loaning activity suspended " + "for %d seconds.\n", + hotplug_delay); + timeleft = msleep_interruptible(hotplug_delay * + 1000); + if (kthread_should_stop() || timeleft) + break; + continue; + } + mutex_unlock(&hotplug_mutex); + } else { + cmm_dbg("Hotplug operation in progress, activity " + "suspended\n"); + continue; } cmm_get_mpp(); @@ -414,6 +461,193 @@ static struct notifier_block cmm_reboot_nb = { }; /** + * cmm_count_pages - Count the number of pages loaned in a particular range. + * + * @arg: memory_isolate_notify structure with address range and count + * + * Return value: + * 0 on success + **/ +static unsigned long cmm_count_pages(void *arg) +{ + struct memory_isolate_notify *marg = arg; + struct cmm_page_array *pa; + unsigned long start = (unsigned long)pfn_to_kaddr(marg->start_pfn); + unsigned long end = start + (marg->nr_pages << PAGE_SHIFT); + unsigned long idx; + + spin_lock(&cmm_lock); + pa = cmm_page_list; + while (pa) { + if ((unsigned long)pa >= start && (unsigned long)pa < end) + marg->pages_found++; + for (idx = 0; idx < pa->index; idx++) + if (pa->page[idx] >= start && pa->page[idx] < end) + marg->pages_found++; + pa = pa->next; + } + spin_unlock(&cmm_lock); + return 0; +} + +/** + * cmm_memory_isolate_cb - Handle memory isolation notifier calls + * @self: notifier block struct + * @action: action to take + * @arg: struct memory_isolate_notify data for handler + * + * Return value: + * NOTIFY_OK or notifier error based on subfunction return value + **/ +static int cmm_memory_isolate_cb(struct notifier_block *self, + unsigned long action, void *arg) +{ + int ret = 0; + + if (action == MEM_ISOLATE_COUNT) + ret = cmm_count_pages(arg); + + if (ret) + ret = notifier_from_errno(ret); + else + ret = NOTIFY_OK; + + return ret; +} + +static struct notifier_block cmm_mem_isolate_nb = { + .notifier_call = cmm_memory_isolate_cb, + .priority = CMM_MEM_ISOLATE_PRI +}; + +/** + * cmm_mem_going_offline - Unloan pages where memory is to be removed + * @arg: memory_notify structure with page range to be offlined + * + * Return value: + * 0 on success + **/ +static int cmm_mem_going_offline(void *arg) +{ + struct memory_notify *marg = arg; + unsigned long start_page = (unsigned long)pfn_to_kaddr(marg->start_pfn); + unsigned long end_page = start_page + (marg->nr_pages << PAGE_SHIFT); + struct cmm_page_array *pa_curr, *pa_last, *npa; + unsigned long idx; + unsigned long freed = 0; + + cmm_dbg("Memory going offline, searching 0x%lx (%ld pages).\n", + start_page, marg->nr_pages); + spin_lock(&cmm_lock); + + /* Search the page list for pages in the range to be offlined */ + pa_last = pa_curr = cmm_page_list; + while (pa_curr) { + for (idx = (pa_curr->index - 1); (idx + 1) > 0; idx--) { + if ((pa_curr->page[idx] < start_page) || + (pa_curr->page[idx] >= end_page)) + continue; + + plpar_page_set_active(__pa(pa_curr->page[idx])); + free_page(pa_curr->page[idx]); + freed++; + loaned_pages--; + totalram_pages++; + pa_curr->page[idx] = pa_last->page[--pa_last->index]; + if (pa_last->index == 0) { + if (pa_curr == pa_last) + pa_curr = pa_last->next; + pa_last = pa_last->next; + free_page((unsigned long)cmm_page_list); + cmm_page_list = pa_last; + continue; + } + } + pa_curr = pa_curr->next; + } + + /* Search for page list structures in the range to be offlined */ + pa_last = NULL; + pa_curr = cmm_page_list; + while (pa_curr) { + if (((unsigned long)pa_curr >= start_page) && + ((unsigned long)pa_curr < end_page)) { + npa = (struct cmm_page_array *)__get_free_page( + GFP_NOIO | __GFP_NOWARN | + __GFP_NORETRY | __GFP_NOMEMALLOC); + if (!npa) { + spin_unlock(&cmm_lock); + cmm_dbg("Failed to allocate memory for list " + "management. Memory hotplug " + "failed.\n"); + return ENOMEM; + } + memcpy(npa, pa_curr, PAGE_SIZE); + if (pa_curr == cmm_page_list) + cmm_page_list = npa; + if (pa_last) + pa_last->next = npa; + free_page((unsigned long) pa_curr); + freed++; + pa_curr = npa; + } + + pa_last = pa_curr; + pa_curr = pa_curr->next; + } + + spin_unlock(&cmm_lock); + cmm_dbg("Released %ld pages in the search range.\n", freed); + + return 0; +} + +/** + * cmm_memory_cb - Handle memory hotplug notifier calls + * @self: notifier block struct + * @action: action to take + * @arg: struct memory_notify data for handler + * + * Return value: + * NOTIFY_OK or notifier error based on subfunction return value + * + **/ +static int cmm_memory_cb(struct notifier_block *self, + unsigned long action, void *arg) +{ + int ret = 0; + + switch (action) { + case MEM_GOING_OFFLINE: + mutex_lock(&hotplug_mutex); + hotplug_occurred = 1; + ret = cmm_mem_going_offline(arg); + break; + case MEM_OFFLINE: + case MEM_CANCEL_OFFLINE: + mutex_unlock(&hotplug_mutex); + cmm_dbg("Memory offline operation complete.\n"); + break; + case MEM_GOING_ONLINE: + case MEM_ONLINE: + case MEM_CANCEL_ONLINE: + break; + } + + if (ret) + ret = notifier_from_errno(ret); + else + ret = NOTIFY_OK; + + return ret; +} + +static struct notifier_block cmm_mem_nb = { + .notifier_call = cmm_memory_cb, + .priority = CMM_MEM_HOTPLUG_PRI +}; + +/** * cmm_init - Module initialization * * Return value: @@ -435,18 +669,24 @@ static int cmm_init(void) if ((rc = cmm_sysfs_register(&cmm_sysdev))) goto out_reboot_notifier; + if (register_memory_notifier(&cmm_mem_nb) || + register_memory_isolate_notifier(&cmm_mem_isolate_nb)) + goto out_unregister_notifier; + if (cmm_disabled) return rc; cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); if (IS_ERR(cmm_thread_ptr)) { rc = PTR_ERR(cmm_thread_ptr); - goto out_unregister_sysfs; + goto out_unregister_notifier; } return rc; -out_unregister_sysfs: +out_unregister_notifier: + unregister_memory_notifier(&cmm_mem_nb); + unregister_memory_isolate_notifier(&cmm_mem_isolate_nb); cmm_unregister_sysfs(&cmm_sysdev); out_reboot_notifier: unregister_reboot_notifier(&cmm_reboot_nb); @@ -467,6 +707,8 @@ static void cmm_exit(void) kthread_stop(cmm_thread_ptr); unregister_oom_notifier(&cmm_oom_nb); unregister_reboot_notifier(&cmm_reboot_nb); + unregister_memory_notifier(&cmm_mem_nb); + unregister_memory_isolate_notifier(&cmm_mem_isolate_nb); cmm_free_pages(loaned_pages); cmm_unregister_sysfs(&cmm_sysdev); } diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 12df9e8812a..67b7a10f9fc 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -346,12 +346,14 @@ int dlpar_release_drc(u32 drc_index) static DEFINE_MUTEX(pseries_cpu_hotplug_mutex); -void cpu_hotplug_driver_lock() +void cpu_hotplug_driver_lock(void) +__acquires(pseries_cpu_hotplug_mutex) { mutex_lock(&pseries_cpu_hotplug_mutex); } -void cpu_hotplug_driver_unlock() +void cpu_hotplug_driver_unlock(void) +__releases(pseries_cpu_hotplug_mutex) { mutex_unlock(&pseries_cpu_hotplug_mutex); } diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 8868c012268..b4886635972 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -144,8 +144,8 @@ static void __devinit smp_pSeries_kick_cpu(int nr) hcpuid = get_hard_smp_processor_id(nr); rc = plpar_hcall_norets(H_PROD, hcpuid); if (rc != H_SUCCESS) - panic("Error: Prod to wake up processor %d Ret= %ld\n", - nr, rc); + printk(KERN_ERR "Error: Prod to wake up processor %d\ + Ret= %ld\n", nr, rc); } } diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 971483f0dfa..1709ac5aac7 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -143,13 +143,23 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) struct irq_desc *desc = irq_to_desc(virq); unsigned int vold, vnew, edibit; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - if (flow_type & IRQ_TYPE_EDGE_RISING) { - printk(KERN_ERR "CPM2 PIC: sense type 0x%x not supported\n", - flow_type); - return -EINVAL; + /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or + * IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING + * or IRQ_TYPE_LEVEL_LOW (default) + */ + if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_EDGE_BOTH; + + if (flow_type != IRQ_TYPE_EDGE_BOTH && + flow_type != IRQ_TYPE_EDGE_FALLING) + goto err_sense; + } else { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_LEVEL_LOW; + + if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) + goto err_sense; } desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); @@ -181,6 +191,10 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) if (vold != vnew) out_be32(&cpm2_intctl->ic_siexr, vnew); return 0; + +err_sense: + pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type); + return -EINVAL; } static struct irq_chip cpm2_pic = { diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4e3a3e345ab..e1a028c1f18 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -464,8 +464,7 @@ static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus, { struct pci_controller *hose = pci_bus_to_host(bus); struct mpc83xx_pcie_priv *pcie = hose->dn->data; - u8 bus_no = bus->number - hose->first_busno; - u32 dev_base = bus_no << 24 | devfn << 16; + u32 dev_base = bus->number << 24 | devfn << 16; int ret; ret = mpc83xx_pcie_exclude_device(bus, devfn); @@ -515,12 +514,17 @@ static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn, static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { + struct pci_controller *hose = pci_bus_to_host(bus); void __iomem *cfg_addr; cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset); if (!cfg_addr) return PCIBIOS_DEVICE_NOT_FOUND; + /* PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS */ + if (offset == PCI_PRIMARY_BUS && bus->number == hose->first_busno) + val &= 0xffffff00; + switch (len) { case 1: out_8(cfg_addr, val); diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c index 103eace3619..ee1c0e1cf4a 100644 --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c @@ -54,6 +54,22 @@ static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); } +/* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs + * defined as output cannot be determined by reading GPDAT register, + * so we use shadow data register instead. The status of input pins + * is determined by reading GPDAT register. + */ +static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + u32 val; + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); + struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); + + val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR); + + return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio); +} + static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); @@ -136,7 +152,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np) gc->ngpio = MPC8XXX_GPIO_PINS; gc->direction_input = mpc8xxx_gpio_dir_in; gc->direction_output = mpc8xxx_gpio_dir_out; - gc->get = mpc8xxx_gpio_get; + if (of_device_is_compatible(np, "fsl,mpc8572-gpio")) + gc->get = mpc8572_gpio_get; + else + gc->get = mpc8xxx_gpio_get; gc->set = mpc8xxx_gpio_set; ret = of_mm_gpiochip_add(np, mm_gc); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index aa9d06e5925..470dc6c11d5 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -567,13 +567,11 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) #endif /* CONFIG_MPIC_U3_HT_IRQS */ #ifdef CONFIG_SMP -static int irq_choose_cpu(unsigned int virt_irq) +static int irq_choose_cpu(const cpumask_t *mask) { - cpumask_t mask; int cpuid; - cpumask_copy(&mask, irq_to_desc(virt_irq)->affinity); - if (cpus_equal(mask, CPU_MASK_ALL)) { + if (cpumask_equal(mask, cpu_all_mask)) { static int irq_rover; static DEFINE_SPINLOCK(irq_rover_lock); unsigned long flags; @@ -594,20 +592,15 @@ static int irq_choose_cpu(unsigned int virt_irq) spin_unlock_irqrestore(&irq_rover_lock, flags); } else { - cpumask_t tmp; - - cpus_and(tmp, cpu_online_map, mask); - - if (cpus_empty(tmp)) + cpuid = cpumask_first_and(mask, cpu_online_mask); + if (cpuid >= nr_cpu_ids) goto do_round_robin; - - cpuid = first_cpu(tmp); } return get_hard_smp_processor_id(cpuid); } #else -static int irq_choose_cpu(unsigned int virt_irq) +static int irq_choose_cpu(const cpumask_t *mask) { return hard_smp_processor_id(); } @@ -816,7 +809,7 @@ int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask) unsigned int src = mpic_irq_to_hw(irq); if (mpic->flags & MPIC_SINGLE_DEST_CPU) { - int cpuid = irq_choose_cpu(irq); + int cpuid = irq_choose_cpu(cpumask); mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); } else { diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index 1d44eee80fa..0f67cd79d48 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c @@ -39,7 +39,12 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) pr_debug("mpic: found U3, guessing msi allocator setup\n"); - /* Reserve source numbers we know are reserved in the HW */ + /* Reserve source numbers we know are reserved in the HW. + * + * This is a bit of a mix of U3 and U4 reserves but that's going + * to work fine, we have plenty enugh numbers left so let's just + * mark anything we don't like reserved. + */ for (i = 0; i < 8; i++) msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); @@ -49,6 +54,10 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) for (i = 100; i < 105; i++) msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); + for (i = 124; i < mpic->irq_count; i++) + msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); + + np = NULL; while ((np = of_find_all_nodes(np))) { pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index d3caf23e631..bcbfe79c704 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c @@ -64,12 +64,12 @@ static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos) return addr; } -static u64 find_ht_magic_addr(struct pci_dev *pdev) +static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq) { struct pci_bus *bus; unsigned int pos; - for (bus = pdev->bus; bus; bus = bus->parent) { + for (bus = pdev->bus; bus && bus->self; bus = bus->parent) { pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING); if (pos) return read_ht_magic_addr(bus->self, pos); @@ -78,13 +78,41 @@ static u64 find_ht_magic_addr(struct pci_dev *pdev) return 0; } +static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq) +{ + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + + /* U4 PCIe MSIs need to write to the special register in + * the bridge that generates interrupts. There should be + * theorically a register at 0xf8005000 where you just write + * the MSI number and that triggers the right interrupt, but + * unfortunately, this is busted in HW, the bridge endian swaps + * the value and hits the wrong nibble in the register. + * + * So instead we use another register set which is used normally + * for converting HT interrupts to MPIC interrupts, which decodes + * the interrupt number as part of the low address bits + * + * This will not work if we ever use more than one legacy MSI in + * a block but we never do. For one MSI or multiple MSI-X where + * each interrupt address can be specified separately, it works + * just fine. + */ + if (of_device_is_compatible(hose->dn, "u4-pcie") || + of_device_is_compatible(hose->dn, "U4-pcie")) + return 0xf8004000 | (hwirq << 4); + + return 0; +} + static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type) { if (type == PCI_CAP_ID_MSIX) pr_debug("u3msi: MSI-X untested, trying anyway.\n"); /* If we can't find a magic address then MSI ain't gonna work */ - if (find_ht_magic_addr(pdev) == 0) { + if (find_ht_magic_addr(pdev, 0) == 0 && + find_u4_magic_addr(pdev, 0) == 0) { pr_debug("u3msi: no magic address found for %s\n", pci_name(pdev)); return -ENXIO; @@ -118,10 +146,6 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) u64 addr; int hwirq; - addr = find_ht_magic_addr(pdev); - msg.address_lo = addr & 0xFFFFFFFF; - msg.address_hi = addr >> 32; - list_for_each_entry(entry, &pdev->msi_list, list) { hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); if (hwirq < 0) { @@ -129,6 +153,12 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) return hwirq; } + addr = find_ht_magic_addr(pdev, hwirq); + if (addr == 0) + addr = find_u4_magic_addr(pdev, hwirq); + msg.address_lo = addr & 0xFFFFFFFF; + msg.address_hi = addr >> 32; + virq = irq_create_mapping(msi_mpic->irqhost, hwirq); if (virq == NO_IRQ) { pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); @@ -143,6 +173,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", virq, hwirq, (unsigned long)addr); + printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", + virq, hwirq, (unsigned long)addr); msg.data = hwirq; write_msi_msg(virq, &msg); diff --git a/drivers/base/memory.c b/drivers/base/memory.c index c4c8f2e1dd1..d7d77d4a402 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -63,6 +63,20 @@ void unregister_memory_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(unregister_memory_notifier); +static ATOMIC_NOTIFIER_HEAD(memory_isolate_chain); + +int register_memory_isolate_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&memory_isolate_chain, nb); +} +EXPORT_SYMBOL(register_memory_isolate_notifier); + +void unregister_memory_isolate_notifier(struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&memory_isolate_chain, nb); +} +EXPORT_SYMBOL(unregister_memory_isolate_notifier); + /* * register_memory - Setup a sysfs device for a memory block */ @@ -157,6 +171,11 @@ int memory_notify(unsigned long val, void *v) return blocking_notifier_call_chain(&memory_chain, val, v); } +int memory_isolate_notify(unsigned long val, void *v) +{ + return atomic_notifier_call_chain(&memory_isolate_chain, val, v); +} + /* * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is * OK to have direct references to sparsemem variables in here. diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 1a216c114a0..48adf80926a 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -161,6 +161,32 @@ void device_pm_move_last(struct device *dev) list_move_tail(&dev->power.entry, &dpm_list); } +static ktime_t initcall_debug_start(struct device *dev) +{ + ktime_t calltime = ktime_set(0, 0); + + if (initcall_debug) { + pr_info("calling %s+ @ %i\n", + dev_name(dev), task_pid_nr(current)); + calltime = ktime_get(); + } + + return calltime; +} + +static void initcall_debug_report(struct device *dev, ktime_t calltime, + int error) +{ + ktime_t delta, rettime; + + if (initcall_debug) { + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev), + error, (unsigned long long)ktime_to_ns(delta) >> 10); + } +} + /** * pm_op - Execute the PM operation appropriate for given PM event. * @dev: Device to handle. @@ -172,13 +198,9 @@ static int pm_op(struct device *dev, pm_message_t state) { int error = 0; - ktime_t calltime, delta, rettime; + ktime_t calltime; - if (initcall_debug) { - pr_info("calling %s+ @ %i\n", - dev_name(dev), task_pid_nr(current)); - calltime = ktime_get(); - } + calltime = initcall_debug_start(dev); switch (state.event) { #ifdef CONFIG_SUSPEND @@ -227,12 +249,7 @@ static int pm_op(struct device *dev, error = -EINVAL; } - if (initcall_debug) { - rettime = ktime_get(); - delta = ktime_sub(rettime, calltime); - pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev), - error, (unsigned long long)ktime_to_ns(delta) >> 10); - } + initcall_debug_report(dev, calltime, error); return error; } @@ -309,8 +326,9 @@ static int pm_noirq_op(struct device *dev, if (initcall_debug) { rettime = ktime_get(); delta = ktime_sub(rettime, calltime); - printk("initcall %s_i+ returned %d after %Ld usecs\n", dev_name(dev), - error, (unsigned long long)ktime_to_ns(delta) >> 10); + printk("initcall %s_i+ returned %d after %Ld usecs\n", + dev_name(dev), error, + (unsigned long long)ktime_to_ns(delta) >> 10); } return error; @@ -354,6 +372,23 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info, kobject_name(&dev->kobj), pm_verb(state.event), info, error); } +static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info) +{ + ktime_t calltime; + s64 usecs64; + int usecs; + + calltime = ktime_get(); + usecs64 = ktime_to_ns(ktime_sub(calltime, starttime)); + do_div(usecs64, NSEC_PER_USEC); + usecs = usecs64; + if (usecs == 0) + usecs = 1; + pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n", + info ?: "", info ? " " : "", pm_verb(state.event), + usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC); +} + /*------------------------- Resume routines -------------------------*/ /** @@ -390,6 +425,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) void dpm_resume_noirq(pm_message_t state) { struct device *dev; + ktime_t starttime = ktime_get(); mutex_lock(&dpm_list_mtx); transition_started = false; @@ -403,11 +439,32 @@ void dpm_resume_noirq(pm_message_t state) pm_dev_err(dev, state, " early", error); } mutex_unlock(&dpm_list_mtx); + dpm_show_time(starttime, state, "early"); resume_device_irqs(); } EXPORT_SYMBOL_GPL(dpm_resume_noirq); /** + * legacy_resume - Execute a legacy (bus or class) resume callback for device. + * dev: Device to resume. + * cb: Resume callback to execute. + */ +static int legacy_resume(struct device *dev, int (*cb)(struct device *dev)) +{ + int error; + ktime_t calltime; + + calltime = initcall_debug_start(dev); + + error = cb(dev); + suspend_report_result(cb, error); + + initcall_debug_report(dev, calltime, error); + + return error; +} + +/** * device_resume - Execute "resume" callbacks for given device. * @dev: Device to handle. * @state: PM transition of the system being carried out. @@ -427,7 +484,7 @@ static int device_resume(struct device *dev, pm_message_t state) error = pm_op(dev, dev->bus->pm, state); } else if (dev->bus->resume) { pm_dev_dbg(dev, state, "legacy "); - error = dev->bus->resume(dev); + error = legacy_resume(dev, dev->bus->resume); } if (error) goto End; @@ -448,7 +505,7 @@ static int device_resume(struct device *dev, pm_message_t state) error = pm_op(dev, dev->class->pm, state); } else if (dev->class->resume) { pm_dev_dbg(dev, state, "legacy class "); - error = dev->class->resume(dev); + error = legacy_resume(dev, dev->class->resume); } } End: @@ -468,6 +525,7 @@ static int device_resume(struct device *dev, pm_message_t state) static void dpm_resume(pm_message_t state) { struct list_head list; + ktime_t starttime = ktime_get(); INIT_LIST_HEAD(&list); mutex_lock(&dpm_list_mtx); @@ -496,6 +554,7 @@ static void dpm_resume(pm_message_t state) } list_splice(&list, &dpm_list); mutex_unlock(&dpm_list_mtx); + dpm_show_time(starttime, state, NULL); } /** @@ -548,7 +607,7 @@ static void dpm_complete(pm_message_t state) mutex_unlock(&dpm_list_mtx); device_complete(dev, state); - pm_runtime_put_noidle(dev); + pm_runtime_put_sync(dev); mutex_lock(&dpm_list_mtx); } @@ -628,6 +687,7 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) int dpm_suspend_noirq(pm_message_t state) { struct device *dev; + ktime_t starttime = ktime_get(); int error = 0; suspend_device_irqs(); @@ -643,11 +703,34 @@ int dpm_suspend_noirq(pm_message_t state) mutex_unlock(&dpm_list_mtx); if (error) dpm_resume_noirq(resume_event(state)); + else + dpm_show_time(starttime, state, "late"); return error; } EXPORT_SYMBOL_GPL(dpm_suspend_noirq); /** + * legacy_suspend - Execute a legacy (bus or class) suspend callback for device. + * dev: Device to suspend. + * cb: Suspend callback to execute. + */ +static int legacy_suspend(struct device *dev, pm_message_t state, + int (*cb)(struct device *dev, pm_message_t state)) +{ + int error; + ktime_t calltime; + + calltime = initcall_debug_start(dev); + + error = cb(dev, state); + suspend_report_result(cb, error); + + initcall_debug_report(dev, calltime, error); + + return error; +} + +/** * device_suspend - Execute "suspend" callbacks for given device. * @dev: Device to handle. * @state: PM transition of the system being carried out. @@ -664,8 +747,7 @@ static int device_suspend(struct device *dev, pm_message_t state) error = pm_op(dev, dev->class->pm, state); } else if (dev->class->suspend) { pm_dev_dbg(dev, state, "legacy class "); - error = dev->class->suspend(dev, state); - suspend_report_result(dev->class->suspend, error); + error = legacy_suspend(dev, state, dev->class->suspend); } if (error) goto End; @@ -686,8 +768,7 @@ static int device_suspend(struct device *dev, pm_message_t state) error = pm_op(dev, dev->bus->pm, state); } else if (dev->bus->suspend) { pm_dev_dbg(dev, state, "legacy "); - error = dev->bus->suspend(dev, state); - suspend_report_result(dev->bus->suspend, error); + error = legacy_suspend(dev, state, dev->bus->suspend); } } End: @@ -703,6 +784,7 @@ static int device_suspend(struct device *dev, pm_message_t state) static int dpm_suspend(pm_message_t state) { struct list_head list; + ktime_t starttime = ktime_get(); int error = 0; INIT_LIST_HEAD(&list); @@ -728,6 +810,8 @@ static int dpm_suspend(pm_message_t state) } list_splice(&list, dpm_list.prev); mutex_unlock(&dpm_list_mtx); + if (!error) + dpm_show_time(starttime, state, NULL); return error; } @@ -796,7 +880,7 @@ static int dpm_prepare(pm_message_t state) pm_runtime_get_noresume(dev); if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) { /* Wake-up requested during system sleep transition. */ - pm_runtime_put_noidle(dev); + pm_runtime_put_sync(dev); error = -EBUSY; } else { error = device_prepare(dev, state); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 40d7720a4b2..f8b044e8aef 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -85,6 +85,19 @@ static int __pm_runtime_idle(struct device *dev) dev->bus->pm->runtime_idle(dev); spin_lock_irq(&dev->power.lock); + } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) { + spin_unlock_irq(&dev->power.lock); + + dev->type->pm->runtime_idle(dev); + + spin_lock_irq(&dev->power.lock); + } else if (dev->class && dev->class->pm + && dev->class->pm->runtime_idle) { + spin_unlock_irq(&dev->power.lock); + + dev->class->pm->runtime_idle(dev); + + spin_lock_irq(&dev->power.lock); } dev->power.idle_notification = false; @@ -194,6 +207,22 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) spin_lock_irq(&dev->power.lock); dev->power.runtime_error = retval; + } else if (dev->type && dev->type->pm + && dev->type->pm->runtime_suspend) { + spin_unlock_irq(&dev->power.lock); + + retval = dev->type->pm->runtime_suspend(dev); + + spin_lock_irq(&dev->power.lock); + dev->power.runtime_error = retval; + } else if (dev->class && dev->class->pm + && dev->class->pm->runtime_suspend) { + spin_unlock_irq(&dev->power.lock); + + retval = dev->class->pm->runtime_suspend(dev); + + spin_lock_irq(&dev->power.lock); + dev->power.runtime_error = retval; } else { retval = -ENOSYS; } @@ -359,6 +388,22 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) spin_lock_irq(&dev->power.lock); dev->power.runtime_error = retval; + } else if (dev->type && dev->type->pm + && dev->type->pm->runtime_resume) { + spin_unlock_irq(&dev->power.lock); + + retval = dev->type->pm->runtime_resume(dev); + + spin_lock_irq(&dev->power.lock); + dev->power.runtime_error = retval; + } else if (dev->class && dev->class->pm + && dev->class->pm->runtime_resume) { + spin_unlock_irq(&dev->power.lock); + + retval = dev->class->pm->runtime_resume(dev); + + spin_lock_irq(&dev->power.lock); + dev->power.runtime_error = retval; } else { retval = -ENOSYS; } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4d290599675..a699f09ddf7 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -307,6 +307,7 @@ static void btusb_bulk_complete(struct urb *urb) return; usb_anchor_urb(urb, &data->bulk_anchor); + usb_mark_last_busy(data->udev); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index d3400b20444..7d73cd43034 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -358,7 +358,7 @@ struct port { u8 update_flow_control; struct ctrl_ul ctrl_ul; struct ctrl_dl ctrl_dl; - struct kfifo *fifo_ul; + struct kfifo fifo_ul; void __iomem *dl_addr[2]; u32 dl_size[2]; u8 toggle_dl; @@ -685,8 +685,6 @@ static int nozomi_read_config_table(struct nozomi *dc) dump_table(dc); for (i = PORT_MDM; i < MAX_PORT; i++) { - dc->port[i].fifo_ul = - kfifo_alloc(FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL); memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl)); memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul)); } @@ -798,7 +796,7 @@ static int send_data(enum port_type index, struct nozomi *dc) struct tty_struct *tty = tty_port_tty_get(&port->port); /* Get data from tty and place in buf for now */ - size = __kfifo_get(port->fifo_ul, dc->send_buf, + size = kfifo_out(&port->fifo_ul, dc->send_buf, ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX); if (size == 0) { @@ -988,11 +986,11 @@ static int receive_flow_control(struct nozomi *dc) } else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) { - if (__kfifo_len(dc->port[port].fifo_ul)) { + if (kfifo_len(&dc->port[port].fifo_ul)) { DBG1("Enable interrupt (0x%04X) on port: %d", enable_ier, port); DBG1("Data in buffer [%d], enable transmit! ", - __kfifo_len(dc->port[port].fifo_ul)); + kfifo_len(&dc->port[port].fifo_ul)); enable_transmit_ul(port, dc); } else { DBG1("No data in buffer..."); @@ -1433,6 +1431,16 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, goto err_free_sbuf; } + for (i = PORT_MDM; i < MAX_PORT; i++) { + if (kfifo_alloc(&dc->port[i].fifo_ul, + FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) { + dev_err(&pdev->dev, + "Could not allocate kfifo buffer\n"); + ret = -ENOMEM; + goto err_free_kfifo; + } + } + spin_lock_init(&dc->spin_mutex); nozomi_setup_private_data(dc); @@ -1445,7 +1453,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, NOZOMI_NAME, dc); if (unlikely(ret)) { dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq); - goto err_free_sbuf; + goto err_free_kfifo; } DBG1("base_addr: %p", dc->base_addr); @@ -1464,13 +1472,28 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, dc->state = NOZOMI_STATE_ENABLED; for (i = 0; i < MAX_PORT; i++) { + struct device *tty_dev; + mutex_init(&dc->port[i].tty_sem); tty_port_init(&dc->port[i].port); - tty_register_device(ntty_driver, dc->index_start + i, + tty_dev = tty_register_device(ntty_driver, dc->index_start + i, &pdev->dev); + + if (IS_ERR(tty_dev)) { + ret = PTR_ERR(tty_dev); + dev_err(&pdev->dev, "Could not allocate tty?\n"); + goto err_free_tty; + } } + return 0; +err_free_tty: + for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) + tty_unregister_device(ntty_driver, i); +err_free_kfifo: + for (i = 0; i < MAX_PORT; i++) + kfifo_free(&dc->port[i].fifo_ul); err_free_sbuf: kfree(dc->send_buf); iounmap(dc->base_addr); @@ -1536,8 +1559,7 @@ static void __devexit nozomi_card_exit(struct pci_dev *pdev) free_irq(pdev->irq, dc); for (i = 0; i < MAX_PORT; i++) - if (dc->port[i].fifo_ul) - kfifo_free(dc->port[i].fifo_ul); + kfifo_free(&dc->port[i].fifo_ul); kfree(dc->send_buf); @@ -1673,7 +1695,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, goto exit; } - rval = __kfifo_put(port->fifo_ul, (unsigned char *)buffer, count); + rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); /* notify card */ if (unlikely(dc == NULL)) { @@ -1721,7 +1743,7 @@ static int ntty_write_room(struct tty_struct *tty) if (!port->port.count) goto exit; - room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); + room = port->fifo_ul.size - kfifo_len(&port->fifo_ul); exit: mutex_unlock(&port->tty_sem); @@ -1878,7 +1900,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) goto exit_in_buffer; } - rval = __kfifo_len(port->fifo_ul); + rval = kfifo_len(&port->fifo_ul); exit_in_buffer: return rval; diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 8c262aaf7c2..0798754a607 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -487,7 +487,7 @@ static struct sonypi_device { int camera_power; int bluetooth_power; struct mutex lock; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; wait_queue_head_t fifo_proc_list; struct fasync_struct *fifo_async; @@ -496,7 +496,7 @@ static struct sonypi_device { struct input_dev *input_jog_dev; struct input_dev *input_key_dev; struct work_struct input_work; - struct kfifo *input_fifo; + struct kfifo input_fifo; spinlock_t input_fifo_lock; } sonypi_device; @@ -777,8 +777,9 @@ static void input_keyrelease(struct work_struct *work) { struct sonypi_keypress kp; - while (kfifo_get(sonypi_device.input_fifo, (unsigned char *)&kp, - sizeof(kp)) == sizeof(kp)) { + while (kfifo_out_locked(&sonypi_device.input_fifo, (unsigned char *)&kp, + sizeof(kp), &sonypi_device.input_fifo_lock) + == sizeof(kp)) { msleep(10); input_report_key(kp.dev, kp.key, 0); input_sync(kp.dev); @@ -827,8 +828,9 @@ static void sonypi_report_input_event(u8 event) if (kp.dev) { input_report_key(kp.dev, kp.key, 1); input_sync(kp.dev); - kfifo_put(sonypi_device.input_fifo, - (unsigned char *)&kp, sizeof(kp)); + kfifo_in_locked(&sonypi_device.input_fifo, + (unsigned char *)&kp, sizeof(kp), + &sonypi_device.input_fifo_lock); schedule_work(&sonypi_device.input_work); } } @@ -880,7 +882,8 @@ found: acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event); #endif - kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); + kfifo_in_locked(&sonypi_device.fifo, (unsigned char *)&event, + sizeof(event), &sonypi_device.fifo_lock); kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_device.fifo_proc_list); @@ -906,7 +909,7 @@ static int sonypi_misc_open(struct inode *inode, struct file *file) mutex_lock(&sonypi_device.lock); /* Flush input queue on first open */ if (!sonypi_device.open_count) - kfifo_reset(sonypi_device.fifo); + kfifo_reset(&sonypi_device.fifo); sonypi_device.open_count++; mutex_unlock(&sonypi_device.lock); unlock_kernel(); @@ -919,17 +922,18 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, ssize_t ret; unsigned char c; - if ((kfifo_len(sonypi_device.fifo) == 0) && + if ((kfifo_len(&sonypi_device.fifo) == 0) && (file->f_flags & O_NONBLOCK)) return -EAGAIN; ret = wait_event_interruptible(sonypi_device.fifo_proc_list, - kfifo_len(sonypi_device.fifo) != 0); + kfifo_len(&sonypi_device.fifo) != 0); if (ret) return ret; while (ret < count && - (kfifo_get(sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) { + (kfifo_out_locked(&sonypi_device.fifo, &c, sizeof(c), + &sonypi_device.fifo_lock) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; ret++; @@ -946,7 +950,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) { poll_wait(file, &sonypi_device.fifo_proc_list, wait); - if (kfifo_len(sonypi_device.fifo)) + if (kfifo_len(&sonypi_device.fifo)) return POLLIN | POLLRDNORM; return 0; } @@ -1313,11 +1317,10 @@ static int __devinit sonypi_probe(struct platform_device *dev) "http://www.linux.it/~malattia/wiki/index.php/Sony_drivers\n"); spin_lock_init(&sonypi_device.fifo_lock); - sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, - &sonypi_device.fifo_lock); - if (IS_ERR(sonypi_device.fifo)) { + error = kfifo_alloc(&sonypi_device.fifo, SONYPI_BUF_SIZE, GFP_KERNEL); + if (error) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); - return PTR_ERR(sonypi_device.fifo); + return error; } init_waitqueue_head(&sonypi_device.fifo_proc_list); @@ -1393,12 +1396,10 @@ static int __devinit sonypi_probe(struct platform_device *dev) } spin_lock_init(&sonypi_device.input_fifo_lock); - sonypi_device.input_fifo = - kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, - &sonypi_device.input_fifo_lock); - if (IS_ERR(sonypi_device.input_fifo)) { + error = kfifo_alloc(&sonypi_device.input_fifo, SONYPI_BUF_SIZE, + GFP_KERNEL); + if (error) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); - error = PTR_ERR(sonypi_device.input_fifo); goto err_inpdev_unregister; } @@ -1423,7 +1424,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) pci_disable_device(pcidev); err_put_pcidev: pci_dev_put(pcidev); - kfifo_free(sonypi_device.fifo); + kfifo_free(&sonypi_device.fifo); return error; } @@ -1438,7 +1439,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) if (useinput) { input_unregister_device(sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_jog_dev); - kfifo_free(sonypi_device.input_fifo); + kfifo_free(&sonypi_device.input_fifo); } misc_deregister(&sonypi_misc_device); @@ -1451,7 +1452,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) pci_dev_put(sonypi_device.dev); } - kfifo_free(sonypi_device.fifo); + kfifo_free(&sonypi_device.fifo); return 0; } diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index bfd03bf8be5..f3d440cc68f 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h @@ -34,6 +34,7 @@ #include <linux/list.h> #include <linux/mutex.h> +#include <linux/kfifo.h> #include "t3_cpl.h" #include "t3cdev.h" @@ -75,13 +76,13 @@ struct cxio_hal_ctrl_qp { }; struct cxio_hal_resource { - struct kfifo *tpt_fifo; + struct kfifo tpt_fifo; spinlock_t tpt_fifo_lock; - struct kfifo *qpid_fifo; + struct kfifo qpid_fifo; spinlock_t qpid_fifo_lock; - struct kfifo *cqid_fifo; + struct kfifo cqid_fifo; spinlock_t cqid_fifo_lock; - struct kfifo *pdid_fifo; + struct kfifo pdid_fifo; spinlock_t pdid_fifo_lock; }; diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c index bd233c08765..31f9201b298 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_resource.c +++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c @@ -39,12 +39,12 @@ #include "cxio_resource.h" #include "cxio_hal.h" -static struct kfifo *rhdl_fifo; +static struct kfifo rhdl_fifo; static spinlock_t rhdl_fifo_lock; #define RANDOM_SIZE 16 -static int __cxio_init_resource_fifo(struct kfifo **fifo, +static int __cxio_init_resource_fifo(struct kfifo *fifo, spinlock_t *fifo_lock, u32 nr, u32 skip_low, u32 skip_high, @@ -55,12 +55,11 @@ static int __cxio_init_resource_fifo(struct kfifo **fifo, u32 rarray[16]; spin_lock_init(fifo_lock); - *fifo = kfifo_alloc(nr * sizeof(u32), GFP_KERNEL, fifo_lock); - if (IS_ERR(*fifo)) + if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL)) return -ENOMEM; for (i = 0; i < skip_low + skip_high; i++) - __kfifo_put(*fifo, (unsigned char *) &entry, sizeof(u32)); + kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32)); if (random) { j = 0; random_bytes = random32(); @@ -72,33 +71,35 @@ static int __cxio_init_resource_fifo(struct kfifo **fifo, random_bytes = random32(); } idx = (random_bytes >> (j * 2)) & 0xF; - __kfifo_put(*fifo, + kfifo_in(fifo, (unsigned char *) &rarray[idx], sizeof(u32)); rarray[idx] = i; j++; } for (i = 0; i < RANDOM_SIZE; i++) - __kfifo_put(*fifo, + kfifo_in(fifo, (unsigned char *) &rarray[i], sizeof(u32)); } else for (i = skip_low; i < nr - skip_high; i++) - __kfifo_put(*fifo, (unsigned char *) &i, sizeof(u32)); + kfifo_in(fifo, (unsigned char *) &i, sizeof(u32)); for (i = 0; i < skip_low + skip_high; i++) - kfifo_get(*fifo, (unsigned char *) &entry, sizeof(u32)); + if (kfifo_out_locked(fifo, (unsigned char *) &entry, + sizeof(u32), fifo_lock) != sizeof(u32)) + break; return 0; } -static int cxio_init_resource_fifo(struct kfifo **fifo, spinlock_t * fifo_lock, +static int cxio_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock, u32 nr, u32 skip_low, u32 skip_high) { return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low, skip_high, 0)); } -static int cxio_init_resource_fifo_random(struct kfifo **fifo, +static int cxio_init_resource_fifo_random(struct kfifo *fifo, spinlock_t * fifo_lock, u32 nr, u32 skip_low, u32 skip_high) { @@ -113,15 +114,13 @@ static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p) spin_lock_init(&rdev_p->rscp->qpid_fifo_lock); - rdev_p->rscp->qpid_fifo = kfifo_alloc(T3_MAX_NUM_QP * sizeof(u32), - GFP_KERNEL, - &rdev_p->rscp->qpid_fifo_lock); - if (IS_ERR(rdev_p->rscp->qpid_fifo)) + if (kfifo_alloc(&rdev_p->rscp->qpid_fifo, T3_MAX_NUM_QP * sizeof(u32), + GFP_KERNEL)) return -ENOMEM; for (i = 16; i < T3_MAX_NUM_QP; i++) if (!(i & rdev_p->qpmask)) - __kfifo_put(rdev_p->rscp->qpid_fifo, + kfifo_in(&rdev_p->rscp->qpid_fifo, (unsigned char *) &i, sizeof(u32)); return 0; } @@ -134,7 +133,7 @@ int cxio_hal_init_rhdl_resource(u32 nr_rhdl) void cxio_hal_destroy_rhdl_resource(void) { - kfifo_free(rhdl_fifo); + kfifo_free(&rhdl_fifo); } /* nr_* must be power of 2 */ @@ -167,11 +166,11 @@ int cxio_hal_init_resource(struct cxio_rdev *rdev_p, goto pdid_err; return 0; pdid_err: - kfifo_free(rscp->cqid_fifo); + kfifo_free(&rscp->cqid_fifo); cqid_err: - kfifo_free(rscp->qpid_fifo); + kfifo_free(&rscp->qpid_fifo); qpid_err: - kfifo_free(rscp->tpt_fifo); + kfifo_free(&rscp->tpt_fifo); tpt_err: return -ENOMEM; } @@ -179,33 +178,37 @@ tpt_err: /* * returns 0 if no resource available */ -static u32 cxio_hal_get_resource(struct kfifo *fifo) +static u32 cxio_hal_get_resource(struct kfifo *fifo, spinlock_t * lock) { u32 entry; - if (kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32))) + if (kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock)) return entry; else return 0; /* fifo emptry */ } -static void cxio_hal_put_resource(struct kfifo *fifo, u32 entry) +static void cxio_hal_put_resource(struct kfifo *fifo, spinlock_t * lock, + u32 entry) { - BUG_ON(kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)) == 0); + BUG_ON( + kfifo_in_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock) + == 0); } u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(rscp->tpt_fifo); + return cxio_hal_get_resource(&rscp->tpt_fifo, &rscp->tpt_fifo_lock); } void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag) { - cxio_hal_put_resource(rscp->tpt_fifo, stag); + cxio_hal_put_resource(&rscp->tpt_fifo, &rscp->tpt_fifo_lock, stag); } u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) { - u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo); + u32 qpid = cxio_hal_get_resource(&rscp->qpid_fifo, + &rscp->qpid_fifo_lock); PDBG("%s qpid 0x%x\n", __func__, qpid); return qpid; } @@ -213,35 +216,35 @@ u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid) { PDBG("%s qpid 0x%x\n", __func__, qpid); - cxio_hal_put_resource(rscp->qpid_fifo, qpid); + cxio_hal_put_resource(&rscp->qpid_fifo, &rscp->qpid_fifo_lock, qpid); } u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(rscp->cqid_fifo); + return cxio_hal_get_resource(&rscp->cqid_fifo, &rscp->cqid_fifo_lock); } void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid) { - cxio_hal_put_resource(rscp->cqid_fifo, cqid); + cxio_hal_put_resource(&rscp->cqid_fifo, &rscp->cqid_fifo_lock, cqid); } u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(rscp->pdid_fifo); + return cxio_hal_get_resource(&rscp->pdid_fifo, &rscp->pdid_fifo_lock); } void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid) { - cxio_hal_put_resource(rscp->pdid_fifo, pdid); + cxio_hal_put_resource(&rscp->pdid_fifo, &rscp->pdid_fifo_lock, pdid); } void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp) { - kfifo_free(rscp->tpt_fifo); - kfifo_free(rscp->cqid_fifo); - kfifo_free(rscp->qpid_fifo); - kfifo_free(rscp->pdid_fifo); + kfifo_free(&rscp->tpt_fifo); + kfifo_free(&rscp->cqid_fifo); + kfifo_free(&rscp->qpid_fifo); + kfifo_free(&rscp->pdid_fifo); kfree(rscp); } diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 7e5f30dbc0a..f1e8af54dff 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -661,7 +661,7 @@ l1oip_socket_thread(void *data) size_t recvbuf_size = 1500; int recvlen; struct socket *socket = NULL; - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); /* allocate buffer memory */ recvbuf = kmalloc(recvbuf_size, GFP_KERNEL); diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index 3ccc8afeccf..2bf57a4527d 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -124,15 +124,12 @@ struct cx23888_ir_state { atomic_t rxclk_divider; atomic_t rx_invert; - struct kfifo *rx_kfifo; + struct kfifo rx_kfifo; spinlock_t rx_kfifo_lock; struct v4l2_subdev_ir_parameters tx_params; struct mutex tx_params_lock; atomic_t txclk_divider; - - struct kfifo *tx_kfifo; - spinlock_t tx_kfifo_lock; }; static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) @@ -522,6 +519,7 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, { struct cx23888_ir_state *state = to_state(sd); struct cx23885_dev *dev = state->dev; + unsigned long flags; u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); @@ -594,8 +592,9 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, if (i == 0) break; j = i * sizeof(u32); - k = kfifo_put(state->rx_kfifo, - (unsigned char *) rx_data, j); + k = kfifo_in_locked(&state->rx_kfifo, + (unsigned char *) rx_data, j, + &state->rx_kfifo_lock); if (k != j) kror++; /* rx_kfifo over run */ } @@ -631,8 +630,11 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl); *handled = true; } - if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) + + spin_lock_irqsave(&state->rx_kfifo_lock, flags); + if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; + spin_unlock_irqrestore(&state->rx_kfifo_lock, flags); if (events) v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events); @@ -657,7 +659,7 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, return 0; } - n = kfifo_get(state->rx_kfifo, buf, n); + n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock); n /= sizeof(u32); *num = n * sizeof(u32); @@ -785,7 +787,12 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, o->interrupt_enable = p->interrupt_enable; o->enable = p->enable; if (p->enable) { - kfifo_reset(state->rx_kfifo); + unsigned long flags; + + spin_lock_irqsave(&state->rx_kfifo_lock, flags); + kfifo_reset(&state->rx_kfifo); + /* reset tx_fifo too if there is one... */ + spin_unlock_irqrestore(&state->rx_kfifo_lock, flags); if (p->interrupt_enable) irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE); control_rx_enable(dev, p->enable); @@ -892,7 +899,6 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, o->interrupt_enable = p->interrupt_enable; o->enable = p->enable; if (p->enable) { - kfifo_reset(state->tx_kfifo); if (p->interrupt_enable) irqenable_tx(dev, IRQEN_TSE); control_tx_enable(dev, p->enable); @@ -1168,18 +1174,8 @@ int cx23888_ir_probe(struct cx23885_dev *dev) return -ENOMEM; spin_lock_init(&state->rx_kfifo_lock); - state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL, - &state->rx_kfifo_lock); - if (state->rx_kfifo == NULL) - return -ENOMEM; - - spin_lock_init(&state->tx_kfifo_lock); - state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL, - &state->tx_kfifo_lock); - if (state->tx_kfifo == NULL) { - kfifo_free(state->rx_kfifo); + if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL)) return -ENOMEM; - } state->dev = dev; state->id = V4L2_IDENT_CX23888_IR; @@ -1211,8 +1207,7 @@ int cx23888_ir_probe(struct cx23885_dev *dev) sizeof(struct v4l2_subdev_ir_parameters)); v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params); } else { - kfifo_free(state->rx_kfifo); - kfifo_free(state->tx_kfifo); + kfifo_free(&state->rx_kfifo); } return ret; } @@ -1231,8 +1226,7 @@ int cx23888_ir_remove(struct cx23885_dev *dev) state = to_state(sd); v4l2_device_unregister_subdev(sd); - kfifo_free(state->rx_kfifo); - kfifo_free(state->tx_kfifo); + kfifo_free(&state->rx_kfifo); kfree(state); /* Nothing more to free() as state held the actual v4l2_subdev object */ return 0; diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 6ffa64cd1c6..b421858ccf9 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -800,8 +800,8 @@ again: return IRQ_HANDLED; if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { - if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, - sizeof(int)) != sizeof(int)) { + if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr, + sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); return IRQ_HANDLED; } @@ -811,7 +811,8 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } else { int size; @@ -820,8 +821,8 @@ again: mchip_free_frame(); goto again; } - if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, - sizeof(int)) != sizeof(int)) { + if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr, + sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); goto again; } @@ -831,7 +832,8 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } mchip_free_frame(); @@ -859,8 +861,8 @@ static int meye_open(struct file *file) for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; - kfifo_reset(meye.grabq); - kfifo_reset(meye.doneq); + kfifo_reset(&meye.grabq); + kfifo_reset(&meye.doneq); return 0; } @@ -933,7 +935,8 @@ static int meyeioc_qbuf_capt(int *nb) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); + kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int), + &meye.grabq_lock); mutex_unlock(&meye.lock); return 0; @@ -965,7 +968,9 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); + if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, + sizeof(int), &meye.doneq_lock) != sizeof(int)) + break; } *i = meye.grab_buffer[*i].size; mutex_unlock(&meye.lock); @@ -1452,7 +1457,8 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); + kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index, + sizeof(int), &meye.grabq_lock); mutex_unlock(&meye.lock); return 0; @@ -1467,19 +1473,19 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) mutex_lock(&meye.lock); - if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { + if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, - kfifo_len(meye.doneq) != 0) < 0) { + kfifo_len(&meye.doneq) != 0) < 0) { mutex_unlock(&meye.lock); return -EINTR; } - if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, - sizeof(int))) { + if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock)) { mutex_unlock(&meye.lock); return -EBUSY; } @@ -1529,8 +1535,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) { mutex_lock(&meye.lock); mchip_hic_stop(); - kfifo_reset(meye.grabq); - kfifo_reset(meye.doneq); + kfifo_reset(&meye.grabq); + kfifo_reset(&meye.doneq); for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; @@ -1572,7 +1578,7 @@ static unsigned int meye_poll(struct file *file, poll_table *wait) mutex_lock(&meye.lock); poll_wait(file, &meye.proc_list, wait); - if (kfifo_len(meye.doneq)) + if (kfifo_len(&meye.doneq)) res = POLLIN | POLLRDNORM; mutex_unlock(&meye.lock); return res; @@ -1745,16 +1751,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, } spin_lock_init(&meye.grabq_lock); - meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.grabq_lock); - if (IS_ERR(meye.grabq)) { + if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, + GFP_KERNEL)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc1; } spin_lock_init(&meye.doneq_lock); - meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.doneq_lock); - if (IS_ERR(meye.doneq)) { + if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, + GFP_KERNEL)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc2; } @@ -1868,9 +1872,9 @@ outregions: outenabledev: sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); outsonypienable: - kfifo_free(meye.doneq); + kfifo_free(&meye.doneq); outkfifoalloc2: - kfifo_free(meye.grabq); + kfifo_free(&meye.grabq); outkfifoalloc1: vfree(meye.grab_temp); outvmalloc: @@ -1901,8 +1905,8 @@ static void __devexit meye_remove(struct pci_dev *pcidev) sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); - kfifo_free(meye.doneq); - kfifo_free(meye.grabq); + kfifo_free(&meye.doneq); + kfifo_free(&meye.grabq); vfree(meye.grab_temp); diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 5f70a106ba2..1321ad5d659 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -303,9 +303,9 @@ struct meye { struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ struct mutex lock; /* mutex for open/mmap... */ - struct kfifo *grabq; /* queue for buffers to be grabbed */ + struct kfifo grabq; /* queue for buffers to be grabbed */ spinlock_t grabq_lock; /* lock protecting the queue */ - struct kfifo *doneq; /* queue for grabbed buffers */ + struct kfifo doneq; /* queue for grabbed buffers */ spinlock_t doneq_lock; /* lock protecting the queue */ wait_queue_head_t proc_list; /* wait queue */ struct video_device *video_dev; /* video device parameters */ diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 4bfc8081292..65df1de447e 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -653,12 +653,20 @@ static void bnx2_netif_stop(struct bnx2 *bp) { bnx2_cnic_stop(bp); - bnx2_disable_int_sync(bp); if (netif_running(bp->dev)) { + int i; + bnx2_napi_disable(bp); netif_tx_disable(bp->dev); - bp->dev->trans_start = jiffies; /* prevent tx timeout */ + /* prevent tx timeout */ + for (i = 0; i < bp->dev->num_tx_queues; i++) { + struct netdev_queue *txq; + + txq = netdev_get_tx_queue(bp->dev, i); + txq->trans_start = jiffies; + } } + bnx2_disable_int_sync(bp); } static void diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index d0ec17878ff..166cc7e579c 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1037,7 +1037,7 @@ static int __init at91_can_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!res || !irq) { + if (!res || irq <= 0) { err = -ENODEV; goto exit_put; } diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 8edac8915ea..34e03104c3c 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -2272,7 +2272,7 @@ static int emac_mii_reset(struct mii_bus *bus) unsigned int clk_div; int mdio_bus_freq = emac_bus_frequency; - if (mdio_max_freq & mdio_bus_freq) + if (mdio_max_freq && mdio_bus_freq) clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); else clk_div = 0xFF; diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 929701ca07d..839fb2b136d 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1829,6 +1829,7 @@ static int e100_alloc_cbs(struct nic *nic) &nic->cbs_dma_addr); if (!nic->cbs) return -ENOMEM; + memset(nic->cbs, 0, count * sizeof(struct cb)); for (cb = nic->cbs, i = 0; i < count; cb++, i++) { cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; @@ -1837,7 +1838,6 @@ static int e100_alloc_cbs(struct nic *nic) cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); cb->link = cpu_to_le32(nic->cbs_dma_addr + ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; } nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index c1a42cfc80b..b979464091b 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1290,7 +1290,6 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw) static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) { u32 ctrl; - u32 led_ctrl; s32 ret_val; ctrl = er32(CTRL); @@ -1305,11 +1304,6 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) break; case e1000_phy_igp_2: ret_val = e1000e_copper_link_setup_igp(hw); - /* Setup activity LED */ - led_ctrl = er32(LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - ew32(LEDCTL, led_ctrl); break; default: return -E1000_ERR_PHY; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 6850dc0a7b9..e0620d08464 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -357,8 +357,11 @@ static void gfar_init_mac(struct net_device *ndev) /* Configure the coalescing support */ gfar_configure_coalescing(priv, 0xFF, 0xFF); - if (priv->rx_filer_enable) + if (priv->rx_filer_enable) { rctrl |= RCTRL_FILREN; + /* Program the RIR0 reg with the required distribution */ + gfar_write(®s->rir0, DEFAULT_RIR0); + } if (priv->rx_csum_enable) rctrl |= RCTRL_CHECKSUMMING; @@ -414,6 +417,36 @@ static void gfar_init_mac(struct net_device *ndev) gfar_write(®s->fifo_tx_starve_shutoff, priv->fifo_starve_off); } +static struct net_device_stats *gfar_get_stats(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + struct netdev_queue *txq; + unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0; + unsigned long tx_packets = 0, tx_bytes = 0; + int i = 0; + + for (i = 0; i < priv->num_rx_queues; i++) { + rx_packets += priv->rx_queue[i]->stats.rx_packets; + rx_bytes += priv->rx_queue[i]->stats.rx_bytes; + rx_dropped += priv->rx_queue[i]->stats.rx_dropped; + } + + dev->stats.rx_packets = rx_packets; + dev->stats.rx_bytes = rx_bytes; + dev->stats.rx_dropped = rx_dropped; + + for (i = 0; i < priv->num_tx_queues; i++) { + txq = netdev_get_tx_queue(dev, i); + tx_bytes += txq->tx_bytes; + tx_packets += txq->tx_packets; + } + + dev->stats.tx_bytes = tx_bytes; + dev->stats.tx_packets = tx_packets; + + return &dev->stats; +} + static const struct net_device_ops gfar_netdev_ops = { .ndo_open = gfar_enet_open, .ndo_start_xmit = gfar_start_xmit, @@ -423,6 +456,7 @@ static const struct net_device_ops gfar_netdev_ops = { .ndo_tx_timeout = gfar_timeout, .ndo_do_ioctl = gfar_ioctl, .ndo_select_queue = gfar_select_queue, + .ndo_get_stats = gfar_get_stats, .ndo_vlan_rx_register = gfar_vlan_rx_register, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -1022,6 +1056,9 @@ static int gfar_probe(struct of_device *ofdev, priv->rx_queue[i]->rxic = DEFAULT_RXIC; } + /* enable filer if using multiple RX queues*/ + if(priv->num_rx_queues > 1) + priv->rx_filer_enable = 1; /* Enable most messages by default */ priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; @@ -1937,7 +1974,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* Update transmit stats */ - dev->stats.tx_bytes += skb->len; + txq->tx_bytes += skb->len; + txq->tx_packets ++; txbdp = txbdp_start = tx_queue->cur_tx; @@ -2295,8 +2333,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) tx_queue->skb_dirtytx = skb_dirtytx; tx_queue->dirty_tx = bdp; - dev->stats.tx_packets += howmany; - return howmany; } @@ -2510,14 +2546,14 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) } } else { /* Increment the number of packets */ - dev->stats.rx_packets++; + rx_queue->stats.rx_packets++; howmany++; if (likely(skb)) { pkt_len = bdp->length - ETH_FCS_LEN; /* Remove the FCS from the packet length */ skb_put(skb, pkt_len); - dev->stats.rx_bytes += pkt_len; + rx_queue->stats.rx_bytes += pkt_len; gfar_process_frame(dev, skb, amount_pull); @@ -2525,7 +2561,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) if (netif_msg_rx_err(priv)) printk(KERN_WARNING "%s: Missing skb!\n", dev->name); - dev->stats.rx_dropped++; + rx_queue->stats.rx_dropped++; priv->extra_stats.rx_skbmissing++; } diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index cbb451011cb..3d72dc43dca 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -333,7 +333,7 @@ extern const char gfar_driver_version[]; #define IMASK_BSY 0x20000000 #define IMASK_EBERR 0x10000000 #define IMASK_MSRO 0x04000000 -#define IMASK_GRSC 0x02000000 +#define IMASK_GTSC 0x02000000 #define IMASK_BABT 0x01000000 #define IMASK_TXC 0x00800000 #define IMASK_TXEEN 0x00400000 @@ -344,7 +344,7 @@ extern const char gfar_driver_version[]; #define IMASK_XFUN 0x00010000 #define IMASK_RXB0 0x00008000 #define IMASK_MAG 0x00000800 -#define IMASK_GTSC 0x00000100 +#define IMASK_GRSC 0x00000100 #define IMASK_RXFEN0 0x00000080 #define IMASK_FIR 0x00000008 #define IMASK_FIQ 0x00000004 @@ -401,6 +401,10 @@ extern const char gfar_driver_version[]; #define FPR_FILER_MASK 0xFFFFFFFF #define MAX_FILER_IDX 0xFF +/* This default RIR value directly corresponds + * to the 3-bit hash value generated */ +#define DEFAULT_RIR0 0x05397700 + /* RQFCR register bits */ #define RQFCR_GPI 0x80000000 #define RQFCR_HASHTBL_Q 0x00000000 @@ -936,6 +940,15 @@ struct gfar_priv_tx_q { unsigned short txtime; }; +/* + * Per RX queue stats + */ +struct rx_q_stats { + unsigned long rx_packets; + unsigned long rx_bytes; + unsigned long rx_dropped; +}; + /** * struct gfar_priv_rx_q - per rx queue structure * @rxlock: per queue rx spin lock @@ -958,6 +971,7 @@ struct gfar_priv_rx_q { struct rxbd8 *cur_rx; struct net_device *dev; struct gfar_priv_grp *grp; + struct rx_q_stats stats; u16 skb_currx; u16 qindex; unsigned int rx_ring_size; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f4996846a23..6cae26a5bd6 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -57,7 +57,9 @@ static int use_msi = 1; static int use_msi_x = 1; -static unsigned long auto_fw_reset = AUTO_FW_RESET_ENABLED; +static int auto_fw_reset = AUTO_FW_RESET_ENABLED; +module_param(auto_fw_reset, int, 0644); +MODULE_PARM_DESC(auto_fw_reset,"Auto firmware reset (0=disabled, 1=enabled"); static int __devinit netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -2534,42 +2536,6 @@ static struct bin_attribute bin_attr_mem = { .write = netxen_sysfs_write_mem, }; -#ifdef CONFIG_MODULES -static ssize_t -netxen_store_auto_fw_reset(struct module_attribute *mattr, - struct module *mod, const char *buf, size_t count) - -{ - unsigned long new; - - if (strict_strtoul(buf, 16, &new)) - return -EINVAL; - - if ((new == AUTO_FW_RESET_ENABLED) || (new == AUTO_FW_RESET_DISABLED)) { - auto_fw_reset = new; - return count; - } - - return -EINVAL; -} - -static ssize_t -netxen_show_auto_fw_reset(struct module_attribute *mattr, - struct module *mod, char *buf) - -{ - if (auto_fw_reset == AUTO_FW_RESET_ENABLED) - return sprintf(buf, "enabled\n"); - else - return sprintf(buf, "disabled\n"); -} - -static struct module_attribute mod_attr_fw_reset = { - .attr = {.name = "auto_fw_reset", .mode = (S_IRUGO | S_IWUSR)}, - .show = netxen_show_auto_fw_reset, - .store = netxen_store_auto_fw_reset, -}; -#endif static void netxen_create_sysfs_entries(struct netxen_adapter *adapter) @@ -2775,23 +2741,12 @@ static struct pci_driver netxen_driver = { static int __init netxen_init_module(void) { -#ifdef CONFIG_MODULES - struct module *mod = THIS_MODULE; -#endif - printk(KERN_INFO "%s\n", netxen_nic_driver_string); #ifdef CONFIG_INET register_netdevice_notifier(&netxen_netdev_cb); register_inetaddr_notifier(&netxen_inetaddr_cb); #endif - -#ifdef CONFIG_MODULES - if (sysfs_create_file(&mod->mkobj.kobj, &mod_attr_fw_reset.attr)) - printk(KERN_ERR "%s: Failed to create auto_fw_reset " - "sysfs entry.", netxen_nic_driver_name); -#endif - return pci_register_driver(&netxen_driver); } @@ -2799,12 +2754,6 @@ module_init(netxen_init_module); static void __exit netxen_exit_module(void) { -#ifdef CONFIG_MODULES - struct module *mod = THIS_MODULE; - - sysfs_remove_file(&mod->mkobj.kobj, &mod_attr_fw_reset.attr); -#endif - pci_unregister_driver(&netxen_driver); #ifdef CONFIG_INET diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index f63c96a4ecb..c13cf64095b 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -326,7 +326,8 @@ error: static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) { - u32 val, orig; + u32 orig; + int val; bool clk125en = true; /* Abort if we are using an untested phy. */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index b9b371bfa30..42611bea76a 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1365,7 +1365,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) priv->dnld_sent = DNLD_RES_RECEIVED; /* If nothing to do, go back to sleep (?) */ - if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) + if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) priv->psstate = PS_STATE_SLEEP; spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -1439,7 +1439,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) } /* Pending events or command responses? */ - if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { + if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) { allowed = 0; lbs_deb_host("pending events or command responses\n"); } diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 6a8d2b291d8..05bb298dfae 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -10,7 +10,7 @@ #include "scan.h" #include "assoc.h" - +#include <linux/kfifo.h> /** sleep_params */ struct sleep_params { @@ -120,7 +120,7 @@ struct lbs_private { u32 resp_len[2]; /* Events sent from hardware to driver */ - struct kfifo *event_fifo; + struct kfifo event_fifo; /** thread to service interrupts */ struct task_struct *main_thread; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index db38a5a719f..c2975c8e2f2 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -459,7 +459,7 @@ static int lbs_thread(void *data) else if (!list_empty(&priv->cmdpendingq) && !(priv->wakeup_dev_required)) shouldsleep = 0; /* We have a command to send */ - else if (__kfifo_len(priv->event_fifo)) + else if (kfifo_len(&priv->event_fifo)) shouldsleep = 0; /* We have an event to process */ else shouldsleep = 1; /* No command */ @@ -511,10 +511,13 @@ static int lbs_thread(void *data) /* Process hardware events, e.g. card removed, link lost */ spin_lock_irq(&priv->driver_lock); - while (__kfifo_len(priv->event_fifo)) { + while (kfifo_len(&priv->event_fifo)) { u32 event; - __kfifo_get(priv->event_fifo, (unsigned char *) &event, - sizeof(event)); + + if (kfifo_out(&priv->event_fifo, + (unsigned char *) &event, sizeof(event)) != + sizeof(event)) + break; spin_unlock_irq(&priv->driver_lock); lbs_process_event(priv, event); spin_lock_irq(&priv->driver_lock); @@ -883,10 +886,9 @@ static int lbs_init_adapter(struct lbs_private *priv) priv->resp_len[0] = priv->resp_len[1] = 0; /* Create the event FIFO */ - priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); - if (IS_ERR(priv->event_fifo)) { + ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL); + if (ret) { lbs_pr_err("Out of memory allocating event FIFO buffer\n"); - ret = -ENOMEM; goto out; } @@ -901,8 +903,7 @@ static void lbs_free_adapter(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_MAIN); lbs_free_cmd_buffer(priv); - if (priv->event_fifo) - kfifo_free(priv->event_fifo); + kfifo_free(&priv->event_fifo); del_timer(&priv->command_timer); del_timer(&priv->auto_deepsleep_timer); kfree(priv->networks); @@ -1177,7 +1178,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event) if (priv->psstate == PS_STATE_SLEEP) priv->psstate = PS_STATE_AWAKE; - __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); + kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); wake_up_interruptible(&priv->waitq); diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index bcd4ba8be7d..b66029bd75d 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -164,7 +164,7 @@ struct fujitsu_hotkey_t { struct input_dev *input; char phys[32]; struct platform_device *pf_device; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; int rfkill_supported; int rfkill_state; @@ -824,12 +824,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) /* kfifo */ spin_lock_init(&fujitsu_hotkey->fifo_lock); - fujitsu_hotkey->fifo = - kfifo_alloc(RINGBUFFERSIZE * sizeof(int), GFP_KERNEL, - &fujitsu_hotkey->fifo_lock); - if (IS_ERR(fujitsu_hotkey->fifo)) { + error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int), + GFP_KERNEL); + if (error) { printk(KERN_ERR "kfifo_alloc failed\n"); - error = PTR_ERR(fujitsu_hotkey->fifo); goto err_stop; } @@ -934,7 +932,7 @@ err_unregister_input_dev: err_free_input_dev: input_free_device(input); err_free_fifo: - kfifo_free(fujitsu_hotkey->fifo); + kfifo_free(&fujitsu_hotkey->fifo); err_stop: return result; } @@ -956,7 +954,7 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type) input_free_device(input); - kfifo_free(fujitsu_hotkey->fifo); + kfifo_free(&fujitsu_hotkey->fifo); fujitsu_hotkey->acpi_handle = NULL; @@ -1008,9 +1006,10 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) vdbg_printk(FUJLAPTOP_DBG_TRACE, "Push keycode into ringbuffer [%d]\n", keycode); - status = kfifo_put(fujitsu_hotkey->fifo, + status = kfifo_in_locked(&fujitsu_hotkey->fifo, (unsigned char *)&keycode, - sizeof(keycode)); + sizeof(keycode), + &fujitsu_hotkey->fifo_lock); if (status != sizeof(keycode)) { vdbg_printk(FUJLAPTOP_DBG_WARN, "Could not push keycode [0x%x]\n", @@ -1021,11 +1020,12 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) } } else if (keycode == 0) { while ((status = - kfifo_get - (fujitsu_hotkey->fifo, (unsigned char *) - &keycode_r, - sizeof - (keycode_r))) == sizeof(keycode_r)) { + kfifo_out_locked( + &fujitsu_hotkey->fifo, + (unsigned char *) &keycode_r, + sizeof(keycode_r), + &fujitsu_hotkey->fifo_lock)) + == sizeof(keycode_r)) { input_report_key(input, keycode_r, 0); input_sync(input); vdbg_printk(FUJLAPTOP_DBG_TRACE, diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 7a2cc8a5c97..2896ca4cd9a 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -142,7 +142,7 @@ struct sony_laptop_input_s { atomic_t users; struct input_dev *jog_dev; struct input_dev *key_dev; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; struct workqueue_struct *wq; }; @@ -300,8 +300,9 @@ static void do_sony_laptop_release_key(struct work_struct *work) { struct sony_laptop_keypress kp; - while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp, - sizeof(kp)) == sizeof(kp)) { + while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, + sizeof(kp), &sony_laptop_input.fifo_lock) + == sizeof(kp)) { msleep(10); input_report_key(kp.dev, kp.key, 0); input_sync(kp.dev); @@ -362,8 +363,9 @@ static void sony_laptop_report_input_event(u8 event) /* we emit the scancode so we can always remap the key */ input_event(kp.dev, EV_MSC, MSC_SCAN, event); input_sync(kp.dev); - kfifo_put(sony_laptop_input.fifo, - (unsigned char *)&kp, sizeof(kp)); + kfifo_in_locked(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp), + &sony_laptop_input.fifo_lock); if (!work_pending(&sony_laptop_release_key_work)) queue_work(sony_laptop_input.wq, @@ -385,12 +387,10 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) /* kfifo */ spin_lock_init(&sony_laptop_input.fifo_lock); - sony_laptop_input.fifo = - kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, - &sony_laptop_input.fifo_lock); - if (IS_ERR(sony_laptop_input.fifo)) { + error = + kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); + if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); - error = PTR_ERR(sony_laptop_input.fifo); goto err_dec_users; } @@ -474,7 +474,7 @@ err_destroy_wq: destroy_workqueue(sony_laptop_input.wq); err_free_kfifo: - kfifo_free(sony_laptop_input.fifo); + kfifo_free(&sony_laptop_input.fifo); err_dec_users: atomic_dec(&sony_laptop_input.users); @@ -500,7 +500,7 @@ static void sony_laptop_remove_input(void) } destroy_workqueue(sony_laptop_input.wq); - kfifo_free(sony_laptop_input.fifo); + kfifo_free(&sony_laptop_input.fifo); } /*********** Platform Device ***********/ @@ -2079,7 +2079,7 @@ static struct attribute_group spic_attribute_group = { struct sonypi_compat_s { struct fasync_struct *fifo_async; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; wait_queue_head_t fifo_proc_list; atomic_t open_count; @@ -2104,12 +2104,12 @@ static int sonypi_misc_open(struct inode *inode, struct file *file) /* Flush input queue on first open */ unsigned long flags; - spin_lock_irqsave(sonypi_compat.fifo->lock, flags); + spin_lock_irqsave(&sonypi_compat.fifo_lock, flags); if (atomic_inc_return(&sonypi_compat.open_count) == 1) - __kfifo_reset(sonypi_compat.fifo); + kfifo_reset(&sonypi_compat.fifo); - spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); + spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags); return 0; } @@ -2120,17 +2120,18 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, ssize_t ret; unsigned char c; - if ((kfifo_len(sonypi_compat.fifo) == 0) && + if ((kfifo_len(&sonypi_compat.fifo) == 0) && (file->f_flags & O_NONBLOCK)) return -EAGAIN; ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, - kfifo_len(sonypi_compat.fifo) != 0); + kfifo_len(&sonypi_compat.fifo) != 0); if (ret) return ret; while (ret < count && - (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { + (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c), + &sonypi_compat.fifo_lock) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; ret++; @@ -2147,7 +2148,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) { poll_wait(file, &sonypi_compat.fifo_proc_list, wait); - if (kfifo_len(sonypi_compat.fifo)) + if (kfifo_len(&sonypi_compat.fifo)) return POLLIN | POLLRDNORM; return 0; } @@ -2309,7 +2310,8 @@ static struct miscdevice sonypi_misc_device = { static void sonypi_compat_report_event(u8 event) { - kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event)); + kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event, + sizeof(event), &sonypi_compat.fifo_lock); kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_compat.fifo_proc_list); } @@ -2319,11 +2321,11 @@ static int sonypi_compat_init(void) int error; spin_lock_init(&sonypi_compat.fifo_lock); - sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, - &sonypi_compat.fifo_lock); - if (IS_ERR(sonypi_compat.fifo)) { + error = + kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); + if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); - return PTR_ERR(sonypi_compat.fifo); + return error; } init_waitqueue_head(&sonypi_compat.fifo_proc_list); @@ -2342,14 +2344,14 @@ static int sonypi_compat_init(void) return 0; err_free_kfifo: - kfifo_free(sonypi_compat.fifo); + kfifo_free(&sonypi_compat.fifo); return error; } static void sonypi_compat_exit(void) { misc_deregister(&sonypi_misc_device); - kfifo_free(sonypi_compat.fifo); + kfifo_free(&sonypi_compat.fifo); } #else static int sonypi_compat_init(void) { return 0; } diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index b7689f3d05f..c28a712fd4d 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -517,7 +517,7 @@ static void iscsi_free_task(struct iscsi_task *task) if (conn->login_task == task) return; - __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); + kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*)); if (sc) { task->sc = NULL; @@ -737,7 +737,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); - if (!__kfifo_get(session->cmdpool.queue, + if (!kfifo_out(&session->cmdpool.queue, (void*)&task, sizeof(void*))) return NULL; } @@ -1567,7 +1567,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, { struct iscsi_task *task; - if (!__kfifo_get(conn->session->cmdpool.queue, + if (!kfifo_out(&conn->session->cmdpool.queue, (void *) &task, sizeof(void *))) return NULL; @@ -2461,12 +2461,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) if (q->pool == NULL) return -ENOMEM; - q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), - GFP_KERNEL, NULL); - if (IS_ERR(q->queue)) { - q->queue = NULL; - goto enomem; - } + kfifo_init(&q->queue, (void*)q->pool, max * sizeof(void*)); for (i = 0; i < max; i++) { q->pool[i] = kzalloc(item_size, GFP_KERNEL); @@ -2474,7 +2469,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) q->max = i; goto enomem; } - __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); + kfifo_in(&q->queue, (void*)&q->pool[i], sizeof(void*)); } if (items) { @@ -2497,7 +2492,6 @@ void iscsi_pool_free(struct iscsi_pool *q) for (i = 0; i < q->max; i++) kfree(q->pool[i]); kfree(q->pool); - kfree(q->queue); } EXPORT_SYMBOL_GPL(iscsi_pool_free); @@ -2825,7 +2819,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, /* allocate login_task used for the login/text sequences */ spin_lock_bh(&session->lock); - if (!__kfifo_get(session->cmdpool.queue, + if (!kfifo_out(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*))) { spin_unlock_bh(&session->lock); @@ -2845,7 +2839,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, return cls_conn; login_task_data_alloc_fail: - __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, + kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); login_task_alloc_fail: iscsi_destroy_conn(cls_conn); @@ -2908,7 +2902,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) free_pages((unsigned long) conn->data, get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); kfree(conn->persistent_address); - __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, + kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); if (session->leadconn == conn) session->leadconn = NULL; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index ca25ee5190b..db6856c138f 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -445,15 +445,15 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task) return; /* flush task's r2t queues */ - while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { - __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, + while (kfifo_out(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { + kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n"); } r2t = tcp_task->r2t; if (r2t != NULL) { - __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); tcp_task->r2t = NULL; } @@ -541,7 +541,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) return 0; } - rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); + rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); if (!rc) { iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. " "Target has sent more R2Ts than it " @@ -554,7 +554,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) if (r2t->data_length == 0) { iscsi_conn_printk(KERN_ERR, conn, "invalid R2T with zero data len\n"); - __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; } @@ -570,7 +570,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) "invalid R2T with data len %u at offset %u " "and total length %d\n", r2t->data_length, r2t->data_offset, scsi_out(task->sc)->length); - __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; } @@ -580,7 +580,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) r2t->sent = 0; tcp_task->exp_datasn = r2tsn + 1; - __kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); + kfifo_in(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); conn->r2t_pdus_cnt++; iscsi_requeue_task(task); @@ -951,7 +951,7 @@ int iscsi_tcp_task_init(struct iscsi_task *task) return conn->session->tt->init_pdu(task, 0, task->data_count); } - BUG_ON(__kfifo_len(tcp_task->r2tqueue)); + BUG_ON(kfifo_len(&tcp_task->r2tqueue)); tcp_task->exp_datasn = 0; /* Prepare PDU, optionally w/ immediate data */ @@ -982,7 +982,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) if (r2t->data_length <= r2t->sent) { ISCSI_DBG_TCP(task->conn, " done with r2t %p\n", r2t); - __kfifo_put(tcp_task->r2tpool.queue, + kfifo_in(&tcp_task->r2tpool.queue, (void *)&tcp_task->r2t, sizeof(void *)); tcp_task->r2t = r2t = NULL; @@ -990,8 +990,13 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) } if (r2t == NULL) { - __kfifo_get(tcp_task->r2tqueue, - (void *)&tcp_task->r2t, sizeof(void *)); + if (kfifo_out(&tcp_task->r2tqueue, + (void *)&tcp_task->r2t, sizeof(void *)) != + sizeof(void *)) { + WARN_ONCE(1, "unexpected fifo state"); + r2t = NULL; + } + r2t = tcp_task->r2t; } spin_unlock_bh(&session->lock); @@ -1127,9 +1132,8 @@ int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session) } /* R2T xmit queue */ - tcp_task->r2tqueue = kfifo_alloc( - session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL); - if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) { + if (kfifo_alloc(&tcp_task->r2tqueue, + session->max_r2t * 4 * sizeof(void*), GFP_KERNEL)) { iscsi_pool_free(&tcp_task->r2tpool); goto r2t_alloc_fail; } @@ -1142,7 +1146,7 @@ r2t_alloc_fail: struct iscsi_task *task = session->cmds[i]; struct iscsi_tcp_task *tcp_task = task->dd_data; - kfifo_free(tcp_task->r2tqueue); + kfifo_free(&tcp_task->r2tqueue); iscsi_pool_free(&tcp_task->r2tpool); } return -ENOMEM; @@ -1157,7 +1161,7 @@ void iscsi_tcp_r2tpool_free(struct iscsi_session *session) struct iscsi_task *task = session->cmds[i]; struct iscsi_tcp_task *tcp_task = task->dd_data; - kfifo_free(tcp_task->r2tqueue); + kfifo_free(&tcp_task->r2tqueue); iscsi_pool_free(&tcp_task->r2tpool); } } diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 9ad38e81e34..ab19b3b4be5 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -58,19 +58,15 @@ static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, goto free_pool; spin_lock_init(&q->lock); - q->queue = kfifo_init((void *) q->pool, max * sizeof(void *), - GFP_KERNEL, &q->lock); - if (IS_ERR(q->queue)) - goto free_item; + kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *)); for (i = 0, iue = q->items; i < max; i++) { - __kfifo_put(q->queue, (void *) &iue, sizeof(void *)); + kfifo_in(&q->queue, (void *) &iue, sizeof(void *)); iue->sbuf = ring[i]; iue++; } return 0; -free_item: kfree(q->items); free_pool: kfree(q->pool); @@ -167,7 +163,11 @@ struct iu_entry *srp_iu_get(struct srp_target *target) { struct iu_entry *iue = NULL; - kfifo_get(target->iu_queue.queue, (void *) &iue, sizeof(void *)); + if (kfifo_out_locked(&target->iu_queue.queue, (void *) &iue, + sizeof(void *), &target->iu_queue.lock) != sizeof(void *)) { + WARN_ONCE(1, "unexpected fifo state"); + return NULL; + } if (!iue) return iue; iue->target = target; @@ -179,7 +179,8 @@ EXPORT_SYMBOL_GPL(srp_iu_get); void srp_iu_put(struct iu_entry *iue) { - kfifo_put(iue->target->iu_queue.queue, (void *) &iue, sizeof(void *)); + kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue, + sizeof(void *), &iue->target->iu_queue.lock); } EXPORT_SYMBOL_GPL(srp_iu_put); diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c index 6c5b261e9f0..aacd25bfb0c 100644 --- a/drivers/staging/pohmelfs/dir.c +++ b/drivers/staging/pohmelfs/dir.c @@ -722,8 +722,6 @@ static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry) if (inode->i_nlink) inode_dec_link_count(inode); } - dprintk("%s: inode: %p, lock: %ld, unhashed: %d.\n", - __func__, pi, inode->i_state & I_LOCK, hlist_unhashed(&inode->i_hash)); return err; } diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 00a29855d0c..ff43747a614 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c @@ -37,7 +37,7 @@ static void recycle_frame(struct fhci_usb *usb, struct packet *pkt) pkt->info = 0; pkt->priv_data = NULL; - cq_put(usb->ep0->empty_frame_Q, pkt); + cq_put(&usb->ep0->empty_frame_Q, pkt); } /* confirm submitted packet */ @@ -57,7 +57,7 @@ void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt) if ((td->data + td->actual_len) && trans_len) memcpy(td->data + td->actual_len, pkt->data, trans_len); - cq_put(usb->ep0->dummy_packets_Q, pkt->data); + cq_put(&usb->ep0->dummy_packets_Q, pkt->data); } recycle_frame(usb, pkt); @@ -213,7 +213,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) } /* update frame object fields before transmitting */ - pkt = cq_get(usb->ep0->empty_frame_Q); + pkt = cq_get(&usb->ep0->empty_frame_Q); if (!pkt) { fhci_dbg(usb->fhci, "there is no empty frame\n"); return -1; @@ -222,7 +222,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) pkt->info = 0; if (data == NULL) { - data = cq_get(usb->ep0->dummy_packets_Q); + data = cq_get(&usb->ep0->dummy_packets_Q); BUG_ON(!data); pkt->info = PKT_DUMMY_PACKET; } @@ -246,7 +246,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) list_del_init(&td->frame_lh); td->status = USB_TD_OK; if (pkt->info & PKT_DUMMY_PACKET) - cq_put(usb->ep0->dummy_packets_Q, pkt->data); + cq_put(&usb->ep0->dummy_packets_Q, pkt->data); recycle_frame(usb, pkt); usb->actual_frame->total_bytes -= (len + PROTOCOL_OVERHEAD); fhci_err(usb->fhci, "host transaction failed\n"); diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c index b4033229031..d224ab467a4 100644 --- a/drivers/usb/host/fhci-tds.c +++ b/drivers/usb/host/fhci-tds.c @@ -106,33 +106,33 @@ void fhci_ep0_free(struct fhci_usb *usb) cpm_muram_free(cpm_muram_offset(ep->td_base)); if (ep->conf_frame_Q) { - size = cq_howmany(ep->conf_frame_Q); + size = cq_howmany(&ep->conf_frame_Q); for (; size; size--) { - struct packet *pkt = cq_get(ep->conf_frame_Q); + struct packet *pkt = cq_get(&ep->conf_frame_Q); kfree(pkt); } - cq_delete(ep->conf_frame_Q); + cq_delete(&ep->conf_frame_Q); } if (ep->empty_frame_Q) { - size = cq_howmany(ep->empty_frame_Q); + size = cq_howmany(&ep->empty_frame_Q); for (; size; size--) { - struct packet *pkt = cq_get(ep->empty_frame_Q); + struct packet *pkt = cq_get(&ep->empty_frame_Q); kfree(pkt); } - cq_delete(ep->empty_frame_Q); + cq_delete(&ep->empty_frame_Q); } if (ep->dummy_packets_Q) { - size = cq_howmany(ep->dummy_packets_Q); + size = cq_howmany(&ep->dummy_packets_Q); for (; size; size--) { - u8 *buff = cq_get(ep->dummy_packets_Q); + u8 *buff = cq_get(&ep->dummy_packets_Q); kfree(buff); } - cq_delete(ep->dummy_packets_Q); + cq_delete(&ep->dummy_packets_Q); } kfree(ep); @@ -175,10 +175,9 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, ep->td_base = cpm_muram_addr(ep_offset); /* zero all queue pointers */ - ep->conf_frame_Q = cq_new(ring_len + 2); - ep->empty_frame_Q = cq_new(ring_len + 2); - ep->dummy_packets_Q = cq_new(ring_len + 2); - if (!ep->conf_frame_Q || !ep->empty_frame_Q || !ep->dummy_packets_Q) { + if (cq_new(&ep->conf_frame_Q, ring_len + 2) || + cq_new(&ep->empty_frame_Q, ring_len + 2) || + cq_new(&ep->dummy_packets_Q, ring_len + 2)) { err_for = "frame_queues"; goto err; } @@ -199,8 +198,8 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, err_for = "buffer"; goto err; } - cq_put(ep->empty_frame_Q, pkt); - cq_put(ep->dummy_packets_Q, buff); + cq_put(&ep->empty_frame_Q, pkt); + cq_put(&ep->dummy_packets_Q, buff); } /* we put the endpoint parameter RAM right behind the TD ring */ @@ -319,7 +318,7 @@ static void fhci_td_transaction_confirm(struct fhci_usb *usb) if ((buf == DUMMY2_BD_BUFFER) && !(td_status & ~TD_W)) continue; - pkt = cq_get(ep->conf_frame_Q); + pkt = cq_get(&ep->conf_frame_Q); if (!pkt) fhci_err(usb->fhci, "no frame to confirm\n"); @@ -460,9 +459,9 @@ u32 fhci_host_transaction(struct fhci_usb *usb, out_be16(&td->length, pkt->len); /* put the frame to the confirmation queue */ - cq_put(ep->conf_frame_Q, pkt); + cq_put(&ep->conf_frame_Q, pkt); - if (cq_howmany(ep->conf_frame_Q) == 1) + if (cq_howmany(&ep->conf_frame_Q) == 1) out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); return 0; diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h index 7116284ed21..72dae1c5ab3 100644 --- a/drivers/usb/host/fhci.h +++ b/drivers/usb/host/fhci.h @@ -423,9 +423,9 @@ struct endpoint { struct usb_td __iomem *td_base; /* first TD in the ring */ struct usb_td __iomem *conf_td; /* next TD for confirm after transac */ struct usb_td __iomem *empty_td;/* next TD for new transaction req. */ - struct kfifo *empty_frame_Q; /* Empty frames list to use */ - struct kfifo *conf_frame_Q; /* frames passed to TDs,waiting for tx */ - struct kfifo *dummy_packets_Q;/* dummy packets for the CRC overun */ + struct kfifo empty_frame_Q; /* Empty frames list to use */ + struct kfifo conf_frame_Q; /* frames passed to TDs,waiting for tx */ + struct kfifo dummy_packets_Q;/* dummy packets for the CRC overun */ bool already_pushed_dummy_bd; }; @@ -493,9 +493,9 @@ static inline struct usb_hcd *fhci_to_hcd(struct fhci_hcd *fhci) } /* fifo of pointers */ -static inline struct kfifo *cq_new(int size) +static inline int cq_new(struct kfifo *fifo, int size) { - return kfifo_alloc(size * sizeof(void *), GFP_KERNEL, NULL); + return kfifo_alloc(fifo, size * sizeof(void *), GFP_KERNEL); } static inline void cq_delete(struct kfifo *kfifo) @@ -505,19 +505,19 @@ static inline void cq_delete(struct kfifo *kfifo) static inline unsigned int cq_howmany(struct kfifo *kfifo) { - return __kfifo_len(kfifo) / sizeof(void *); + return kfifo_len(kfifo) / sizeof(void *); } static inline int cq_put(struct kfifo *kfifo, void *p) { - return __kfifo_put(kfifo, (void *)&p, sizeof(p)); + return kfifo_in(kfifo, (void *)&p, sizeof(p)); } static inline void *cq_get(struct kfifo *kfifo) { void *p = NULL; - __kfifo_get(kfifo, (void *)&p, sizeof(p)); + kfifo_out(kfifo, (void *)&p, sizeof(p)); return p; } diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index bbe005cefcf..b0f1183755c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -276,7 +276,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) if (port->write_urb_busy) start_io = false; else { - start_io = (__kfifo_len(port->write_fifo) != 0); + start_io = (kfifo_len(port->write_fifo) != 0); port->write_urb_busy = start_io; } spin_unlock_irqrestore(&port->lock, flags); @@ -285,7 +285,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) return 0; data = port->write_urb->transfer_buffer; - count = kfifo_get(port->write_fifo, data, port->bulk_out_size); + count = kfifo_out_locked(port->write_fifo, data, port->bulk_out_size, &port->lock); usb_serial_debug_data(debug, &port->dev, __func__, count, data); /* set up our urb */ @@ -345,7 +345,7 @@ int usb_serial_generic_write(struct tty_struct *tty, return usb_serial_multi_urb_write(tty, port, buf, count); - count = kfifo_put(port->write_fifo, buf, count); + count = kfifo_in_locked(port->write_fifo, buf, count, &port->lock); result = usb_serial_generic_write_start(port); if (result >= 0) @@ -370,7 +370,7 @@ int usb_serial_generic_write_room(struct tty_struct *tty) (serial->type->max_in_flight_urbs - port->urbs_in_flight); } else if (serial->num_bulk_out) - room = port->write_fifo->size - __kfifo_len(port->write_fifo); + room = port->write_fifo->size - kfifo_len(port->write_fifo); spin_unlock_irqrestore(&port->lock, flags); dbg("%s - returns %d", __func__, room); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4543f359be7..636a4f23445 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -939,9 +939,7 @@ int usb_serial_probe(struct usb_interface *interface, dev_err(&interface->dev, "No free urbs available\n"); goto probe_error; } - port->write_fifo = kfifo_alloc(PAGE_SIZE, GFP_KERNEL, - &port->lock); - if (IS_ERR(port->write_fifo)) + if (kfifo_alloc(port->write_fifo, PAGE_SIZE, GFP_KERNEL)) goto probe_error; buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); port->bulk_out_size = buffer_size; diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 2c994591f4d..9f0bf13291e 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -121,13 +121,13 @@ struct file *anon_inode_getfile(const char *name, d_instantiate(path.dentry, anon_inode_inode); error = -ENFILE; - file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops); + file = alloc_file(&path, OPEN_FMODE(flags), fops); if (!file) goto err_dput; file->f_mapping = anon_inode_inode->i_mapping; file->f_pos = 0; - file->f_flags = O_RDWR | (flags & O_NONBLOCK); + file->f_flags = flags & (O_ACCMODE | O_NONBLOCK); file->f_version = 0; file->private_data = priv; diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 14cbc831422..332dd00f089 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1600,8 +1600,6 @@ static long do_ioctl_trans(int fd, unsigned int cmd, case KDSKBMETA: case KDSKBLED: case KDSETLED: - /* SG stuff */ - case SG_SET_TRANSFORM: /* AUTOFS */ case AUTOFS_IOC_READY: case AUTOFS_IOC_FAIL: diff --git a/fs/eventfd.c b/fs/eventfd.c index 8b47e4200e6..d26402ff06e 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c @@ -339,7 +339,7 @@ struct file *eventfd_file_create(unsigned int count, int flags) ctx->flags = flags; file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx, - flags & EFD_SHARED_FCNTL_FLAGS); + O_RDWR | (flags & EFD_SHARED_FCNTL_FLAGS)); if (IS_ERR(file)) eventfd_free_ctx(ctx); diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 366c503f965..bd056a5b4ef 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1206,7 +1206,7 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) * a file structure and a free file descriptor. */ error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, - flags & O_CLOEXEC); + O_RDWR | (flags & O_CLOEXEC)); if (error < 0) ep_free(ep); diff --git a/fs/file_table.c b/fs/file_table.c index 0afacf65439..69652c5bd5f 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -186,10 +186,8 @@ struct file *alloc_file(struct path *path, fmode_t mode, * that we can do debugging checks at __fput() */ if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) { - int error = 0; file_take_write(file); - error = mnt_clone_write(path->mnt); - WARN_ON(error); + WARN_ON(mnt_clone_write(path->mnt)); } ima_counts_get(file); return file; diff --git a/fs/internal.h b/fs/internal.h index f67cd141d9a..e96a1667d74 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -85,3 +85,10 @@ extern struct file *get_empty_filp(void); * super.c */ extern int do_remount_sb(struct super_block *, int, void *, int); + +/* + * open.c + */ +struct nameidata; +extern struct file *nameidata_to_filp(struct nameidata *); +extern void release_open_intent(struct nameidata *); diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 2234c73fc57..d929a822a74 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -524,7 +524,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) * Page cache is indexed by long. * I would use MAX_LFS_FILESIZE, but it's only half as big */ - sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes); + sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, (u64)sb->s_maxbytes); #endif sb->s_time_gran = 1; return 0; diff --git a/fs/namei.c b/fs/namei.c index dad4b80257d..68921d9b530 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -37,8 +37,6 @@ #include "internal.h" -#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) - /* [Feb-1997 T. Schoebel-Theuer] * Fundamental changes in the pathname lookup mechanisms (namei) * were necessary because of omirr. The reason is that omirr needs @@ -1640,6 +1638,7 @@ struct file *do_filp_open(int dfd, const char *pathname, if (filp == NULL) return ERR_PTR(-ENFILE); nd.intent.open.file = filp; + filp->f_flags = open_flag; nd.intent.open.flags = flag; nd.intent.open.create_mode = 0; error = do_path_lookup(dfd, pathname, @@ -1685,6 +1684,7 @@ struct file *do_filp_open(int dfd, const char *pathname, if (filp == NULL) goto exit_parent; nd.intent.open.file = filp; + filp->f_flags = open_flag; nd.intent.open.flags = flag; nd.intent.open.create_mode = mode; dir = nd.path.dentry; @@ -1725,7 +1725,7 @@ do_last: mnt_drop_write(nd.path.mnt); goto exit; } - filp = nameidata_to_filp(&nd, open_flag); + filp = nameidata_to_filp(&nd); mnt_drop_write(nd.path.mnt); if (nd.root.mnt) path_put(&nd.root); @@ -1789,7 +1789,7 @@ ok: mnt_drop_write(nd.path.mnt); goto exit; } - filp = nameidata_to_filp(&nd, open_flag); + filp = nameidata_to_filp(&nd); if (!IS_ERR(filp)) { error = ima_path_check(&filp->f_path, filp->f_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 1c12177b908..55c8e63af0b 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -89,7 +89,7 @@ static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp, int flags = nfsexp_flags(rqstp, exp); /* Check if the request originated from a secure port. */ - if (!rqstp->rq_secure && (flags & NFSEXP_INSECURE_PORT)) { + if (!rqstp->rq_secure && !(flags & NFSEXP_INSECURE_PORT)) { RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); dprintk(KERN_WARNING "nfsd: request from insecure port %s!\n", diff --git a/fs/open.c b/fs/open.c index ca69241796b..040cef72bc0 100644 --- a/fs/open.c +++ b/fs/open.c @@ -821,15 +821,14 @@ static inline int __get_file_write_access(struct inode *inode, } static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, - int flags, struct file *f, + struct file *f, int (*open)(struct inode *, struct file *), const struct cred *cred) { struct inode *inode; int error; - f->f_flags = flags; - f->f_mode = (__force fmode_t)((flags+1) & O_ACCMODE) | FMODE_LSEEK | + f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; inode = dentry->d_inode; if (f->f_mode & FMODE_WRITE) { @@ -930,7 +929,6 @@ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry if (IS_ERR(dentry)) goto out_err; nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), - nd->intent.open.flags - 1, nd->intent.open.file, open, cred); out: @@ -949,7 +947,7 @@ EXPORT_SYMBOL_GPL(lookup_instantiate_filp); * * Note that this function destroys the original nameidata */ -struct file *nameidata_to_filp(struct nameidata *nd, int flags) +struct file *nameidata_to_filp(struct nameidata *nd) { const struct cred *cred = current_cred(); struct file *filp; @@ -958,7 +956,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) filp = nd->intent.open.file; /* Has the filesystem initialised the file for us? */ if (filp->f_path.dentry == NULL) - filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp, + filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, NULL, cred); else path_put(&nd->path); @@ -997,7 +995,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, return ERR_PTR(error); } - return __dentry_open(dentry, mnt, flags, f, NULL, cred); + f->f_flags = flags; + return __dentry_open(dentry, mnt, f, NULL, cred); } EXPORT_SYMBOL(dentry_open); diff --git a/fs/signalfd.c b/fs/signalfd.c index b07565c9438..1dabe4ee02f 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -236,7 +236,7 @@ SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, * anon_inode_getfd() will install the fd. */ ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, - flags & (O_CLOEXEC | O_NONBLOCK)); + O_RDWR | (flags & (O_CLOEXEC | O_NONBLOCK))); if (ufd < 0) kfree(ctx); } else { diff --git a/fs/timerfd.c b/fs/timerfd.c index b042bd7034b..1bfc95ad5f7 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -200,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS); ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx, - flags & TFD_SHARED_FCNTL_FLAGS); + O_RDWR | (flags & TFD_SHARED_FCNTL_FLAGS)); if (ufd < 0) kfree(ctx); diff --git a/include/linux/fs.h b/include/linux/fs.h index cca191933ff..7e3012e0ac0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1624,8 +1624,6 @@ struct super_operations { * on the bit address once it is done. * * Q: What is the difference between I_WILL_FREE and I_FREEING? - * Q: igrab() only checks on (I_FREEING|I_WILL_FREE). Should it also check on - * I_CLEAR? If not, why? */ #define I_DIRTY_SYNC 1 #define I_DIRTY_DATASYNC 2 @@ -2464,5 +2462,8 @@ int proc_nr_files(struct ctl_table *table, int write, int __init get_filesystem_list(char *buf); +#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) +#define OPEN_FMODE(flag) ((__force fmode_t)((flag + 1) & O_ACCMODE)) + #endif /* __KERNEL__ */ #endif /* _LINUX_FS_H */ diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index ad6bdf5a597..486e8ad3bb5 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -1,6 +1,7 @@ /* - * A simple kernel FIFO implementation. + * A generic kernel FIFO implementation. * + * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net> * Copyright (C) 2004 Stelian Pop <stelian@popies.net> * * This program is free software; you can redistribute it and/or modify @@ -18,6 +19,25 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ + +/* + * Howto porting drivers to the new generic fifo API: + * + * - Modify the declaration of the "struct kfifo *" object into a + * in-place "struct kfifo" object + * - Init the in-place object with kfifo_alloc() or kfifo_init() + * Note: The address of the in-place "struct kfifo" object must be + * passed as the first argument to this functions + * - Replace the use of __kfifo_put into kfifo_in and __kfifo_get + * into kfifo_out + * - Replace the use of kfifo_put into kfifo_in_locked and kfifo_get + * into kfifo_out_locked + * Note: the spinlock pointer formerly passed to kfifo_init/kfifo_alloc + * must be passed now to the kfifo_in_locked and kfifo_out_locked + * as the last parameter. + * - All formerly name __kfifo_* functions has been renamed into kfifo_* + */ + #ifndef _LINUX_KFIFO_H #define _LINUX_KFIFO_H @@ -29,124 +49,563 @@ struct kfifo { unsigned int size; /* the size of the allocated buffer */ unsigned int in; /* data is added at offset (in % size) */ unsigned int out; /* data is extracted from off. (out % size) */ - spinlock_t *lock; /* protects concurrent modifications */ }; -extern struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, - gfp_t gfp_mask, spinlock_t *lock); -extern struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, - spinlock_t *lock); +/* + * Macros for declaration and initialization of the kfifo datatype + */ + +/* helper macro */ +#define __kfifo_initializer(s, b) \ + (struct kfifo) { \ + .size = s, \ + .in = 0, \ + .out = 0, \ + .buffer = b \ + } + +/** + * DECLARE_KFIFO - macro to declare a kfifo and the associated buffer + * @name: name of the declared kfifo datatype + * @size: size of the fifo buffer + * + * Note: the macro can be used inside struct or union declaration + * Note: the macro creates two objects: + * A kfifo object with the given name and a buffer for the kfifo + * object named name##kfifo_buffer + */ +#define DECLARE_KFIFO(name, size) \ +union { \ + struct kfifo name; \ + unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \ +} + +/** + * INIT_KFIFO - Initialize a kfifo declared by DECLARED_KFIFO + * @name: name of the declared kfifo datatype + * @size: size of the fifo buffer + */ +#define INIT_KFIFO(name) \ + name = __kfifo_initializer(sizeof(name##kfifo_buffer) - \ + sizeof(struct kfifo), name##kfifo_buffer) + +/** + * DEFINE_KFIFO - macro to define and initialize a kfifo + * @name: name of the declared kfifo datatype + * @size: size of the fifo buffer + * + * Note: the macro can be used for global and local kfifo data type variables + * Note: the macro creates two objects: + * A kfifo object with the given name and a buffer for the kfifo + * object named name##kfifo_buffer + */ +#define DEFINE_KFIFO(name, size) \ + unsigned char name##kfifo_buffer[size]; \ + struct kfifo name = __kfifo_initializer(size, name##kfifo_buffer) + +#undef __kfifo_initializer + +extern void kfifo_init(struct kfifo *fifo, unsigned char *buffer, + unsigned int size); +extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size, + gfp_t gfp_mask); extern void kfifo_free(struct kfifo *fifo); -extern unsigned int __kfifo_put(struct kfifo *fifo, - const unsigned char *buffer, unsigned int len); -extern unsigned int __kfifo_get(struct kfifo *fifo, - unsigned char *buffer, unsigned int len); +extern unsigned int kfifo_in(struct kfifo *fifo, + const unsigned char *from, unsigned int len); +extern __must_check unsigned int kfifo_out(struct kfifo *fifo, + unsigned char *to, unsigned int len); /** - * __kfifo_reset - removes the entire FIFO contents, no locking version + * kfifo_reset - removes the entire FIFO contents * @fifo: the fifo to be emptied. */ -static inline void __kfifo_reset(struct kfifo *fifo) +static inline void kfifo_reset(struct kfifo *fifo) { fifo->in = fifo->out = 0; } /** - * kfifo_reset - removes the entire FIFO contents + * kfifo_reset_out - skip FIFO contents * @fifo: the fifo to be emptied. */ -static inline void kfifo_reset(struct kfifo *fifo) +static inline void kfifo_reset_out(struct kfifo *fifo) { - unsigned long flags; + smp_mb(); + fifo->out = fifo->in; +} - spin_lock_irqsave(fifo->lock, flags); +/** + * kfifo_size - returns the size of the fifo in bytes + * @fifo: the fifo to be used. + */ +static inline __must_check unsigned int kfifo_size(struct kfifo *fifo) +{ + return fifo->size; +} - __kfifo_reset(fifo); +/** + * kfifo_len - returns the number of used bytes in the FIFO + * @fifo: the fifo to be used. + */ +static inline unsigned int kfifo_len(struct kfifo *fifo) +{ + register unsigned int out; - spin_unlock_irqrestore(fifo->lock, flags); + out = fifo->out; + smp_rmb(); + return fifo->in - out; } /** - * kfifo_put - puts some data into the FIFO + * kfifo_is_empty - returns true if the fifo is empty * @fifo: the fifo to be used. - * @buffer: the data to be added. - * @len: the length of the data to be added. + */ +static inline __must_check int kfifo_is_empty(struct kfifo *fifo) +{ + return fifo->in == fifo->out; +} + +/** + * kfifo_is_full - returns true if the fifo is full + * @fifo: the fifo to be used. + */ +static inline __must_check int kfifo_is_full(struct kfifo *fifo) +{ + return kfifo_len(fifo) == kfifo_size(fifo); +} + +/** + * kfifo_avail - returns the number of bytes available in the FIFO + * @fifo: the fifo to be used. + */ +static inline __must_check unsigned int kfifo_avail(struct kfifo *fifo) +{ + return kfifo_size(fifo) - kfifo_len(fifo); +} + +/** + * kfifo_in_locked - puts some data into the FIFO using a spinlock for locking + * @fifo: the fifo to be used. + * @from: the data to be added. + * @n: the length of the data to be added. + * @lock: pointer to the spinlock to use for locking. * - * This function copies at most @len bytes from the @buffer into + * This function copies at most @len bytes from the @from buffer into * the FIFO depending on the free space, and returns the number of * bytes copied. */ -static inline unsigned int kfifo_put(struct kfifo *fifo, - const unsigned char *buffer, unsigned int len) +static inline unsigned int kfifo_in_locked(struct kfifo *fifo, + const unsigned char *from, unsigned int n, spinlock_t *lock) { unsigned long flags; unsigned int ret; - spin_lock_irqsave(fifo->lock, flags); + spin_lock_irqsave(lock, flags); - ret = __kfifo_put(fifo, buffer, len); + ret = kfifo_in(fifo, from, n); - spin_unlock_irqrestore(fifo->lock, flags); + spin_unlock_irqrestore(lock, flags); return ret; } /** - * kfifo_get - gets some data from the FIFO + * kfifo_out_locked - gets some data from the FIFO using a spinlock for locking * @fifo: the fifo to be used. - * @buffer: where the data must be copied. - * @len: the size of the destination buffer. + * @to: where the data must be copied. + * @n: the size of the destination buffer. + * @lock: pointer to the spinlock to use for locking. * * This function copies at most @len bytes from the FIFO into the - * @buffer and returns the number of copied bytes. + * @to buffer and returns the number of copied bytes. */ -static inline unsigned int kfifo_get(struct kfifo *fifo, - unsigned char *buffer, unsigned int len) +static inline __must_check unsigned int kfifo_out_locked(struct kfifo *fifo, + unsigned char *to, unsigned int n, spinlock_t *lock) { unsigned long flags; unsigned int ret; - spin_lock_irqsave(fifo->lock, flags); + spin_lock_irqsave(lock, flags); - ret = __kfifo_get(fifo, buffer, len); + ret = kfifo_out(fifo, to, n); /* * optimization: if the FIFO is empty, set the indices to 0 * so we don't wrap the next time */ - if (fifo->in == fifo->out) - fifo->in = fifo->out = 0; + if (kfifo_is_empty(fifo)) + kfifo_reset(fifo); + + spin_unlock_irqrestore(lock, flags); + + return ret; +} + +extern void kfifo_skip(struct kfifo *fifo, unsigned int len); + +extern __must_check unsigned int kfifo_from_user(struct kfifo *fifo, + const void __user *from, unsigned int n); + +extern __must_check unsigned int kfifo_to_user(struct kfifo *fifo, + void __user *to, unsigned int n); + +/** + * __kfifo_add_out internal helper function for updating the out offset + */ +static inline void __kfifo_add_out(struct kfifo *fifo, + unsigned int off) +{ + smp_mb(); + fifo->out += off; +} + +/** + * __kfifo_add_in internal helper function for updating the in offset + */ +static inline void __kfifo_add_in(struct kfifo *fifo, + unsigned int off) +{ + smp_wmb(); + fifo->in += off; +} + +/** + * __kfifo_off internal helper function for calculating the index of a + * given offeset + */ +static inline unsigned int __kfifo_off(struct kfifo *fifo, unsigned int off) +{ + return off & (fifo->size - 1); +} + +/** + * __kfifo_peek_n internal helper function for determinate the length of + * the next record in the fifo + */ +static inline unsigned int __kfifo_peek_n(struct kfifo *fifo, + unsigned int recsize) +{ +#define __KFIFO_GET(fifo, off, shift) \ + ((fifo)->buffer[__kfifo_off((fifo), (fifo)->out+(off))] << (shift)) + + unsigned int l; + + l = __KFIFO_GET(fifo, 0, 0); + + if (--recsize) + l |= __KFIFO_GET(fifo, 1, 8); + + return l; +#undef __KFIFO_GET +} + +/** + * __kfifo_poke_n internal helper function for storing the length of + * the next record into the fifo + */ +static inline void __kfifo_poke_n(struct kfifo *fifo, + unsigned int recsize, unsigned int n) +{ +#define __KFIFO_PUT(fifo, off, val, shift) \ + ( \ + (fifo)->buffer[__kfifo_off((fifo), (fifo)->in+(off))] = \ + (unsigned char)((val) >> (shift)) \ + ) - spin_unlock_irqrestore(fifo->lock, flags); + __KFIFO_PUT(fifo, 0, n, 0); + if (--recsize) + __KFIFO_PUT(fifo, 1, n, 8); +#undef __KFIFO_PUT +} + +/** + * __kfifo_in_... internal functions for put date into the fifo + * do not call it directly, use kfifo_in_rec() instead + */ +extern unsigned int __kfifo_in_n(struct kfifo *fifo, + const void *from, unsigned int n, unsigned int recsize); + +extern unsigned int __kfifo_in_generic(struct kfifo *fifo, + const void *from, unsigned int n, unsigned int recsize); + +static inline unsigned int __kfifo_in_rec(struct kfifo *fifo, + const void *from, unsigned int n, unsigned int recsize) +{ + unsigned int ret; + + ret = __kfifo_in_n(fifo, from, n, recsize); + + if (likely(ret == 0)) { + if (recsize) + __kfifo_poke_n(fifo, recsize, n); + __kfifo_add_in(fifo, n + recsize); + } return ret; } /** - * __kfifo_len - returns the number of bytes available in the FIFO, no locking version + * kfifo_in_rec - puts some record data into the FIFO * @fifo: the fifo to be used. + * @from: the data to be added. + * @n: the length of the data to be added. + * @recsize: size of record field + * + * This function copies @n bytes from the @from into the FIFO and returns + * the number of bytes which cannot be copied. + * A returned value greater than the @n value means that the record doesn't + * fit into the buffer. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. */ -static inline unsigned int __kfifo_len(struct kfifo *fifo) +static inline __must_check unsigned int kfifo_in_rec(struct kfifo *fifo, + void *from, unsigned int n, unsigned int recsize) { - return fifo->in - fifo->out; + if (!__builtin_constant_p(recsize)) + return __kfifo_in_generic(fifo, from, n, recsize); + return __kfifo_in_rec(fifo, from, n, recsize); } /** - * kfifo_len - returns the number of bytes available in the FIFO + * __kfifo_out_... internal functions for get date from the fifo + * do not call it directly, use kfifo_out_rec() instead + */ +extern unsigned int __kfifo_out_n(struct kfifo *fifo, + void *to, unsigned int reclen, unsigned int recsize); + +extern unsigned int __kfifo_out_generic(struct kfifo *fifo, + void *to, unsigned int n, + unsigned int recsize, unsigned int *total); + +static inline unsigned int __kfifo_out_rec(struct kfifo *fifo, + void *to, unsigned int n, unsigned int recsize, + unsigned int *total) +{ + unsigned int l; + + if (!recsize) { + l = n; + if (total) + *total = l; + } else { + l = __kfifo_peek_n(fifo, recsize); + if (total) + *total = l; + if (n < l) + return l; + } + + return __kfifo_out_n(fifo, to, l, recsize); +} + +/** + * kfifo_out_rec - gets some record data from the FIFO * @fifo: the fifo to be used. + * @to: where the data must be copied. + * @n: the size of the destination buffer. + * @recsize: size of record field + * @total: pointer where the total number of to copied bytes should stored + * + * This function copies at most @n bytes from the FIFO to @to and returns the + * number of bytes which cannot be copied. + * A returned value greater than the @n value means that the record doesn't + * fit into the @to buffer. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. */ -static inline unsigned int kfifo_len(struct kfifo *fifo) +static inline __must_check unsigned int kfifo_out_rec(struct kfifo *fifo, + void *to, unsigned int n, unsigned int recsize, + unsigned int *total) + { - unsigned long flags; - unsigned int ret; + if (!__builtin_constant_p(recsize)) + return __kfifo_out_generic(fifo, to, n, recsize, total); + return __kfifo_out_rec(fifo, to, n, recsize, total); +} + +/** + * __kfifo_from_user_... internal functions for transfer from user space into + * the fifo. do not call it directly, use kfifo_from_user_rec() instead + */ +extern unsigned int __kfifo_from_user_n(struct kfifo *fifo, + const void __user *from, unsigned int n, unsigned int recsize); - spin_lock_irqsave(fifo->lock, flags); +extern unsigned int __kfifo_from_user_generic(struct kfifo *fifo, + const void __user *from, unsigned int n, unsigned int recsize); - ret = __kfifo_len(fifo); +static inline unsigned int __kfifo_from_user_rec(struct kfifo *fifo, + const void __user *from, unsigned int n, unsigned int recsize) +{ + unsigned int ret; - spin_unlock_irqrestore(fifo->lock, flags); + ret = __kfifo_from_user_n(fifo, from, n, recsize); + if (likely(ret == 0)) { + if (recsize) + __kfifo_poke_n(fifo, recsize, n); + __kfifo_add_in(fifo, n + recsize); + } return ret; } +/** + * kfifo_from_user_rec - puts some data from user space into the FIFO + * @fifo: the fifo to be used. + * @from: pointer to the data to be added. + * @n: the length of the data to be added. + * @recsize: size of record field + * + * This function copies @n bytes from the @from into the + * FIFO and returns the number of bytes which cannot be copied. + * + * If the returned value is equal or less the @n value, the copy_from_user() + * functions has failed. Otherwise the record doesn't fit into the buffer. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. + */ +static inline __must_check unsigned int kfifo_from_user_rec(struct kfifo *fifo, + const void __user *from, unsigned int n, unsigned int recsize) +{ + if (!__builtin_constant_p(recsize)) + return __kfifo_from_user_generic(fifo, from, n, recsize); + return __kfifo_from_user_rec(fifo, from, n, recsize); +} + +/** + * __kfifo_to_user_... internal functions for transfer fifo data into user space + * do not call it directly, use kfifo_to_user_rec() instead + */ +extern unsigned int __kfifo_to_user_n(struct kfifo *fifo, + void __user *to, unsigned int n, unsigned int reclen, + unsigned int recsize); + +extern unsigned int __kfifo_to_user_generic(struct kfifo *fifo, + void __user *to, unsigned int n, unsigned int recsize, + unsigned int *total); + +static inline unsigned int __kfifo_to_user_rec(struct kfifo *fifo, + void __user *to, unsigned int n, + unsigned int recsize, unsigned int *total) +{ + unsigned int l; + + if (!recsize) { + l = n; + if (total) + *total = l; + } else { + l = __kfifo_peek_n(fifo, recsize); + if (total) + *total = l; + if (n < l) + return l; + } + + return __kfifo_to_user_n(fifo, to, n, l, recsize); +} + +/** + * kfifo_to_user_rec - gets data from the FIFO and write it to user space + * @fifo: the fifo to be used. + * @to: where the data must be copied. + * @n: the size of the destination buffer. + * @recsize: size of record field + * @total: pointer where the total number of to copied bytes should stored + * + * This function copies at most @n bytes from the FIFO to the @to. + * In case of an error, the function returns the number of bytes which cannot + * be copied. + * If the returned value is equal or less the @n value, the copy_to_user() + * functions has failed. Otherwise the record doesn't fit into the @to buffer. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. + */ +static inline __must_check unsigned int kfifo_to_user_rec(struct kfifo *fifo, + void __user *to, unsigned int n, unsigned int recsize, + unsigned int *total) +{ + if (!__builtin_constant_p(recsize)) + return __kfifo_to_user_generic(fifo, to, n, recsize, total); + return __kfifo_to_user_rec(fifo, to, n, recsize, total); +} + +/** + * __kfifo_peek_... internal functions for peek into the next fifo record + * do not call it directly, use kfifo_peek_rec() instead + */ +extern unsigned int __kfifo_peek_generic(struct kfifo *fifo, + unsigned int recsize); + +/** + * kfifo_peek_rec - gets the size of the next FIFO record data + * @fifo: the fifo to be used. + * @recsize: size of record field + * + * This function returns the size of the next FIFO record in number of bytes + */ +static inline __must_check unsigned int kfifo_peek_rec(struct kfifo *fifo, + unsigned int recsize) +{ + if (!__builtin_constant_p(recsize)) + return __kfifo_peek_generic(fifo, recsize); + if (!recsize) + return kfifo_len(fifo); + return __kfifo_peek_n(fifo, recsize); +} + +/** + * __kfifo_skip_... internal functions for skip the next fifo record + * do not call it directly, use kfifo_skip_rec() instead + */ +extern void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize); + +static inline void __kfifo_skip_rec(struct kfifo *fifo, + unsigned int recsize) +{ + unsigned int l; + + if (recsize) { + l = __kfifo_peek_n(fifo, recsize); + + if (l + recsize <= kfifo_len(fifo)) { + __kfifo_add_out(fifo, l + recsize); + return; + } + } + kfifo_reset_out(fifo); +} + +/** + * kfifo_skip_rec - skip the next fifo out record + * @fifo: the fifo to be used. + * @recsize: size of record field + * + * This function skips the next FIFO record + */ +static inline void kfifo_skip_rec(struct kfifo *fifo, + unsigned int recsize) +{ + if (!__builtin_constant_p(recsize)) + __kfifo_skip_generic(fifo, recsize); + else + __kfifo_skip_rec(fifo, recsize); +} + +/** + * kfifo_avail_rec - returns the number of bytes available in a record FIFO + * @fifo: the fifo to be used. + * @recsize: size of record field + */ +static inline __must_check unsigned int kfifo_avail_rec(struct kfifo *fifo, + unsigned int recsize) +{ + unsigned int l = kfifo_size(fifo) - kfifo_len(fifo); + + return (l > recsize) ? l - recsize : 0; +} + #endif diff --git a/include/linux/memory.h b/include/linux/memory.h index 37fa19b34ef..1adfe779eb9 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -50,6 +50,19 @@ struct memory_notify { int status_change_nid; }; +/* + * During pageblock isolation, count the number of pages within the + * range [start_pfn, start_pfn + nr_pages) which are owned by code + * in the notifier chain. + */ +#define MEM_ISOLATE_COUNT (1<<0) + +struct memory_isolate_notify { + unsigned long start_pfn; /* Start of range to check */ + unsigned int nr_pages; /* # pages in range to check */ + unsigned int pages_found; /* # pages owned found by callbacks */ +}; + struct notifier_block; struct mem_section; @@ -76,14 +89,28 @@ static inline int memory_notify(unsigned long val, void *v) { return 0; } +static inline int register_memory_isolate_notifier(struct notifier_block *nb) +{ + return 0; +} +static inline void unregister_memory_isolate_notifier(struct notifier_block *nb) +{ +} +static inline int memory_isolate_notify(unsigned long val, void *v) +{ + return 0; +} #else extern int register_memory_notifier(struct notifier_block *nb); extern void unregister_memory_notifier(struct notifier_block *nb); +extern int register_memory_isolate_notifier(struct notifier_block *nb); +extern void unregister_memory_isolate_notifier(struct notifier_block *nb); extern int register_new_memory(int, struct mem_section *); extern int unregister_memory_section(struct mem_section *); extern int memory_dev_init(void); extern int remove_memory_block(unsigned long, struct mem_section *, int); extern int memory_notify(unsigned long val, void *v); +extern int memory_isolate_notify(unsigned long val, void *v); extern struct memory_block *find_memory_block(struct mem_section *); #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT) enum mem_add_context { BOOT, HOTPLUG }; diff --git a/include/linux/namei.h b/include/linux/namei.h index 02894675028..05b441d9364 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -72,8 +72,6 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *, extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, int (*open)(struct inode *, struct file *)); -extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); -extern void release_open_intent(struct nameidata *); extern struct dentry *lookup_one_len(const char *, struct dentry *, int); diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 7394e3bc8f4..ff92b46f515 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -28,6 +28,7 @@ #include <linux/mutex.h> #include <linux/timer.h> #include <linux/workqueue.h> +#include <linux/kfifo.h> #include <scsi/iscsi_proto.h> #include <scsi/iscsi_if.h> #include <scsi/scsi_transport_iscsi.h> @@ -231,7 +232,7 @@ struct iscsi_conn { }; struct iscsi_pool { - struct kfifo *queue; /* FIFO Queue */ + struct kfifo queue; /* FIFO Queue */ void **pool; /* Pool of elements */ int max; /* Max number of elements */ }; diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h index 9e3182e659d..741ae7ed439 100644 --- a/include/scsi/libiscsi_tcp.h +++ b/include/scsi/libiscsi_tcp.h @@ -80,7 +80,7 @@ struct iscsi_tcp_task { int data_offset; struct iscsi_r2t_info *r2t; /* in progress solict R2T */ struct iscsi_pool r2tpool; - struct kfifo *r2tqueue; + struct kfifo r2tqueue; void *dd_data; }; diff --git a/include/scsi/libsrp.h b/include/scsi/libsrp.h index ba615e4c1d7..07e3adde21d 100644 --- a/include/scsi/libsrp.h +++ b/include/scsi/libsrp.h @@ -21,7 +21,7 @@ struct srp_buf { struct srp_queue { void *pool; void *items; - struct kfifo *queue; + struct kfifo queue; spinlock_t lock; }; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 267e484f019..fc0f928167e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -250,7 +250,6 @@ struct audit_context { #endif }; -#define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE]) static inline int open_arg(int flags, int mask) { int n = ACC_MODE(flags); diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 3765ff3c1bb..e92d519f93b 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -1,6 +1,7 @@ /* - * A simple kernel FIFO implementation. + * A generic kernel FIFO implementation. * + * Copyright (C) 2009 Stefani Seibold <stefani@seibold.net> * Copyright (C) 2004 Stelian Pop <stelian@popies.net> * * This program is free software; you can redistribute it and/or modify @@ -25,50 +26,48 @@ #include <linux/err.h> #include <linux/kfifo.h> #include <linux/log2.h> +#include <linux/uaccess.h> + +static void _kfifo_init(struct kfifo *fifo, unsigned char *buffer, + unsigned int size) +{ + fifo->buffer = buffer; + fifo->size = size; + + kfifo_reset(fifo); +} /** - * kfifo_init - allocates a new FIFO using a preallocated buffer + * kfifo_init - initialize a FIFO using a preallocated buffer + * @fifo: the fifo to assign the buffer * @buffer: the preallocated buffer to be used. * @size: the size of the internal buffer, this have to be a power of 2. - * @gfp_mask: get_free_pages mask, passed to kmalloc() - * @lock: the lock to be used to protect the fifo buffer * - * Do NOT pass the kfifo to kfifo_free() after use! Simply free the - * &struct kfifo with kfree(). */ -struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, - gfp_t gfp_mask, spinlock_t *lock) +void kfifo_init(struct kfifo *fifo, unsigned char *buffer, unsigned int size) { - struct kfifo *fifo; - /* size must be a power of 2 */ BUG_ON(!is_power_of_2(size)); - fifo = kmalloc(sizeof(struct kfifo), gfp_mask); - if (!fifo) - return ERR_PTR(-ENOMEM); - - fifo->buffer = buffer; - fifo->size = size; - fifo->in = fifo->out = 0; - fifo->lock = lock; - - return fifo; + _kfifo_init(fifo, buffer, size); } EXPORT_SYMBOL(kfifo_init); /** - * kfifo_alloc - allocates a new FIFO and its internal buffer - * @size: the size of the internal buffer to be allocated. + * kfifo_alloc - allocates a new FIFO internal buffer + * @fifo: the fifo to assign then new buffer + * @size: the size of the buffer to be allocated, this have to be a power of 2. * @gfp_mask: get_free_pages mask, passed to kmalloc() - * @lock: the lock to be used to protect the fifo buffer + * + * This function dynamically allocates a new fifo internal buffer * * The size will be rounded-up to a power of 2. + * The buffer will be release with kfifo_free(). + * Return 0 if no error, otherwise the an error code */ -struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) +int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask) { unsigned char *buffer; - struct kfifo *ret; /* * round up to the next power of 2, since our 'let the indices @@ -80,48 +79,91 @@ struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) } buffer = kmalloc(size, gfp_mask); - if (!buffer) - return ERR_PTR(-ENOMEM); - - ret = kfifo_init(buffer, size, gfp_mask, lock); + if (!buffer) { + _kfifo_init(fifo, 0, 0); + return -ENOMEM; + } - if (IS_ERR(ret)) - kfree(buffer); + _kfifo_init(fifo, buffer, size); - return ret; + return 0; } EXPORT_SYMBOL(kfifo_alloc); /** - * kfifo_free - frees the FIFO + * kfifo_free - frees the FIFO internal buffer * @fifo: the fifo to be freed. */ void kfifo_free(struct kfifo *fifo) { kfree(fifo->buffer); - kfree(fifo); } EXPORT_SYMBOL(kfifo_free); /** - * __kfifo_put - puts some data into the FIFO, no locking version + * kfifo_skip - skip output data * @fifo: the fifo to be used. - * @buffer: the data to be added. - * @len: the length of the data to be added. - * - * This function copies at most @len bytes from the @buffer into - * the FIFO depending on the free space, and returns the number of - * bytes copied. - * - * Note that with only one concurrent reader and one concurrent - * writer, you don't need extra locking to use these functions. + * @len: number of bytes to skip */ -unsigned int __kfifo_put(struct kfifo *fifo, - const unsigned char *buffer, unsigned int len) +void kfifo_skip(struct kfifo *fifo, unsigned int len) +{ + if (len < kfifo_len(fifo)) { + __kfifo_add_out(fifo, len); + return; + } + kfifo_reset_out(fifo); +} +EXPORT_SYMBOL(kfifo_skip); + +static inline void __kfifo_in_data(struct kfifo *fifo, + const void *from, unsigned int len, unsigned int off) { unsigned int l; - len = min(len, fifo->size - fifo->in + fifo->out); + /* + * Ensure that we sample the fifo->out index -before- we + * start putting bytes into the kfifo. + */ + + smp_mb(); + + off = __kfifo_off(fifo, fifo->in + off); + + /* first put the data starting from fifo->in to buffer end */ + l = min(len, fifo->size - off); + memcpy(fifo->buffer + off, from, l); + + /* then put the rest (if any) at the beginning of the buffer */ + memcpy(fifo->buffer, from + l, len - l); +} + +static inline void __kfifo_out_data(struct kfifo *fifo, + void *to, unsigned int len, unsigned int off) +{ + unsigned int l; + + /* + * Ensure that we sample the fifo->in index -before- we + * start removing bytes from the kfifo. + */ + + smp_rmb(); + + off = __kfifo_off(fifo, fifo->out + off); + + /* first get the data from fifo->out until the end of the buffer */ + l = min(len, fifo->size - off); + memcpy(to, fifo->buffer + off, l); + + /* then get the rest (if any) from the beginning of the buffer */ + memcpy(to + l, fifo->buffer, len - l); +} + +static inline unsigned int __kfifo_from_user_data(struct kfifo *fifo, + const void __user *from, unsigned int len, unsigned int off) +{ + unsigned int l; + int ret; /* * Ensure that we sample the fifo->out index -before- we @@ -130,68 +172,229 @@ unsigned int __kfifo_put(struct kfifo *fifo, smp_mb(); + off = __kfifo_off(fifo, fifo->in + off); + /* first put the data starting from fifo->in to buffer end */ - l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); - memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); + l = min(len, fifo->size - off); + ret = copy_from_user(fifo->buffer + off, from, l); + + if (unlikely(ret)) + return ret + len - l; /* then put the rest (if any) at the beginning of the buffer */ - memcpy(fifo->buffer, buffer + l, len - l); + return copy_from_user(fifo->buffer, from + l, len - l); +} + +static inline unsigned int __kfifo_to_user_data(struct kfifo *fifo, + void __user *to, unsigned int len, unsigned int off) +{ + unsigned int l; + int ret; /* - * Ensure that we add the bytes to the kfifo -before- - * we update the fifo->in index. + * Ensure that we sample the fifo->in index -before- we + * start removing bytes from the kfifo. */ - smp_wmb(); + smp_rmb(); + + off = __kfifo_off(fifo, fifo->out + off); + + /* first get the data from fifo->out until the end of the buffer */ + l = min(len, fifo->size - off); + ret = copy_to_user(to, fifo->buffer + off, l); + + if (unlikely(ret)) + return ret + len - l; + + /* then get the rest (if any) from the beginning of the buffer */ + return copy_to_user(to + l, fifo->buffer, len - l); +} + +unsigned int __kfifo_in_n(struct kfifo *fifo, + const void *from, unsigned int len, unsigned int recsize) +{ + if (kfifo_avail(fifo) < len + recsize) + return len + 1; + + __kfifo_in_data(fifo, from, len, recsize); + return 0; +} +EXPORT_SYMBOL(__kfifo_in_n); - fifo->in += len; +/** + * kfifo_in - puts some data into the FIFO + * @fifo: the fifo to be used. + * @from: the data to be added. + * @len: the length of the data to be added. + * + * This function copies at most @len bytes from the @from buffer into + * the FIFO depending on the free space, and returns the number of + * bytes copied. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. + */ +unsigned int kfifo_in(struct kfifo *fifo, const unsigned char *from, + unsigned int len) +{ + len = min(kfifo_avail(fifo), len); + __kfifo_in_data(fifo, from, len, 0); + __kfifo_add_in(fifo, len); return len; } -EXPORT_SYMBOL(__kfifo_put); +EXPORT_SYMBOL(kfifo_in); + +unsigned int __kfifo_in_generic(struct kfifo *fifo, + const void *from, unsigned int len, unsigned int recsize) +{ + return __kfifo_in_rec(fifo, from, len, recsize); +} +EXPORT_SYMBOL(__kfifo_in_generic); + +unsigned int __kfifo_out_n(struct kfifo *fifo, + void *to, unsigned int len, unsigned int recsize) +{ + if (kfifo_len(fifo) < len + recsize) + return len; + + __kfifo_out_data(fifo, to, len, recsize); + __kfifo_add_out(fifo, len + recsize); + return 0; +} +EXPORT_SYMBOL(__kfifo_out_n); /** - * __kfifo_get - gets some data from the FIFO, no locking version + * kfifo_out - gets some data from the FIFO * @fifo: the fifo to be used. - * @buffer: where the data must be copied. + * @to: where the data must be copied. * @len: the size of the destination buffer. * * This function copies at most @len bytes from the FIFO into the - * @buffer and returns the number of copied bytes. + * @to buffer and returns the number of copied bytes. * * Note that with only one concurrent reader and one concurrent * writer, you don't need extra locking to use these functions. */ -unsigned int __kfifo_get(struct kfifo *fifo, - unsigned char *buffer, unsigned int len) +unsigned int kfifo_out(struct kfifo *fifo, unsigned char *to, unsigned int len) { - unsigned int l; + len = min(kfifo_len(fifo), len); - len = min(len, fifo->in - fifo->out); + __kfifo_out_data(fifo, to, len, 0); + __kfifo_add_out(fifo, len); - /* - * Ensure that we sample the fifo->in index -before- we - * start removing bytes from the kfifo. - */ + return len; +} +EXPORT_SYMBOL(kfifo_out); - smp_rmb(); +unsigned int __kfifo_out_generic(struct kfifo *fifo, + void *to, unsigned int len, unsigned int recsize, + unsigned int *total) +{ + return __kfifo_out_rec(fifo, to, len, recsize, total); +} +EXPORT_SYMBOL(__kfifo_out_generic); - /* first get the data from fifo->out until the end of the buffer */ - l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); - memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); +unsigned int __kfifo_from_user_n(struct kfifo *fifo, + const void __user *from, unsigned int len, unsigned int recsize) +{ + if (kfifo_avail(fifo) < len + recsize) + return len + 1; - /* then get the rest (if any) from the beginning of the buffer */ - memcpy(buffer + l, fifo->buffer, len - l); + return __kfifo_from_user_data(fifo, from, len, recsize); +} +EXPORT_SYMBOL(__kfifo_from_user_n); - /* - * Ensure that we remove the bytes from the kfifo -before- - * we update the fifo->out index. - */ +/** + * kfifo_from_user - puts some data from user space into the FIFO + * @fifo: the fifo to be used. + * @from: pointer to the data to be added. + * @len: the length of the data to be added. + * + * This function copies at most @len bytes from the @from into the + * FIFO depending and returns the number of copied bytes. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. + */ +unsigned int kfifo_from_user(struct kfifo *fifo, + const void __user *from, unsigned int len) +{ + len = min(kfifo_avail(fifo), len); + len -= __kfifo_from_user_data(fifo, from, len, 0); + __kfifo_add_in(fifo, len); + return len; +} +EXPORT_SYMBOL(kfifo_from_user); - smp_mb(); +unsigned int __kfifo_from_user_generic(struct kfifo *fifo, + const void __user *from, unsigned int len, unsigned int recsize) +{ + return __kfifo_from_user_rec(fifo, from, len, recsize); +} +EXPORT_SYMBOL(__kfifo_from_user_generic); - fifo->out += len; +unsigned int __kfifo_to_user_n(struct kfifo *fifo, + void __user *to, unsigned int len, unsigned int reclen, + unsigned int recsize) +{ + unsigned int ret; + + if (kfifo_len(fifo) < reclen + recsize) + return len; + + ret = __kfifo_to_user_data(fifo, to, reclen, recsize); + if (likely(ret == 0)) + __kfifo_add_out(fifo, reclen + recsize); + + return ret; +} +EXPORT_SYMBOL(__kfifo_to_user_n); + +/** + * kfifo_to_user - gets data from the FIFO and write it to user space + * @fifo: the fifo to be used. + * @to: where the data must be copied. + * @len: the size of the destination buffer. + * + * This function copies at most @len bytes from the FIFO into the + * @to buffer and returns the number of copied bytes. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. + */ +unsigned int kfifo_to_user(struct kfifo *fifo, + void __user *to, unsigned int len) +{ + len = min(kfifo_len(fifo), len); + len -= __kfifo_to_user_data(fifo, to, len, 0); + __kfifo_add_out(fifo, len); return len; } -EXPORT_SYMBOL(__kfifo_get); +EXPORT_SYMBOL(kfifo_to_user); + +unsigned int __kfifo_to_user_generic(struct kfifo *fifo, + void __user *to, unsigned int len, unsigned int recsize, + unsigned int *total) +{ + return __kfifo_to_user_rec(fifo, to, len, recsize, total); +} +EXPORT_SYMBOL(__kfifo_to_user_generic); + +unsigned int __kfifo_peek_generic(struct kfifo *fifo, unsigned int recsize) +{ + if (recsize == 0) + return kfifo_avail(fifo); + + return __kfifo_peek_n(fifo, recsize); +} +EXPORT_SYMBOL(__kfifo_peek_generic); + +void __kfifo_skip_generic(struct kfifo *fifo, unsigned int recsize) +{ + __kfifo_skip_rec(fifo, recsize); +} +EXPORT_SYMBOL(__kfifo_skip_generic); + diff --git a/kernel/perf_event.c b/kernel/perf_event.c index e0eb4a2fe18..1f38270f08c 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -4724,7 +4724,7 @@ SYSCALL_DEFINE5(perf_event_open, if (IS_ERR(event)) goto err_put_context; - err = anon_inode_getfd("[perf_event]", &perf_fops, event, 0); + err = anon_inode_getfd("[perf_event]", &perf_fops, event, O_RDWR); if (err < 0) goto err_free_put_context; diff --git a/kernel/resource.c b/kernel/resource.c index dc15686b7a7..af96c1e4b54 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -308,37 +308,37 @@ static int find_resource(struct resource *root, struct resource *new, void *alignf_data) { struct resource *this = root->child; - resource_size_t start, end; + struct resource tmp = *new; - start = root->start; + tmp.start = root->start; /* * Skip past an allocated resource that starts at 0, since the assignment - * of this->start - 1 to new->end below would cause an underflow. + * of this->start - 1 to tmp->end below would cause an underflow. */ if (this && this->start == 0) { - start = this->end + 1; + tmp.start = this->end + 1; this = this->sibling; } for(;;) { if (this) - end = this->start - 1; + tmp.end = this->start - 1; else - end = root->end; - if (start < min) - start = min; - if (end > max) - end = max; - start = ALIGN(start, align); + tmp.end = root->end; + if (tmp.start < min) + tmp.start = min; + if (tmp.end > max) + tmp.end = max; + tmp.start = ALIGN(tmp.start, align); if (alignf) - alignf(alignf_data, new, size, align); - if (start < end && end - start >= size - 1) { - new->start = start; - new->end = start + size - 1; + alignf(alignf_data, &tmp, size, align); + if (tmp.start < tmp.end && tmp.end - tmp.start >= size - 1) { + new->start = tmp.start; + new->end = tmp.start + size - 1; return 0; } if (!this) break; - start = this->end + 1; + tmp.start = this->end + 1; this = this->sibling; } return -EBUSY; diff --git a/kernel/sched.c b/kernel/sched.c index 720df108a2d..87f1f47beff 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -26,8 +26,6 @@ * Thomas Gleixner, Mike Kravetz */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/mm.h> #include <linux/module.h> #include <linux/nmi.h> @@ -2348,7 +2346,7 @@ int select_task_rq(struct task_struct *p, int sd_flags, int wake_flags) * not worry about this generic constraint ] */ if (unlikely(!cpumask_test_cpu(cpu, &p->cpus_allowed) || - !cpu_active(cpu))) + !cpu_online(cpu))) cpu = select_fallback_rq(task_cpu(p), p); return cpu; @@ -5375,8 +5373,8 @@ static noinline void __schedule_bug(struct task_struct *prev) { struct pt_regs *regs = get_irq_regs(); - pr_err("BUG: scheduling while atomic: %s/%d/0x%08x\n", - prev->comm, prev->pid, preempt_count()); + printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n", + prev->comm, prev->pid, preempt_count()); debug_show_held_locks(prev); print_modules(); @@ -6940,23 +6938,23 @@ void sched_show_task(struct task_struct *p) unsigned state; state = p->state ? __ffs(p->state) + 1 : 0; - pr_info("%-13.13s %c", p->comm, + printk(KERN_INFO "%-13.13s %c", p->comm, state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?'); #if BITS_PER_LONG == 32 if (state == TASK_RUNNING) - pr_cont(" running "); + printk(KERN_CONT " running "); else - pr_cont(" %08lx ", thread_saved_pc(p)); + printk(KERN_CONT " %08lx ", thread_saved_pc(p)); #else if (state == TASK_RUNNING) - pr_cont(" running task "); + printk(KERN_CONT " running task "); else - pr_cont(" %016lx ", thread_saved_pc(p)); + printk(KERN_CONT " %016lx ", thread_saved_pc(p)); #endif #ifdef CONFIG_DEBUG_STACK_USAGE free = stack_not_used(p); #endif - pr_cont("%5lu %5d %6d 0x%08lx\n", free, + printk(KERN_CONT "%5lu %5d %6d 0x%08lx\n", free, task_pid_nr(p), task_pid_nr(p->real_parent), (unsigned long)task_thread_info(p)->flags); @@ -6968,9 +6966,11 @@ void show_state_filter(unsigned long state_filter) struct task_struct *g, *p; #if BITS_PER_LONG == 32 - pr_info(" task PC stack pid father\n"); + printk(KERN_INFO + " task PC stack pid father\n"); #else - pr_info(" task PC stack pid father\n"); + printk(KERN_INFO + " task PC stack pid father\n"); #endif read_lock(&tasklist_lock); do_each_thread(g, p) { @@ -7828,44 +7828,48 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level, printk(KERN_DEBUG "%*s domain %d: ", level, "", level); if (!(sd->flags & SD_LOAD_BALANCE)) { - pr_cont("does not load-balance\n"); + printk("does not load-balance\n"); if (sd->parent) - pr_err("ERROR: !SD_LOAD_BALANCE domain has parent\n"); + printk(KERN_ERR "ERROR: !SD_LOAD_BALANCE domain" + " has parent"); return -1; } - pr_cont("span %s level %s\n", str, sd->name); + printk(KERN_CONT "span %s level %s\n", str, sd->name); if (!cpumask_test_cpu(cpu, sched_domain_span(sd))) { - pr_err("ERROR: domain->span does not contain CPU%d\n", cpu); + printk(KERN_ERR "ERROR: domain->span does not contain " + "CPU%d\n", cpu); } if (!cpumask_test_cpu(cpu, sched_group_cpus(group))) { - pr_err("ERROR: domain->groups does not contain CPU%d\n", cpu); + printk(KERN_ERR "ERROR: domain->groups does not contain" + " CPU%d\n", cpu); } printk(KERN_DEBUG "%*s groups:", level + 1, ""); do { if (!group) { - pr_cont("\n"); - pr_err("ERROR: group is NULL\n"); + printk("\n"); + printk(KERN_ERR "ERROR: group is NULL\n"); break; } if (!group->cpu_power) { - pr_cont("\n"); - pr_err("ERROR: domain->cpu_power not set\n"); + printk(KERN_CONT "\n"); + printk(KERN_ERR "ERROR: domain->cpu_power not " + "set\n"); break; } if (!cpumask_weight(sched_group_cpus(group))) { - pr_cont("\n"); - pr_err("ERROR: empty group\n"); + printk(KERN_CONT "\n"); + printk(KERN_ERR "ERROR: empty group\n"); break; } if (cpumask_intersects(groupmask, sched_group_cpus(group))) { - pr_cont("\n"); - pr_err("ERROR: repeated CPUs\n"); + printk(KERN_CONT "\n"); + printk(KERN_ERR "ERROR: repeated CPUs\n"); break; } @@ -7873,21 +7877,23 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level, cpulist_scnprintf(str, sizeof(str), sched_group_cpus(group)); - pr_cont(" %s", str); + printk(KERN_CONT " %s", str); if (group->cpu_power != SCHED_LOAD_SCALE) { - pr_cont(" (cpu_power = %d)", group->cpu_power); + printk(KERN_CONT " (cpu_power = %d)", + group->cpu_power); } group = group->next; } while (group != sd->groups); - pr_cont("\n"); + printk(KERN_CONT "\n"); if (!cpumask_equal(sched_domain_span(sd), groupmask)) - pr_err("ERROR: groups don't span domain->span\n"); + printk(KERN_ERR "ERROR: groups don't span domain->span\n"); if (sd->parent && !cpumask_subset(groupmask, sched_domain_span(sd->parent))) - pr_err("ERROR: parent span is not a superset of domain->span\n"); + printk(KERN_ERR "ERROR: parent span is not a superset " + "of domain->span\n"); return 0; } @@ -8443,7 +8449,8 @@ static int build_numa_sched_groups(struct s_data *d, sg = kmalloc_node(sizeof(struct sched_group) + cpumask_size(), GFP_KERNEL, num); if (!sg) { - pr_warning("Can not alloc domain group for node %d\n", num); + printk(KERN_WARNING "Can not alloc domain group for node %d\n", + num); return -ENOMEM; } d->sched_group_nodes[num] = sg; @@ -8472,8 +8479,8 @@ static int build_numa_sched_groups(struct s_data *d, sg = kmalloc_node(sizeof(struct sched_group) + cpumask_size(), GFP_KERNEL, num); if (!sg) { - pr_warning("Can not alloc domain group for node %d\n", - j); + printk(KERN_WARNING + "Can not alloc domain group for node %d\n", j); return -ENOMEM; } sg->cpu_power = 0; @@ -8701,7 +8708,7 @@ static enum s_alloc __visit_domain_allocation_hell(struct s_data *d, d->sched_group_nodes = kcalloc(nr_node_ids, sizeof(struct sched_group *), GFP_KERNEL); if (!d->sched_group_nodes) { - pr_warning("Can not alloc sched group node list\n"); + printk(KERN_WARNING "Can not alloc sched group node list\n"); return sa_notcovered; } sched_group_nodes_bycpu[cpumask_first(cpu_map)] = d->sched_group_nodes; @@ -8718,7 +8725,7 @@ static enum s_alloc __visit_domain_allocation_hell(struct s_data *d, return sa_send_covered; d->rd = alloc_rootdomain(); if (!d->rd) { - pr_warning("Cannot alloc root domain\n"); + printk(KERN_WARNING "Cannot alloc root domain\n"); return sa_tmpmask; } return sa_rootdomain; @@ -9700,11 +9707,13 @@ void __might_sleep(char *file, int line, int preempt_offset) return; prev_jiffy = jiffies; - pr_err("BUG: sleeping function called from invalid context at %s:%d\n", - file, line); - pr_err("in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n", - in_atomic(), irqs_disabled(), - current->pid, current->comm); + printk(KERN_ERR + "BUG: sleeping function called from invalid context at %s:%d\n", + file, line); + printk(KERN_ERR + "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n", + in_atomic(), irqs_disabled(), + current->pid, current->comm); debug_show_held_locks(current); if (irqs_disabled()) diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c index 21b969a2872..5f93b570d38 100644 --- a/kernel/sched_idletask.c +++ b/kernel/sched_idletask.c @@ -35,7 +35,7 @@ static void dequeue_task_idle(struct rq *rq, struct task_struct *p, int sleep) { raw_spin_unlock_irq(&rq->lock); - pr_err("bad: scheduling from the idle thread!\n"); + printk(KERN_ERR "bad: scheduling from the idle thread!\n"); dump_stack(); raw_spin_lock_irq(&rq->lock); } diff --git a/kernel/time.c b/kernel/time.c index c6324d96009..804798005d1 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -136,6 +136,7 @@ static inline void warp_clock(void) write_seqlock_irq(&xtime_lock); wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60; xtime.tv_sec += sys_tz.tz_minuteswest * 60; + update_xtime_cache(0); write_sequnlock_irq(&xtime_lock); clock_was_set(); } diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index af4135f0582..7faaa32fbf4 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -165,6 +165,13 @@ struct timespec raw_time; /* flag for if timekeeping is suspended */ int __read_mostly timekeeping_suspended; +static struct timespec xtime_cache __attribute__ ((aligned (16))); +void update_xtime_cache(u64 nsec) +{ + xtime_cache = xtime; + timespec_add_ns(&xtime_cache, nsec); +} + /* must hold xtime_lock */ void timekeeping_leap_insert(int leapsecond) { @@ -325,6 +332,8 @@ int do_settimeofday(struct timespec *tv) xtime = *tv; + update_xtime_cache(0); + timekeeper.ntp_error = 0; ntp_clear(); @@ -550,6 +559,7 @@ void __init timekeeping_init(void) } set_normalized_timespec(&wall_to_monotonic, -boot.tv_sec, -boot.tv_nsec); + update_xtime_cache(0); total_sleep_time.tv_sec = 0; total_sleep_time.tv_nsec = 0; write_sequnlock_irqrestore(&xtime_lock, flags); @@ -583,6 +593,7 @@ static int timekeeping_resume(struct sys_device *dev) wall_to_monotonic = timespec_sub(wall_to_monotonic, ts); total_sleep_time = timespec_add_safe(total_sleep_time, ts); } + update_xtime_cache(0); /* re-base the last cycle value */ timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); timekeeper.ntp_error = 0; @@ -722,6 +733,7 @@ static void timekeeping_adjust(s64 offset) timekeeper.ntp_error_shift; } + /** * logarithmic_accumulation - shifted accumulation of cycles * @@ -765,6 +777,7 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) return offset; } + /** * update_wall_time - Uses the current clocksource to increment the wall time * @@ -774,6 +787,7 @@ void update_wall_time(void) { struct clocksource *clock; cycle_t offset; + u64 nsecs; int shift = 0, maxshift; /* Make sure we're fully resumed: */ @@ -839,6 +853,9 @@ void update_wall_time(void) timekeeper.ntp_error += timekeeper.xtime_nsec << timekeeper.ntp_error_shift; + nsecs = clocksource_cyc2ns(offset, timekeeper.mult, timekeeper.shift); + update_xtime_cache(nsecs); + /* check to see if there is a new clocksource to use */ update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult); } @@ -875,13 +892,13 @@ void monotonic_to_bootbased(struct timespec *ts) unsigned long get_seconds(void) { - return xtime.tv_sec; + return xtime_cache.tv_sec; } EXPORT_SYMBOL(get_seconds); struct timespec __current_kernel_time(void) { - return xtime; + return xtime_cache; } struct timespec current_kernel_time(void) @@ -891,7 +908,8 @@ struct timespec current_kernel_time(void) do { seq = read_seqbegin(&xtime_lock); - now = xtime; + + now = xtime_cache; } while (read_seqretry(&xtime_lock, seq)); return now; @@ -905,7 +923,8 @@ struct timespec get_monotonic_coarse(void) do { seq = read_seqbegin(&xtime_lock); - now = xtime; + + now = xtime_cache; mono = wall_to_monotonic; } while (read_seqretry(&xtime_lock, seq)); diff --git a/lib/string.c b/lib/string.c index afce96af3af..9f75b4ec50b 100644 --- a/lib/string.c +++ b/lib/string.c @@ -338,10 +338,10 @@ EXPORT_SYMBOL(strnchr); #endif /** - * skip_spaces - Removes leading whitespace from @s. - * @s: The string to be stripped. + * skip_spaces - Removes leading whitespace from @str. + * @str: The string to be stripped. * - * Returns a pointer to the first non-whitespace character in @s. + * Returns a pointer to the first non-whitespace character in @str. */ char *skip_spaces(const char *str) { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4e869657cb5..d79b9258056 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -48,6 +48,7 @@ #include <linux/page_cgroup.h> #include <linux/debugobjects.h> #include <linux/kmemleak.h> +#include <linux/memory.h> #include <trace/events/kmem.h> #include <asm/tlbflush.h> @@ -5008,23 +5009,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, int set_migratetype_isolate(struct page *page) { struct zone *zone; - unsigned long flags; + struct page *curr_page; + unsigned long flags, pfn, iter; + unsigned long immobile = 0; + struct memory_isolate_notify arg; + int notifier_ret; int ret = -EBUSY; int zone_idx; zone = page_zone(page); zone_idx = zone_idx(zone); + spin_lock_irqsave(&zone->lock, flags); + if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE || + zone_idx == ZONE_MOVABLE) { + ret = 0; + goto out; + } + + pfn = page_to_pfn(page); + arg.start_pfn = pfn; + arg.nr_pages = pageblock_nr_pages; + arg.pages_found = 0; + /* - * In future, more migrate types will be able to be isolation target. + * It may be possible to isolate a pageblock even if the + * migratetype is not MIGRATE_MOVABLE. The memory isolation + * notifier chain is used by balloon drivers to return the + * number of pages in a range that are held by the balloon + * driver to shrink memory. If all the pages are accounted for + * by balloons, are free, or on the LRU, isolation can continue. + * Later, for example, when memory hotplug notifier runs, these + * pages reported as "can be isolated" should be isolated(freed) + * by the balloon driver through the memory notifier chain. */ - if (get_pageblock_migratetype(page) != MIGRATE_MOVABLE && - zone_idx != ZONE_MOVABLE) + notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); + notifier_ret = notifier_to_errno(notifier_ret); + if (notifier_ret || !arg.pages_found) goto out; - set_pageblock_migratetype(page, MIGRATE_ISOLATE); - move_freepages_block(zone, page, MIGRATE_ISOLATE); - ret = 0; + + for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) { + if (!pfn_valid_within(pfn)) + continue; + + curr_page = pfn_to_page(iter); + if (!page_count(curr_page) || PageLRU(curr_page)) + continue; + + immobile++; + } + + if (arg.pages_found == immobile) + ret = 0; + out: + if (!ret) { + set_pageblock_migratetype(page, MIGRATE_ISOLATE); + move_freepages_block(zone, page, MIGRATE_ISOLATE); + } + spin_unlock_irqrestore(&zone->lock, flags); if (!ret) drain_all_pages(); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 569750010fd..18e7f5a43dc 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -770,7 +770,7 @@ static int hidp_setup_hid(struct hidp_session *session, hid = hid_allocate_device(); if (IS_ERR(hid)) - return PTR_ERR(session->hid); + return PTR_ERR(hid); session->hid = hid; session->req = req; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 5129b88c8e5..1120cf14a54 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1212,6 +1212,7 @@ static void l2cap_monitor_timeout(unsigned long arg) bh_lock_sock(sk); if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) { l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk); + bh_unlock_sock(sk); return; } @@ -3435,8 +3436,8 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str (pi->unacked_frames > 0)) __mod_retrans_timer(); - l2cap_ertm_send(sk); pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; + l2cap_ertm_send(sk); } break; @@ -3471,9 +3472,9 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; if (rx_control & L2CAP_CTRL_POLL) { - l2cap_retransmit_frame(sk, tx_seq); pi->expected_ack_seq = tx_seq; l2cap_drop_acked_frames(sk); + l2cap_retransmit_frame(sk, tx_seq); l2cap_ertm_send(sk); if (pi->conn_state & L2CAP_CONN_WAIT_F) { pi->srej_save_reqseq = tx_seq; diff --git a/net/dccp/probe.c b/net/dccp/probe.c index dc328425fa2..a1362dc8abb 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -43,7 +43,7 @@ static int bufsize = 64 * 1024; static const char procname[] = "dccpprobe"; static struct { - struct kfifo *fifo; + struct kfifo fifo; spinlock_t lock; wait_queue_head_t wait; struct timespec tstart; @@ -67,7 +67,7 @@ static void printl(const char *fmt, ...) len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); va_end(args); - kfifo_put(dccpw.fifo, tbuf, len); + kfifo_in_locked(&dccpw.fifo, tbuf, len, &dccpw.lock); wake_up(&dccpw.wait); } @@ -109,7 +109,7 @@ static struct jprobe dccp_send_probe = { static int dccpprobe_open(struct inode *inode, struct file *file) { - kfifo_reset(dccpw.fifo); + kfifo_reset(&dccpw.fifo); getnstimeofday(&dccpw.tstart); return 0; } @@ -131,11 +131,11 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf, return -ENOMEM; error = wait_event_interruptible(dccpw.wait, - __kfifo_len(dccpw.fifo) != 0); + kfifo_len(&dccpw.fifo) != 0); if (error) goto out_free; - cnt = kfifo_get(dccpw.fifo, tbuf, len); + cnt = kfifo_out_locked(&dccpw.fifo, tbuf, len, &dccpw.lock); error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0; out_free: @@ -156,10 +156,8 @@ static __init int dccpprobe_init(void) init_waitqueue_head(&dccpw.wait); spin_lock_init(&dccpw.lock); - dccpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &dccpw.lock); - if (IS_ERR(dccpw.fifo)) - return PTR_ERR(dccpw.fifo); - + if (kfifo_alloc(&dccpw.fifo, bufsize, GFP_KERNEL)) + return ret; if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops)) goto err0; @@ -172,14 +170,14 @@ static __init int dccpprobe_init(void) err1: proc_net_remove(&init_net, procname); err0: - kfifo_free(dccpw.fifo); + kfifo_free(&dccpw.fifo); return ret; } module_init(dccpprobe_init); static __exit void dccpprobe_exit(void) { - kfifo_free(dccpw.fifo); + kfifo_free(&dccpw.fifo); proc_net_remove(&init_net, procname); unregister_jprobe(&dccp_send_probe); diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 3b3a9560712..2cddea3bd6b 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -708,7 +708,8 @@ static void ip6_frags_ns_sysctl_unregister(struct net *net) table = net->ipv6.sysctl.frags_hdr->ctl_table_arg; unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr); - kfree(table); + if (!net_eq(net, &init_net)) + kfree(table); } static struct ctl_table_header *ip6_ctl_header; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index db3b2730389..c2bd74c5f8d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2630,6 +2630,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity; table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; + table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; } return table; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 8346938809b..9a6c58881c0 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -12,7 +12,6 @@ #include "common.h" #include "tomoyo.h" #include "realpath.h" -#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) /* * tomoyo_globally_readable_file_entry is a structure which is used for holding diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 1497dce1b04..c5699863643 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -172,14 +172,15 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) return v; } -static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun) +static inline void +aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask) { u32 val; int timeout = 5000; do { val = readl(aacirun->base + AACI_SR); - } while (val & (SR_TXB|SR_RXB) && timeout--); + } while (val & mask && timeout--); } @@ -208,8 +209,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) writel(0, aacirun->base + AACI_IE); return; } - ptr = aacirun->ptr; + spin_lock(&aacirun->lock); + + ptr = aacirun->ptr; do { unsigned int len = aacirun->fifosz; u32 val; @@ -217,9 +220,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) if (aacirun->bytes <= 0) { aacirun->bytes += aacirun->period; aacirun->ptr = ptr; - spin_unlock(&aaci->lock); + spin_unlock(&aacirun->lock); snd_pcm_period_elapsed(aacirun->substream); - spin_lock(&aaci->lock); + spin_lock(&aacirun->lock); } if (!(aacirun->cr & CR_EN)) break; @@ -245,7 +248,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) ptr = aacirun->start; } } while(1); + aacirun->ptr = ptr; + + spin_unlock(&aacirun->lock); } if (mask & ISR_URINTR) { @@ -263,6 +269,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) return; } + spin_lock(&aacirun->lock); + ptr = aacirun->ptr; do { unsigned int len = aacirun->fifosz; @@ -271,9 +279,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) if (aacirun->bytes <= 0) { aacirun->bytes += aacirun->period; aacirun->ptr = ptr; - spin_unlock(&aaci->lock); + spin_unlock(&aacirun->lock); snd_pcm_period_elapsed(aacirun->substream); - spin_lock(&aaci->lock); + spin_lock(&aacirun->lock); } if (!(aacirun->cr & CR_EN)) break; @@ -301,6 +309,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) } while (1); aacirun->ptr = ptr; + + spin_unlock(&aacirun->lock); } } @@ -310,7 +320,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) u32 mask; int i; - spin_lock(&aaci->lock); mask = readl(aaci->base + AACI_ALLINTS); if (mask) { u32 m = mask; @@ -320,7 +329,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) } } } - spin_unlock(&aaci->lock); return mask ? IRQ_HANDLED : IRQ_NONE; } @@ -330,63 +338,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) /* * ALSA support. */ - -struct aaci_stream { - unsigned char codec_idx; - unsigned char rate_idx; -}; - -static struct aaci_stream aaci_streams[] = { - [ACSTREAM_FRONT] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_FRONT_DAC, - }, - [ACSTREAM_SURROUND] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_SURR_DAC, - }, - [ACSTREAM_LFE] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_LFE_DAC, - }, -}; - -static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid) -{ - struct aaci_stream *s = aaci_streams + streamid; - return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx]; -} - -static unsigned int rate_list[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, - 48000, 64000, 88200, 96000, 176400, 192000 -}; - -/* - * Double-rate rule: we can support double rate iff channels == 2 - * (unimplemented) - */ -static int -aaci_rule_rate_by_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule) -{ - struct aaci *aaci = rule->private; - unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512; - struct snd_interval *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS); - - switch (c->max) { - case 6: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE); - case 4: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND); - case 2: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT); - } - - return snd_interval_list(hw_param_interval(p, rule->var), - ARRAY_SIZE(rate_list), rate_list, - rate_mask); -} - static struct snd_pcm_hardware aaci_hw_info = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | @@ -400,10 +351,7 @@ static struct snd_pcm_hardware aaci_hw_info = { */ .formats = SNDRV_PCM_FMTBIT_S16_LE, - /* should this be continuous or knot? */ - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_max = 48000, - .rate_min = 4000, + /* rates are setup from the AC'97 codec */ .channels_min = 2, .channels_max = 6, .buffer_bytes_max = 64 * 1024, @@ -423,6 +371,12 @@ static int __aaci_pcm_open(struct aaci *aaci, aacirun->substream = substream; runtime->private_data = aacirun; runtime->hw = aaci_hw_info; + runtime->hw.rates = aacirun->pcm->rates; + snd_pcm_limit_hw_rates(runtime); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + aacirun->pcm->r[1].slots) + snd_ac97_pcm_double_rate_rules(runtime); /* * FIXME: ALSA specifies fifo_size in bytes. If we're in normal @@ -433,17 +387,6 @@ static int __aaci_pcm_open(struct aaci *aaci, */ runtime->hw.fifo_size = aaci->fifosize * 2; - /* - * Add rule describing hardware rate dependency - * on the number of channels. - */ - ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - aaci_rule_rate_by_channels, aaci, - SNDRV_PCM_HW_PARAM_CHANNELS, - SNDRV_PCM_HW_PARAM_RATE, -1); - if (ret) - goto out; - ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED, DRIVER_NAME, aaci); if (ret) @@ -507,18 +450,22 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (err < 0) - goto out; + if (err >= 0) { + unsigned int rate = params_rate(params); + int dbl = rate > 48000; - err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), - params_channels(params), - aacirun->pcm->r[0].slots); - if (err) - goto out; + err = snd_ac97_pcm_open(aacirun->pcm, rate, + params_channels(params), + aacirun->pcm->r[dbl].slots); - aacirun->pcm_open = 1; + aacirun->pcm_open = err == 0; + aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; + aacirun->fifosz = aaci->fifosize * 4; + + if (aacirun->cr & CR_COMPACT) + aacirun->fifosz >>= 1; + } - out: return err; } @@ -527,7 +474,7 @@ static int aaci_pcm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct aaci_runtime *aacirun = runtime->private_data; - aacirun->start = (void *)runtime->dma_area; + aacirun->start = runtime->dma_area; aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream); aacirun->ptr = aacirun->start; aacirun->period = @@ -627,14 +574,9 @@ static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, * Enable FIFO, compact mode, 16 bits per sample. * FIXME: double rate slots? */ - if (ret >= 0) { - aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; + if (ret >= 0) aacirun->cr |= channels_to_txmask[channels]; - aacirun->fifosz = aaci->fifosize * 4; - if (aacirun->cr & CR_COMPACT) - aacirun->fifosz >>= 1; - } return ret; } @@ -646,7 +588,7 @@ static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) ie &= ~(IE_URIE|IE_TXIE); writel(ie, aacirun->base + AACI_IE); aacirun->cr &= ~CR_EN; - aaci_chan_wait_ready(aacirun); + aaci_chan_wait_ready(aacirun, SR_TXB); writel(aacirun->cr, aacirun->base + AACI_TXCR); } @@ -654,7 +596,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) { u32 ie; - aaci_chan_wait_ready(aacirun); + aaci_chan_wait_ready(aacirun, SR_TXB); aacirun->cr |= CR_EN; ie = readl(aacirun->base + AACI_IE); @@ -665,12 +607,12 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) { - struct aaci *aaci = substream->private_data; struct aaci_runtime *aacirun = substream->runtime->private_data; unsigned long flags; int ret = 0; - spin_lock_irqsave(&aaci->lock, flags); + spin_lock_irqsave(&aacirun->lock, flags); + switch (cmd) { case SNDRV_PCM_TRIGGER_START: aaci_pcm_playback_start(aacirun); @@ -697,7 +639,8 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm default: ret = -EINVAL; } - spin_unlock_irqrestore(&aaci->lock, flags); + + spin_unlock_irqrestore(&aacirun->lock, flags); return ret; } @@ -721,18 +664,10 @@ static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, int ret; ret = aaci_pcm_hw_params(substream, aacirun, params); - - if (ret >= 0) { - aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; - + if (ret >= 0) /* Line in record: slot 3 and 4 */ aacirun->cr |= CR_SL3 | CR_SL4; - aacirun->fifosz = aaci->fifosize * 4; - - if (aacirun->cr & CR_COMPACT) - aacirun->fifosz >>= 1; - } return ret; } @@ -740,7 +675,7 @@ static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) { u32 ie; - aaci_chan_wait_ready(aacirun); + aaci_chan_wait_ready(aacirun, SR_RXB); ie = readl(aacirun->base + AACI_IE); ie &= ~(IE_ORIE | IE_RXIE); @@ -755,7 +690,7 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) { u32 ie; - aaci_chan_wait_ready(aacirun); + aaci_chan_wait_ready(aacirun, SR_RXB); #ifdef DEBUG /* RX Timeout value: bits 28:17 in RXCR */ @@ -772,12 +707,11 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) { - struct aaci *aaci = substream->private_data; struct aaci_runtime *aacirun = substream->runtime->private_data; unsigned long flags; int ret = 0; - spin_lock_irqsave(&aaci->lock, flags); + spin_lock_irqsave(&aacirun->lock, flags); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -806,7 +740,7 @@ static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd ret = -EINVAL; } - spin_unlock_irqrestore(&aaci->lock, flags); + spin_unlock_irqrestore(&aacirun->lock, flags); return ret; } @@ -889,6 +823,12 @@ static struct ac97_pcm ac97_defs[] __devinitdata = { (1 << AC97_SLOT_PCM_SRIGHT) | (1 << AC97_SLOT_LFE), }, + [1] = { + .slots = (1 << AC97_SLOT_PCM_LEFT) | + (1 << AC97_SLOT_PCM_RIGHT) | + (1 << AC97_SLOT_PCM_LEFT_0) | + (1 << AC97_SLOT_PCM_RIGHT_0), + }, }, }, [1] = { /* PCM in */ @@ -1001,7 +941,6 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) aaci = card->private_data; mutex_init(&aaci->ac97_sem); - spin_lock_init(&aaci->lock); aaci->card = card; aaci->dev = dev; @@ -1028,7 +967,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - NULL, 0, 64 * 104); + NULL, 0, 64 * 1024); } return ret; @@ -1088,12 +1027,14 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) /* * Playback uses AACI channel 0 */ + spin_lock_init(&aaci->playback.lock); aaci->playback.base = aaci->base + AACI_CSCH1; aaci->playback.fifo = aaci->base + AACI_DR1; /* * Capture uses AACI channel 0 */ + spin_lock_init(&aaci->capture.lock); aaci->capture.base = aaci->base + AACI_CSCH1; aaci->capture.fifo = aaci->base + AACI_DR1; diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h index 924f69c1c44..6a4a2eebdda 100644 --- a/sound/arm/aaci.h +++ b/sound/arm/aaci.h @@ -202,6 +202,7 @@ struct aaci_runtime { void __iomem *base; void __iomem *fifo; + spinlock_t lock; struct ac97_pcm *pcm; int pcm_open; @@ -232,7 +233,6 @@ struct aaci { struct snd_ac97 *ac97; u32 maincr; - spinlock_t lock; struct aaci_runtime playback; struct aaci_runtime capture; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 30f410832a2..a27545b23ee 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -758,7 +758,7 @@ int snd_interval_ratnum(struct snd_interval *i, int diff; if (q == 0) q = 1; - den = div_down(num, q); + den = div_up(num, q); if (den < rats[k].den_min) continue; if (den > rats[k].den_max) @@ -794,7 +794,7 @@ int snd_interval_ratnum(struct snd_interval *i, i->empty = 1; return -EINVAL; } - den = div_up(num, q); + den = div_down(num, q); if (den > rats[k].den_max) continue; if (den < rats[k].den_min) diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c index cb9aa4c4edd..4be562b2cf2 100644 --- a/sound/isa/msnd/msnd_midi.c +++ b/sound/isa/msnd/msnd_midi.c @@ -162,7 +162,7 @@ int snd_msndmidi_new(struct snd_card *card, int device) err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi); if (err < 0) return err; - mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL); + mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); if (mpu == NULL) { snd_device_free(card, rmidi); return -ENOMEM; diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 96678d5d383..751762f1c59 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -393,8 +393,6 @@ size_dram(struct snd_emu8000 *emu) while (size < EMU8000_MAX_DRAM) { - size += 512 * 1024; /* increment 512kbytes */ - /* Write a unique data on the test address. * if the address is out of range, the data is written on * 0x200000(=EMU8000_DRAM_OFFSET). Then the id word is @@ -414,7 +412,9 @@ size_dram(struct snd_emu8000 *emu) /*snd_emu8000_read_wait(emu);*/ EMU8000_SMLD_READ(emu); /* discard stale data */ if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2) - break; /* we must have wrapped around */ + break; /* no memory at this address */ + + size += 512 * 1024; /* increment 512kbytes */ snd_emu8000_read_wait(emu); diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 8691f4cf619..f1d9d16b548 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -609,7 +609,7 @@ static int snd_sgio2audio_pcm_hw_params(struct snd_pcm_substream *substream, /* alloc virtual 'dma' area */ if (runtime->dma_area) vfree(runtime->dma_area); - runtime->dma_area = vmalloc(size); + runtime->dma_area = vmalloc_user(size); if (runtime->dma_area == NULL) return -ENOMEM; runtime->dma_bytes = size; diff --git a/sound/oss/pss.c b/sound/oss/pss.c index 83f5ee236b1..e19dd5dcc2d 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c @@ -269,7 +269,7 @@ static int pss_reset_dsp(pss_confdata * devc) unsigned long i, limit = jiffies + HZ/10; outw(0x2000, REG(PSS_CONTROL)); - for (i = 0; i < 32768 && (limit-jiffies >= 0); i++) + for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) inw(REG(PSS_CONTROL)); outw(0x0000, REG(PSS_CONTROL)); return 1; @@ -369,11 +369,11 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size outw(0, REG(PSS_DATA)); limit = jiffies + HZ/10; - for (i = 0; i < 32768 && (limit - jiffies >= 0); i++) + for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) val = inw(REG(PSS_STATUS)); limit = jiffies + HZ/10; - for (i = 0; i < 32768 && (limit-jiffies >= 0); i++) + for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) { val = inw(REG(PSS_STATUS)); if (val & 0x4000) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a09c03c3f62..c578c28f368 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -29,6 +29,7 @@ #include "hda_codec.h" #include "hda_local.h" +#include "hda_beep.h" #define CXT_PIN_DIR_IN 0x00 #define CXT_PIN_DIR_OUT 0x01 @@ -111,6 +112,7 @@ struct conexant_spec { unsigned int dell_automute; unsigned int port_d_mode; unsigned char ext_mic_bias; + unsigned int dell_vostro; }; static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, @@ -476,6 +478,7 @@ static void conexant_free(struct hda_codec *codec) snd_array_free(&spec->jacks); } #endif + snd_hda_detach_beep_device(codec); kfree(codec->spec); } @@ -2109,9 +2112,12 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); int val; + hda_nid_t nid = kcontrol->private_value & 0xff; + int inout = (kcontrol->private_value & 0x100) ? + AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT; - val = snd_hda_codec_read(codec, 0x17, 0, - AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT); + val = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_AMP_GAIN_MUTE, inout); ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN; return 0; @@ -2123,6 +2129,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, struct hda_codec *codec = snd_kcontrol_chip(kcontrol); const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; unsigned int idx; + hda_nid_t nid = kcontrol->private_value & 0xff; + int inout = (kcontrol->private_value & 0x100) ? + AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT; if (!imux->num_items) return 0; @@ -2130,9 +2139,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, if (idx >= imux->num_items) idx = imux->num_items - 1; - snd_hda_codec_write_cache(codec, 0x17, 0, + snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | + AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout | imux->items[idx].index); return 1; @@ -2201,10 +2210,11 @@ static struct snd_kcontrol_new cxt5066_mixers[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Mic Boost Capture Enum", + .name = "Ext Mic Boost Capture Enum", .info = cxt5066_mic_boost_mux_enum_info, .get = cxt5066_mic_boost_mux_enum_get, .put = cxt5066_mic_boost_mux_enum_put, + .private_value = 0x17, }, HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), @@ -2212,6 +2222,19 @@ static struct snd_kcontrol_new cxt5066_mixers[] = { {} }; +static struct snd_kcontrol_new cxt5066_vostro_mixers[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Int Mic Boost Capture Enum", + .info = cxt5066_mic_boost_mux_enum_info, + .get = cxt5066_mic_boost_mux_enum_get, + .put = cxt5066_mic_boost_mux_enum_put, + .private_value = 0x23 | 0x100, + }, + HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), + {} +}; + static struct hda_verb cxt5066_init_verbs[] = { {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ @@ -2397,11 +2420,16 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = { /* initialize jack-sensing, too */ static int cxt5066_init(struct hda_codec *codec) { + struct conexant_spec *spec = codec->spec; + snd_printdd("CXT5066: init\n"); conexant_init(codec); if (codec->patch_ops.unsol_event) { cxt5066_hp_automute(codec); - cxt5066_automic(codec); + if (spec->dell_vostro) + cxt5066_vostro_automic(codec); + else + cxt5066_automic(codec); } return 0; } @@ -2500,7 +2528,10 @@ static int patch_cxt5066(struct hda_codec *codec) spec->init_verbs[0] = cxt5066_init_verbs_vostro; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; spec->mixers[spec->num_mixers++] = cxt5066_mixers; + spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; spec->port_d_mode = 0; + spec->dell_vostro = 1; + snd_hda_attach_beep_device(codec, 0x13); /* no S/PDIF out */ spec->multiout.dig_out_nid = 0; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index aeed4cc5aa7..c7465053d6b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -131,8 +131,8 @@ enum { enum { ALC269_BASIC, ALC269_QUANTA_FL1, - ALC269_ASUS_EEEPC_P703, - ALC269_ASUS_EEEPC_P901, + ALC269_ASUS_AMIC, + ALC269_ASUS_DMIC, ALC269_FUJITSU, ALC269_LIFEBOOK, ALC269_AUTO, @@ -188,6 +188,8 @@ enum { ALC663_ASUS_MODE4, ALC663_ASUS_MODE5, ALC663_ASUS_MODE6, + ALC663_ASUS_MODE7, + ALC663_ASUS_MODE8, ALC272_DELL, ALC272_DELL_ZM1, ALC272_SAMSUNG_NC10, @@ -335,6 +337,9 @@ struct alc_spec { /* hooks */ void (*init_hook)(struct hda_codec *codec); void (*unsol_event)(struct hda_codec *codec, unsigned int res); +#ifdef CONFIG_SND_HDA_POWER_SAVE + void (*power_hook)(struct hda_codec *codec, int power); +#endif /* for pin sensing */ unsigned int sense_updated: 1; @@ -386,6 +391,7 @@ struct alc_config_preset { void (*init_hook)(struct hda_codec *); #ifdef CONFIG_SND_HDA_POWER_SAVE struct hda_amp_list *loopbacks; + void (*power_hook)(struct hda_codec *codec, int power); #endif }; @@ -898,6 +904,7 @@ static void setup_preset(struct hda_codec *codec, spec->unsol_event = preset->unsol_event; spec->init_hook = preset->init_hook; #ifdef CONFIG_SND_HDA_POWER_SAVE + spec->power_hook = preset->power_hook; spec->loopback.amplist = preset->loopbacks; #endif @@ -1663,9 +1670,6 @@ static struct hda_verb alc889_acer_aspire_8930g_verbs[] = { /* some bit here disables the other DACs. Init=0x4900 */ {0x20, AC_VERB_SET_COEF_INDEX, 0x08}, {0x20, AC_VERB_SET_PROC_COEF, 0x0000}, -/* Enable amplifiers */ - {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, - {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, /* DMIC fix * This laptop has a stereo digital microphone. The mics are only 1cm apart * which makes the stereo useless. However, either the mic or the ALC889 @@ -1778,6 +1782,25 @@ static struct snd_kcontrol_new alc888_base_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, + HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + { } /* end */ +}; + + static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -1808,6 +1831,16 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec) spec->autocfg.speaker_pins[2] = 0x1b; } +#ifdef CONFIG_SND_HDA_POWER_SAVE +static void alc889_power_eapd(struct hda_codec *codec, int power) +{ + snd_hda_codec_write(codec, 0x14, 0, + AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0); + snd_hda_codec_write(codec, 0x15, 0, + AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0); +} +#endif + /* * ALC880 3-stack model * @@ -3601,12 +3634,29 @@ static void alc_free(struct hda_codec *codec) snd_hda_detach_beep_device(codec); } +#ifdef CONFIG_SND_HDA_POWER_SAVE +static int alc_suspend(struct hda_codec *codec, pm_message_t state) +{ + struct alc_spec *spec = codec->spec; + if (spec && spec->power_hook) + spec->power_hook(codec, 0); + return 0; +} +#endif + #ifdef SND_HDA_NEEDS_RESUME static int alc_resume(struct hda_codec *codec) { +#ifdef CONFIG_SND_HDA_POWER_SAVE + struct alc_spec *spec = codec->spec; +#endif codec->patch_ops.init(codec); snd_hda_codec_resume_amp(codec); snd_hda_codec_resume_cache(codec); +#ifdef CONFIG_SND_HDA_POWER_SAVE + if (spec && spec->power_hook) + spec->power_hook(codec, 1); +#endif return 0; } #endif @@ -3623,6 +3673,7 @@ static struct hda_codec_ops alc_patch_ops = { .resume = alc_resume, #endif #ifdef CONFIG_SND_HDA_POWER_SAVE + .suspend = alc_suspend, .check_power_status = alc_check_power_status, #endif }; @@ -8919,7 +8970,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ - SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG), + SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO), SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG), @@ -9282,6 +9333,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .dig_out_nid = ALC883_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), .channel_mode = alc883_3ST_2ch_modes, @@ -9378,10 +9430,11 @@ static struct alc_config_preset alc882_presets[] = { .init_hook = alc_automute_amp, }, [ALC888_ACER_ASPIRE_8930G] = { - .mixers = { alc888_base_mixer, + .mixers = { alc889_acer_aspire_8930g_mixer, alc883_chmode_mixer }, .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs, - alc889_acer_aspire_8930g_verbs }, + alc889_acer_aspire_8930g_verbs, + alc889_eapd_verbs}, .num_dacs = ARRAY_SIZE(alc883_dac_nids), .dac_nids = alc883_dac_nids, .num_adc_nids = ARRAY_SIZE(alc889_adc_nids), @@ -9398,6 +9451,9 @@ static struct alc_config_preset alc882_presets[] = { .unsol_event = alc_automute_amp_unsol_event, .setup = alc889_acer_aspire_8930g_setup, .init_hook = alc_automute_amp, +#ifdef CONFIG_SND_HDA_POWER_SAVE + .power_hook = alc889_power_eapd, +#endif }, [ALC888_ACER_ASPIRE_7730G] = { .mixers = { alc883_3ST_6ch_mixer, @@ -9428,6 +9484,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), .channel_mode = alc883_sixstack_modes, .input_mux = &alc883_capture_source, @@ -9489,6 +9546,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), .channel_mode = alc883_3ST_2ch_modes, .input_mux = &alc883_lenovo_101e_capture_source, @@ -9668,6 +9726,7 @@ static struct alc_config_preset alc882_presets[] = { alc880_gpio1_init_verbs }, .adc_nids = alc883_adc_nids, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), + .capsrc_nids = alc883_capsrc_nids, .dac_nids = alc883_dac_nids, .num_dacs = ARRAY_SIZE(alc883_dac_nids), .channel_mode = alc889A_mb31_6ch_modes, @@ -10678,6 +10737,13 @@ static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = { {} }; +static struct hda_verb alc262_lenovo_3000_init_verbs[] = { + /* Front Mic pin: input vref at 50% */ + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, + {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {} +}; + static struct hda_input_mux alc262_fujitsu_capture_source = { .num_items = 3, .items = { @@ -11720,7 +11786,8 @@ static struct alc_config_preset alc262_presets[] = { [ALC262_LENOVO_3000] = { .mixers = { alc262_lenovo_3000_mixer }, .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs, - alc262_lenovo_3000_unsol_verbs }, + alc262_lenovo_3000_unsol_verbs, + alc262_lenovo_3000_init_verbs }, .num_dacs = ARRAY_SIZE(alc262_dac_nids), .dac_nids = alc262_dac_nids, .hp_nid = 0x03, @@ -12857,7 +12924,7 @@ static int patch_alc268(struct hda_codec *codec) int board_config; int i, has_beep, err; - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); + spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; @@ -13232,10 +13299,12 @@ static struct hda_verb alc269_eeepc_amic_init_verbs[] = { /* toggle speaker-output according to the hp-jack state */ static void alc269_speaker_automute(struct hda_codec *codec) { + struct alc_spec *spec = codec->spec; + unsigned int nid = spec->autocfg.hp_pins[0]; unsigned int present; unsigned char bits; - present = snd_hda_jack_detect(codec, 0x15); + present = snd_hda_jack_detect(codec, nid); bits = present ? AMP_IN_MUTE(0) : 0; snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, AMP_IN_MUTE(0), bits); @@ -13460,8 +13529,8 @@ static void alc269_auto_init(struct hda_codec *codec) static const char *alc269_models[ALC269_MODEL_LAST] = { [ALC269_BASIC] = "basic", [ALC269_QUANTA_FL1] = "quanta", - [ALC269_ASUS_EEEPC_P703] = "eeepc-p703", - [ALC269_ASUS_EEEPC_P901] = "eeepc-p901", + [ALC269_ASUS_AMIC] = "asus-amic", + [ALC269_ASUS_DMIC] = "asus-dmic", [ALC269_FUJITSU] = "fujitsu", [ALC269_LIFEBOOK] = "lifebook", [ALC269_AUTO] = "auto", @@ -13470,18 +13539,41 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { static struct snd_pci_quirk alc269_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", - ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_EEEPC_P703), + ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80JT", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_DMIC), + SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", - ALC269_ASUS_EEEPC_P901), + ALC269_ASUS_DMIC), SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", - ALC269_ASUS_EEEPC_P901), - SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_EEEPC_P901), + ALC269_ASUS_DMIC), + SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_ASUS_DMIC), + SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_ASUS_DMIC), SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), {} @@ -13511,7 +13603,7 @@ static struct alc_config_preset alc269_presets[] = { .setup = alc269_quanta_fl1_setup, .init_hook = alc269_quanta_fl1_init_hook, }, - [ALC269_ASUS_EEEPC_P703] = { + [ALC269_ASUS_AMIC] = { .mixers = { alc269_eeepc_mixer }, .cap_mixer = alc269_epc_capture_mixer, .init_verbs = { alc269_init_verbs, @@ -13525,7 +13617,7 @@ static struct alc_config_preset alc269_presets[] = { .setup = alc269_eeepc_amic_setup, .init_hook = alc269_eeepc_inithook, }, - [ALC269_ASUS_EEEPC_P901] = { + [ALC269_ASUS_DMIC] = { .mixers = { alc269_eeepc_mixer }, .cap_mixer = alc269_epc_capture_mixer, .init_verbs = { alc269_init_verbs, @@ -16160,6 +16252,52 @@ static struct snd_kcontrol_new alc663_g50v_mixer[] = { { } /* end */ }; +static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = { + .ops = &snd_hda_bind_sw, + .values = { + HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), + 0 + }, +}; + +static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = { + .ops = &snd_hda_bind_sw, + .values = { + HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), + 0 + }, +}; + +static struct snd_kcontrol_new alc663_mode7_mixer[] = { + HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch), + HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol), + HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch), + HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + { } /* end */ +}; + +static struct snd_kcontrol_new alc663_mode8_mixer[] = { + HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch), + HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol), + HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch), + HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + { } /* end */ +}; + + static struct snd_kcontrol_new alc662_chmode_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -16447,6 +16585,45 @@ static struct hda_verb alc272_dell_init_verbs[] = { {} }; +static struct hda_verb alc663_mode7_init_verbs[] = { + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01}, + {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)}, + {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {} +}; + +static struct hda_verb alc663_mode8_init_verbs[] = { + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)}, + {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, + {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {} +}; + static struct snd_kcontrol_new alc662_auto_capture_mixer[] = { HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), @@ -16626,6 +16803,54 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec) } } +static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec) +{ + unsigned int present1, present2; + + present1 = snd_hda_codec_read(codec, 0x1b, 0, + AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + present2 = snd_hda_codec_read(codec, 0x21, 0, + AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + + if (present1 || present2) { + snd_hda_codec_write_cache(codec, 0x14, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + snd_hda_codec_write_cache(codec, 0x17, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + } else { + snd_hda_codec_write_cache(codec, 0x14, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + snd_hda_codec_write_cache(codec, 0x17, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + } +} + +static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec) +{ + unsigned int present1, present2; + + present1 = snd_hda_codec_read(codec, 0x21, 0, + AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + present2 = snd_hda_codec_read(codec, 0x15, 0, + AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + + if (present1 || present2) { + snd_hda_codec_write_cache(codec, 0x14, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + snd_hda_codec_write_cache(codec, 0x17, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + } else { + snd_hda_codec_write_cache(codec, 0x14, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + snd_hda_codec_write_cache(codec, 0x17, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + } +} + static void alc663_m51va_unsol_event(struct hda_codec *codec, unsigned int res) { @@ -16645,7 +16870,7 @@ static void alc663_m51va_setup(struct hda_codec *codec) spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; - spec->int_mic.mux_idx = 1; + spec->int_mic.mux_idx = 9; spec->auto_mic = 1; } @@ -16657,7 +16882,17 @@ static void alc663_m51va_inithook(struct hda_codec *codec) /* ***************** Mode1 ******************************/ #define alc663_mode1_unsol_event alc663_m51va_unsol_event -#define alc663_mode1_setup alc663_m51va_setup + +static void alc663_mode1_setup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + spec->ext_mic.pin = 0x18; + spec->ext_mic.mux_idx = 0; + spec->int_mic.pin = 0x19; + spec->int_mic.mux_idx = 1; + spec->auto_mic = 1; +} + #define alc663_mode1_inithook alc663_m51va_inithook /* ***************** Mode2 ******************************/ @@ -16674,7 +16909,7 @@ static void alc662_mode2_unsol_event(struct hda_codec *codec, } } -#define alc662_mode2_setup alc663_m51va_setup +#define alc662_mode2_setup alc663_mode1_setup static void alc662_mode2_inithook(struct hda_codec *codec) { @@ -16695,7 +16930,7 @@ static void alc663_mode3_unsol_event(struct hda_codec *codec, } } -#define alc663_mode3_setup alc663_m51va_setup +#define alc663_mode3_setup alc663_mode1_setup static void alc663_mode3_inithook(struct hda_codec *codec) { @@ -16716,7 +16951,7 @@ static void alc663_mode4_unsol_event(struct hda_codec *codec, } } -#define alc663_mode4_setup alc663_m51va_setup +#define alc663_mode4_setup alc663_mode1_setup static void alc663_mode4_inithook(struct hda_codec *codec) { @@ -16737,7 +16972,7 @@ static void alc663_mode5_unsol_event(struct hda_codec *codec, } } -#define alc663_mode5_setup alc663_m51va_setup +#define alc663_mode5_setup alc663_mode1_setup static void alc663_mode5_inithook(struct hda_codec *codec) { @@ -16758,7 +16993,7 @@ static void alc663_mode6_unsol_event(struct hda_codec *codec, } } -#define alc663_mode6_setup alc663_m51va_setup +#define alc663_mode6_setup alc663_mode1_setup static void alc663_mode6_inithook(struct hda_codec *codec) { @@ -16766,6 +17001,50 @@ static void alc663_mode6_inithook(struct hda_codec *codec) alc_mic_automute(codec); } +/* ***************** Mode7 ******************************/ +static void alc663_mode7_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + switch (res >> 26) { + case ALC880_HP_EVENT: + alc663_two_hp_m7_speaker_automute(codec); + break; + case ALC880_MIC_EVENT: + alc_mic_automute(codec); + break; + } +} + +#define alc663_mode7_setup alc663_mode1_setup + +static void alc663_mode7_inithook(struct hda_codec *codec) +{ + alc663_two_hp_m7_speaker_automute(codec); + alc_mic_automute(codec); +} + +/* ***************** Mode8 ******************************/ +static void alc663_mode8_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + switch (res >> 26) { + case ALC880_HP_EVENT: + alc663_two_hp_m8_speaker_automute(codec); + break; + case ALC880_MIC_EVENT: + alc_mic_automute(codec); + break; + } +} + +#define alc663_mode8_setup alc663_m51va_setup + +static void alc663_mode8_inithook(struct hda_codec *codec) +{ + alc663_two_hp_m8_speaker_automute(codec); + alc_mic_automute(codec); +} + static void alc663_g71v_hp_automute(struct hda_codec *codec) { unsigned int present; @@ -16900,6 +17179,8 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { [ALC663_ASUS_MODE4] = "asus-mode4", [ALC663_ASUS_MODE5] = "asus-mode5", [ALC663_ASUS_MODE6] = "asus-mode6", + [ALC663_ASUS_MODE7] = "asus-mode7", + [ALC663_ASUS_MODE8] = "asus-mode8", [ALC272_DELL] = "dell", [ALC272_DELL_ZM1] = "dell-zm1", [ALC272_SAMSUNG_NC10] = "samsung-nc10", @@ -16916,12 +17197,22 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7), + SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7), + SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8), + SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3), + SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA), SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2), @@ -17205,6 +17496,36 @@ static struct alc_config_preset alc662_presets[] = { .setup = alc663_mode6_setup, .init_hook = alc663_mode6_inithook, }, + [ALC663_ASUS_MODE7] = { + .mixers = { alc663_mode7_mixer }, + .cap_mixer = alc662_auto_capture_mixer, + .init_verbs = { alc662_init_verbs, + alc663_mode7_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .hp_nid = 0x03, + .dac_nids = alc662_dac_nids, + .dig_out_nid = ALC662_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), + .channel_mode = alc662_3ST_2ch_modes, + .unsol_event = alc663_mode7_unsol_event, + .setup = alc663_mode7_setup, + .init_hook = alc663_mode7_inithook, + }, + [ALC663_ASUS_MODE8] = { + .mixers = { alc663_mode8_mixer }, + .cap_mixer = alc662_auto_capture_mixer, + .init_verbs = { alc662_init_verbs, + alc663_mode8_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .hp_nid = 0x03, + .dac_nids = alc662_dac_nids, + .dig_out_nid = ALC662_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), + .channel_mode = alc662_3ST_2ch_modes, + .unsol_event = alc663_mode8_unsol_event, + .setup = alc663_mode8_setup, + .init_hook = alc663_mode8_inithook, + }, [ALC272_DELL] = { .mixers = { alc663_m51va_mixer }, .cap_mixer = alc272_auto_capture_mixer, @@ -17688,7 +18009,9 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 }, { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 }, + { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 }, { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 }, + { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index d057e648964..5cfa608823f 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -51,7 +51,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s return 0; /* already enough large */ vfree(runtime->dma_area); } - runtime->dma_area = vmalloc_32(size); + runtime->dma_area = vmalloc_32_user(size); if (! runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index b69861d5216..3ef16bbc8c8 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -470,7 +470,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); static int __init ak4642_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&ak4642_i2c_driver); #endif diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index bbc72c2ddfc..81b8c9dfe7f 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -191,6 +191,7 @@ static int ac97_analog_prepare(struct snd_pcm_substream *substream, vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); vra |= 0x1; /* enable variable rate audio */ + vra &= ~0x4; /* disable SPDIF output */ stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); @@ -221,22 +222,6 @@ static int ac97_digital_prepare(struct snd_pcm_substream *substream, return stac9766_ac97_write(codec, reg, runtime->rate); } -static int ac97_digital_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - unsigned short vra; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_STOP: - vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); - vra &= !0x04; - stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); - break; - } - return 0; -} - static int stac9766_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -315,7 +300,6 @@ static struct snd_soc_dai_ops stac9766_dai_ops_analog = { static struct snd_soc_dai_ops stac9766_dai_ops_digital = { .prepare = ac97_digital_prepare, - .trigger = ac97_digital_trigger, }; struct snd_soc_dai stac9766_dai[] = { diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 81c57b5c591..a808675388f 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -47,7 +47,7 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { }; #define WM8974_POWER1_BIASEN 0x08 -#define WM8974_POWER1_BUFIOEN 0x10 +#define WM8974_POWER1_BUFIOEN 0x04 struct wm8974_priv { struct snd_soc_codec codec; diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index b074a594c59..4963defee18 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -752,7 +752,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s return 0; /* already large enough */ vfree(runtime->dma_area); } - runtime->dma_area = vmalloc(size); + runtime->dma_area = vmalloc_user(size); if (!runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index e1f2bf8d7b1..b5af8816761 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1177,7 +1177,7 @@ static struct file_operations kvm_vcpu_fops = { */ static int create_vcpu_fd(struct kvm_vcpu *vcpu) { - return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, 0); + return anon_inode_getfd("kvm-vcpu", &kvm_vcpu_fops, vcpu, O_RDWR); } /* @@ -1638,7 +1638,7 @@ static int kvm_dev_ioctl_create_vm(void) kvm = kvm_create_vm(); if (IS_ERR(kvm)) return PTR_ERR(kvm); - fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, 0); + fd = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR); if (fd < 0) kvm_put_kvm(kvm); |