From 9b00297ab7b9f9a2c40198d286ffd396cd10313a Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 26 Sep 2007 14:11:43 -0700 Subject: [PATCH] --- yaml --- r: 65190 b: refs/heads/master c: 2efa33f81ef56e7700c09a3d8a881c96692149e5 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/crypto/async-tx-api.txt | 219 -------- trunk/Documentation/input/iforce-protocol.txt | 508 +++++++++--------- trunk/Documentation/lguest/lguest.c | 2 +- trunk/MAINTAINERS | 6 +- trunk/Makefile | 2 +- trunk/arch/arm/mach-ep93xx/core.c | 2 +- trunk/arch/arm/mm/cache-l2x0.c | 12 +- trunk/arch/i386/boot/memory.c | 30 +- trunk/arch/i386/xen/mmu.c | 5 +- trunk/arch/mips/kernel/i8259.c | 5 +- trunk/arch/mips/kernel/irq-msc01.c | 10 +- trunk/arch/mips/kernel/irq.c | 10 +- trunk/arch/mips/kernel/smtc.c | 5 +- trunk/arch/mips/sibyte/bcm1480/setup.c | 2 - trunk/arch/powerpc/kernel/process.c | 7 - .../arch/powerpc/platforms/cell/spufs/file.c | 4 +- trunk/arch/x86_64/Kconfig | 8 + trunk/arch/x86_64/ia32/ia32entry.S | 18 +- trunk/arch/x86_64/kernel/process.c | 1 + trunk/arch/x86_64/kernel/ptrace.c | 4 + trunk/arch/x86_64/kernel/smp.c | 2 +- trunk/crypto/async_tx/async_tx.c | 12 +- trunk/drivers/acpi/processor_core.c | 2 - trunk/drivers/acpi/processor_idle.c | 19 +- trunk/drivers/acpi/sleep/Makefile | 4 +- trunk/drivers/acpi/sleep/main.c | 61 +-- trunk/drivers/acpi/sleep/poweroff.c | 75 +++ trunk/drivers/acpi/video.c | 3 +- trunk/drivers/ata/ahci.c | 10 +- trunk/drivers/ata/libata-core.c | 4 - trunk/drivers/ata/libata-sff.c | 5 +- trunk/drivers/ata/pata_sis.c | 3 +- trunk/drivers/ata/sata_sil24.c | 16 +- trunk/drivers/base/core.c | 1 - trunk/drivers/cdrom/cdrom.c | 4 - trunk/drivers/char/hpet.c | 9 +- trunk/drivers/char/mspec.c | 26 +- trunk/drivers/ieee1394/ieee1394_core.c | 2 +- trunk/drivers/ieee1394/ohci1394.c | 4 +- trunk/drivers/infiniband/hw/mlx4/qp.c | 62 +-- trunk/drivers/input/mouse/appletouch.c | 6 +- trunk/drivers/kvm/Kconfig | 3 +- trunk/drivers/lguest/lguest_asm.S | 6 +- trunk/drivers/md/raid5.c | 17 +- .../media/video/usbvision/usbvision-video.c | 5 +- trunk/drivers/net/bnx2.c | 7 +- trunk/drivers/net/mv643xx_eth.c | 2 + trunk/drivers/net/myri10ge/myri10ge.c | 3 - trunk/drivers/net/pcmcia/3c589_cs.c | 2 +- trunk/drivers/net/phy/phy.c | 1 - trunk/drivers/net/ppp_mppe.c | 14 +- trunk/drivers/net/pppoe.c | 3 +- trunk/drivers/net/pppol2tp.c | 118 ++-- trunk/drivers/net/r8169.c | 14 +- trunk/drivers/net/sky2.c | 373 ++++--------- trunk/drivers/net/sky2.h | 41 +- trunk/drivers/power/power_supply_sysfs.c | 1 - trunk/drivers/scsi/esp_scsi.c | 3 +- trunk/drivers/scsi/scsi_transport_spi.c | 28 +- trunk/drivers/serial/sunsab.c | 2 +- trunk/drivers/w1/w1.c | 1 - trunk/fs/compat_ioctl.c | 2 - trunk/fs/exec.c | 3 + trunk/fs/lockd/svclock.c | 29 +- trunk/fs/ocfs2/aops.c | 33 +- trunk/fs/ocfs2/file.c | 4 +- trunk/fs/ocfs2/localalloc.c | 4 +- trunk/fs/ocfs2/localalloc.h | 2 +- trunk/fs/ocfs2/suballoc.c | 29 +- trunk/fs/ocfs2/suballoc.h | 11 - trunk/fs/ocfs2/vote.c | 4 +- trunk/fs/signalfd.c | 190 ++++++- trunk/fs/ufs/super.c | 4 +- trunk/fs/xfs/xfs_filestream.c | 7 +- trunk/fs/xfs/xfs_log_recover.c | 4 +- trunk/include/acpi/acpi_drivers.h | 4 + trunk/include/acpi/processor.h | 2 - trunk/include/asm-mips/irq.h | 32 +- trunk/include/asm-x86_64/pgalloc.h | 73 ++- trunk/include/asm-x86_64/pgtable.h | 1 - trunk/include/linux/init_task.h | 2 +- trunk/include/linux/sched.h | 2 +- trunk/include/linux/signalfd.h | 40 +- trunk/include/net/sctp/sm.h | 4 +- trunk/include/net/sctp/structs.h | 3 +- trunk/kernel/exit.c | 9 + trunk/kernel/fork.c | 2 +- trunk/kernel/power/Kconfig | 2 +- trunk/kernel/signal.c | 8 +- trunk/kernel/time/tick-broadcast.c | 17 +- trunk/lib/Kconfig.debug | 2 +- .../softmac/ieee80211softmac_assoc.c | 2 + .../ieee80211/softmac/ieee80211softmac_wx.c | 54 +- trunk/net/mac80211/ieee80211.c | 2 +- trunk/net/mac80211/rc80211_simple.c | 2 +- trunk/net/mac80211/wme.c | 2 +- trunk/net/netfilter/nfnetlink_log.c | 13 +- trunk/net/sched/sch_sfq.c | 10 +- trunk/net/sctp/bind_addr.c | 2 +- trunk/net/sctp/input.c | 8 - trunk/net/sctp/inqueue.c | 8 - trunk/net/sctp/sm_make_chunk.c | 46 -- trunk/net/sctp/sm_statefuns.c | 243 ++------- trunk/net/sctp/sm_statetable.c | 16 +- trunk/net/sunrpc/svcsock.c | 3 +- trunk/net/wireless/core.c | 2 +- trunk/net/wireless/sysfs.c | 2 - trunk/sound/core/memalloc.c | 68 +-- 109 files changed, 1166 insertions(+), 1682 deletions(-) delete mode 100644 trunk/Documentation/crypto/async-tx-api.txt create mode 100644 trunk/drivers/acpi/sleep/poweroff.c diff --git a/[refs] b/[refs] index 315751f92904..999855b88672 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f7f847b01571e86044dc77e03d92f43699652f8d +refs/heads/master: 2efa33f81ef56e7700c09a3d8a881c96692149e5 diff --git a/trunk/Documentation/crypto/async-tx-api.txt b/trunk/Documentation/crypto/async-tx-api.txt deleted file mode 100644 index c1e9545c59bd..000000000000 --- a/trunk/Documentation/crypto/async-tx-api.txt +++ /dev/null @@ -1,219 +0,0 @@ - Asynchronous Transfers/Transforms API - -1 INTRODUCTION - -2 GENEALOGY - -3 USAGE -3.1 General format of the API -3.2 Supported operations -3.3 Descriptor management -3.4 When does the operation execute? -3.5 When does the operation complete? -3.6 Constraints -3.7 Example - -4 DRIVER DEVELOPER NOTES -4.1 Conformance points -4.2 "My application needs finer control of hardware channels" - -5 SOURCE - ---- - -1 INTRODUCTION - -The async_tx API provides methods for describing a chain of asynchronous -bulk memory transfers/transforms with support for inter-transactional -dependencies. It is implemented as a dmaengine client that smooths over -the details of different hardware offload engine implementations. Code -that is written to the API can optimize for asynchronous operation and -the API will fit the chain of operations to the available offload -resources. - -2 GENEALOGY - -The API was initially designed to offload the memory copy and -xor-parity-calculations of the md-raid5 driver using the offload engines -present in the Intel(R) Xscale series of I/O processors. It also built -on the 'dmaengine' layer developed for offloading memory copies in the -network stack using Intel(R) I/OAT engines. The following design -features surfaced as a result: -1/ implicit synchronous path: users of the API do not need to know if - the platform they are running on has offload capabilities. The - operation will be offloaded when an engine is available and carried out - in software otherwise. -2/ cross channel dependency chains: the API allows a chain of dependent - operations to be submitted, like xor->copy->xor in the raid5 case. The - API automatically handles cases where the transition from one operation - to another implies a hardware channel switch. -3/ dmaengine extensions to support multiple clients and operation types - beyond 'memcpy' - -3 USAGE - -3.1 General format of the API: -struct dma_async_tx_descriptor * -async_(, - enum async_tx_flags flags, - struct dma_async_tx_descriptor *dependency, - dma_async_tx_callback callback_routine, - void *callback_parameter); - -3.2 Supported operations: -memcpy - memory copy between a source and a destination buffer -memset - fill a destination buffer with a byte value -xor - xor a series of source buffers and write the result to a - destination buffer -xor_zero_sum - xor a series of source buffers and set a flag if the - result is zero. The implementation attempts to prevent - writes to memory - -3.3 Descriptor management: -The return value is non-NULL and points to a 'descriptor' when the operation -has been queued to execute asynchronously. Descriptors are recycled -resources, under control of the offload engine driver, to be reused as -operations complete. When an application needs to submit a chain of -operations it must guarantee that the descriptor is not automatically recycled -before the dependency is submitted. This requires that all descriptors be -acknowledged by the application before the offload engine driver is allowed to -recycle (or free) the descriptor. A descriptor can be acked by one of the -following methods: -1/ setting the ASYNC_TX_ACK flag if no child operations are to be submitted -2/ setting the ASYNC_TX_DEP_ACK flag to acknowledge the parent - descriptor of a new operation. -3/ calling async_tx_ack() on the descriptor. - -3.4 When does the operation execute? -Operations do not immediately issue after return from the -async_ call. Offload engine drivers batch operations to -improve performance by reducing the number of mmio cycles needed to -manage the channel. Once a driver-specific threshold is met the driver -automatically issues pending operations. An application can force this -event by calling async_tx_issue_pending_all(). This operates on all -channels since the application has no knowledge of channel to operation -mapping. - -3.5 When does the operation complete? -There are two methods for an application to learn about the completion -of an operation. -1/ Call dma_wait_for_async_tx(). This call causes the CPU to spin while - it polls for the completion of the operation. It handles dependency - chains and issuing pending operations. -2/ Specify a completion callback. The callback routine runs in tasklet - context if the offload engine driver supports interrupts, or it is - called in application context if the operation is carried out - synchronously in software. The callback can be set in the call to - async_, or when the application needs to submit a chain of - unknown length it can use the async_trigger_callback() routine to set a - completion interrupt/callback at the end of the chain. - -3.6 Constraints: -1/ Calls to async_ are not permitted in IRQ context. Other - contexts are permitted provided constraint #2 is not violated. -2/ Completion callback routines cannot submit new operations. This - results in recursion in the synchronous case and spin_locks being - acquired twice in the asynchronous case. - -3.7 Example: -Perform a xor->copy->xor operation where each operation depends on the -result from the previous operation: - -void complete_xor_copy_xor(void *param) -{ - printk("complete\n"); -} - -int run_xor_copy_xor(struct page **xor_srcs, - int xor_src_cnt, - struct page *xor_dest, - size_t xor_len, - struct page *copy_src, - struct page *copy_dest, - size_t copy_len) -{ - struct dma_async_tx_descriptor *tx; - - tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len, - ASYNC_TX_XOR_DROP_DST, NULL, NULL, NULL); - tx = async_memcpy(copy_dest, copy_src, 0, 0, copy_len, - ASYNC_TX_DEP_ACK, tx, NULL, NULL); - tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len, - ASYNC_TX_XOR_DROP_DST | ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, - tx, complete_xor_copy_xor, NULL); - - async_tx_issue_pending_all(); -} - -See include/linux/async_tx.h for more information on the flags. See the -ops_run_* and ops_complete_* routines in drivers/md/raid5.c for more -implementation examples. - -4 DRIVER DEVELOPMENT NOTES -4.1 Conformance points: -There are a few conformance points required in dmaengine drivers to -accommodate assumptions made by applications using the async_tx API: -1/ Completion callbacks are expected to happen in tasklet context -2/ dma_async_tx_descriptor fields are never manipulated in IRQ context -3/ Use async_tx_run_dependencies() in the descriptor clean up path to - handle submission of dependent operations - -4.2 "My application needs finer control of hardware channels" -This requirement seems to arise from cases where a DMA engine driver is -trying to support device-to-memory DMA. The dmaengine and async_tx -implementations were designed for offloading memory-to-memory -operations; however, there are some capabilities of the dmaengine layer -that can be used for platform-specific channel management. -Platform-specific constraints can be handled by registering the -application as a 'dma_client' and implementing a 'dma_event_callback' to -apply a filter to the available channels in the system. Before showing -how to implement a custom dma_event callback some background of -dmaengine's client support is required. - -The following routines in dmaengine support multiple clients requesting -use of a channel: -- dma_async_client_register(struct dma_client *client) -- dma_async_client_chan_request(struct dma_client *client) - -dma_async_client_register takes a pointer to an initialized dma_client -structure. It expects that the 'event_callback' and 'cap_mask' fields -are already initialized. - -dma_async_client_chan_request triggers dmaengine to notify the client of -all channels that satisfy the capability mask. It is up to the client's -event_callback routine to track how many channels the client needs and -how many it is currently using. The dma_event_callback routine returns a -dma_state_client code to let dmaengine know the status of the -allocation. - -Below is the example of how to extend this functionality for -platform-specific filtering of the available channels beyond the -standard capability mask: - -static enum dma_state_client -my_dma_client_callback(struct dma_client *client, - struct dma_chan *chan, enum dma_state state) -{ - struct dma_device *dma_dev; - struct my_platform_specific_dma *plat_dma_dev; - - dma_dev = chan->device; - plat_dma_dev = container_of(dma_dev, - struct my_platform_specific_dma, - dma_dev); - - if (!plat_dma_dev->platform_specific_capability) - return DMA_DUP; - - . . . -} - -5 SOURCE -include/linux/dmaengine.h: core header file for DMA drivers and clients -drivers/dma/dmaengine.c: offload engine channel management routines -drivers/dma/: location for offload engine drivers -include/linux/async_tx.h: core header file for the async_tx api -crypto/async_tx/async_tx.c: async_tx interface to dmaengine and common code -crypto/async_tx/async_memcpy.c: copy offload -crypto/async_tx/async_memset.c: memory fill offload -crypto/async_tx/async_xor.c: xor and xor zero sum offload diff --git a/trunk/Documentation/input/iforce-protocol.txt b/trunk/Documentation/input/iforce-protocol.txt index 8777d2d321e3..95df4ca70e71 100644 --- a/trunk/Documentation/input/iforce-protocol.txt +++ b/trunk/Documentation/input/iforce-protocol.txt @@ -1,254 +1,254 @@ -** Introduction -This document describes what I managed to discover about the protocol used to -specify force effects to I-Force 2.0 devices. None of this information comes -from Immerse. That's why you should not trust what is written in this -document. This document is intended to help understanding the protocol. -This is not a reference. Comments and corrections are welcome. To contact me, -send an email to: deneux@ifrance.com - -** WARNING ** -I may not be held responsible for any dammage or harm caused if you try to -send data to your I-Force device based on what you read in this document. - -** Preliminary Notes: -All values are hexadecimal with big-endian encoding (msb on the left). Beware, -values inside packets are encoded using little-endian. Bytes whose roles are -unknown are marked ??? Information that needs deeper inspection is marked (?) - -** General form of a packet ** -This is how packets look when the device uses the rs232 to communicate. -2B OP LEN DATA CS -CS is the checksum. It is equal to the exclusive or of all bytes. - -When using USB: -OP DATA -The 2B, LEN and CS fields have disappeared, probably because USB handles frames and -data corruption is handled or unsignificant. - -First, I describe effects that are sent by the device to the computer - -** Device input state -This packet is used to indicate the state of each button and the value of each -axis -OP= 01 for a joystick, 03 for a wheel -LEN= Varies from device to device -00 X-Axis lsb -01 X-Axis msb -02 Y-Axis lsb, or gas pedal for a wheel -03 Y-Axis msb, or brake pedal for a wheel -04 Throttle -05 Buttons -06 Lower 4 bits: Buttons - Upper 4 bits: Hat -07 Rudder - -** Device effects states -OP= 02 -LEN= Varies -00 ? Bit 1 (Value 2) is the value of the deadman switch -01 Bit 8 is set if the effect is playing. Bits 0 to 7 are the effect id. -02 ?? -03 Address of parameter block changed (lsb) -04 Address of parameter block changed (msb) -05 Address of second parameter block changed (lsb) -... depending on the number of parameter blocks updated - -** Force effect ** -OP= 01 -LEN= 0e -00 Channel (when playing several effects at the same time, each must be assigned a channel) -01 Wave form - Val 00 Constant - Val 20 Square - Val 21 Triangle - Val 22 Sine - Val 23 Sawtooth up - Val 24 Sawtooth down - Val 40 Spring (Force = f(pos)) - Val 41 Friction (Force = f(velocity)) and Inertia (Force = f(acceleration)) - - -02 Axes affected and trigger - Bits 4-7: Val 2 = effect along one axis. Byte 05 indicates direction - Val 4 = X axis only. Byte 05 must contain 5a - Val 8 = Y axis only. Byte 05 must contain b4 - Val c = X and Y axes. Bytes 05 must contain 60 - Bits 0-3: Val 0 = No trigger - Val x+1 = Button x triggers the effect - When the whole byte is 0, cancel the previously set trigger - -03-04 Duration of effect (little endian encoding, in ms) - -05 Direction of effect, if applicable. Else, see 02 for value to assign. - -06-07 Minimum time between triggering. - -08-09 Address of periodicity or magnitude parameters -0a-0b Address of attack and fade parameters, or ffff if none. -*or* -08-09 Address of interactive parameters for X-axis, or ffff if not applicable -0a-0b Address of interactive parameters for Y-axis, or ffff if not applicable - -0c-0d Delay before execution of effect (little endian encoding, in ms) - - -** Time based parameters ** - -*** Attack and fade *** -OP= 02 -LEN= 08 -00-01 Address where to store the parameteres -02-03 Duration of attack (little endian encoding, in ms) -04 Level at end of attack. Signed byte. -05-06 Duration of fade. -07 Level at end of fade. - -*** Magnitude *** -OP= 03 -LEN= 03 -00-01 Address -02 Level. Signed byte. - -*** Periodicity *** -OP= 04 -LEN= 07 -00-01 Address -02 Magnitude. Signed byte. -03 Offset. Signed byte. -04 Phase. Val 00 = 0 deg, Val 40 = 90 degs. -05-06 Period (little endian encoding, in ms) - -** Interactive parameters ** -OP= 05 -LEN= 0a -00-01 Address -02 Positive Coeff -03 Negative Coeff -04+05 Offset (center) -06+07 Dead band (Val 01F4 = 5000 (decimal)) -08 Positive saturation (Val 0a = 1000 (decimal) Val 64 = 10000 (decimal)) -09 Negative saturation - -The encoding is a bit funny here: For coeffs, these are signed values. The -maximum value is 64 (100 decimal), the min is 9c. -For the offset, the minimum value is FE0C, the maximum value is 01F4. -For the deadband, the minimum value is 0, the max is 03E8. - -** Controls ** -OP= 41 -LEN= 03 -00 Channel -01 Start/Stop - Val 00: Stop - Val 01: Start and play once. - Val 41: Start and play n times (See byte 02 below) -02 Number of iterations n. - -** Init ** - -*** Querying features *** -OP= ff -Query command. Length varies according to the query type. -The general format of this packet is: -ff 01 QUERY [INDEX] CHECKSUM -reponses are of the same form: -FF LEN QUERY VALUE_QUERIED CHECKSUM2 -where LEN = 1 + length(VALUE_QUERIED) - -**** Query ram size **** -QUERY = 42 ('B'uffer size) -The device should reply with the same packet plus two additionnal bytes -containing the size of the memory: -ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available. - -**** Query number of effects **** -QUERY = 4e ('N'umber of effects) -The device should respond by sending the number of effects that can be played -at the same time (one byte) -ff 02 4e 14 CS would stand for 20 effects. - -**** Vendor's id **** -QUERY = 4d ('M'anufacturer) -Query the vendors'id (2 bytes) - -**** Product id ***** -QUERY = 50 ('P'roduct) -Query the product id (2 bytes) - -**** Open device **** -QUERY = 4f ('O'pen) -No data returned. - -**** Close device ***** -QUERY = 43 ('C')lose -No data returned. - -**** Query effect **** -QUERY = 45 ('E') -Send effect type. -Returns nonzero if supported (2 bytes) - -**** Firmware Version **** -QUERY = 56 ('V'ersion) -Sends back 3 bytes - major, minor, subminor - -*** Initialisation of the device *** - -**** Set Control **** -!!! Device dependent, can be different on different models !!! -OP= 40 [] -LEN= 2 or 3 -00 Idx - Idx 00 Set dead zone (0..2048) - Idx 01 Ignore Deadman sensor (0..1) - Idx 02 Enable comm watchdog (0..1) - Idx 03 Set the strength of the spring (0..100) - Idx 04 Enable or disable the spring (0/1) - Idx 05 Set axis saturation threshold (0..2048) - -**** Set Effect State **** -OP= 42 -LEN= 1 -00 State - Bit 3 Pause force feedback - Bit 2 Enable force feedback - Bit 0 Stop all effects - -**** Set overall gain **** -OP= 43 -LEN= 1 -00 Gain - Val 00 = 0% - Val 40 = 50% - Val 80 = 100% - -** Parameter memory ** - -Each device has a certain amount of memory to store parameters of effects. -The amount of RAM may vary, I encountered values from 200 to 1000 bytes. Below -is the amount of memory apparently needed for every set of parameters: - - period : 0c - - magnitude : 02 - - attack and fade : 0e - - interactive : 08 - -** Appendix: How to study the protocol ? ** - -1. Generate effects using the force editor provided with the DirectX SDK, or use Immersion Studio (freely available at their web site in the developer section: www.immersion.com) -2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!) -3. Play the effect, and watch what happens on the spy screen. - -A few words about ComPortSpy: -At first glance, this soft seems, hum, well... buggy. In fact, data appear with a few seconds latency. Personnaly, I restart it every time I play an effect. -Remember it's free (as in free beer) and alpha! - -** URLS ** -Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy. - -** Author of this document ** -Johann Deneux -Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/ - -Additions by Vojtech Pavlik. - -I-Force is trademark of Immersion Corp. +** Introduction +This document describes what I managed to discover about the protocol used to +specify force effects to I-Force 2.0 devices. None of this information comes +from Immerse. That's why you should not trust what is written in this +document. This document is intended to help understanding the protocol. +This is not a reference. Comments and corrections are welcome. To contact me, +send an email to: deneux@ifrance.com + +** WARNING ** +I may not be held responsible for any dammage or harm caused if you try to +send data to your I-Force device based on what you read in this document. + +** Preliminary Notes: +All values are hexadecimal with big-endian encoding (msb on the left). Beware, +values inside packets are encoded using little-endian. Bytes whose roles are +unknown are marked ??? Information that needs deeper inspection is marked (?) + +** General form of a packet ** +This is how packets look when the device uses the rs232 to communicate. +2B OP LEN DATA CS +CS is the checksum. It is equal to the exclusive or of all bytes. + +When using USB: +OP DATA +The 2B, LEN and CS fields have disappeared, probably because USB handles frames and +data corruption is handled or unsignificant. + +First, I describe effects that are sent by the device to the computer + +** Device input state +This packet is used to indicate the state of each button and the value of each +axis +OP= 01 for a joystick, 03 for a wheel +LEN= Varies from device to device +00 X-Axis lsb +01 X-Axis msb +02 Y-Axis lsb, or gas pedal for a wheel +03 Y-Axis msb, or brake pedal for a wheel +04 Throttle +05 Buttons +06 Lower 4 bits: Buttons + Upper 4 bits: Hat +07 Rudder + +** Device effects states +OP= 02 +LEN= Varies +00 ? Bit 1 (Value 2) is the value of the deadman switch +01 Bit 8 is set if the effect is playing. Bits 0 to 7 are the effect id. +02 ?? +03 Address of parameter block changed (lsb) +04 Address of parameter block changed (msb) +05 Address of second parameter block changed (lsb) +... depending on the number of parameter blocks updated + +** Force effect ** +OP= 01 +LEN= 0e +00 Channel (when playing several effects at the same time, each must be assigned a channel) +01 Wave form + Val 00 Constant + Val 20 Square + Val 21 Triangle + Val 22 Sine + Val 23 Sawtooth up + Val 24 Sawtooth down + Val 40 Spring (Force = f(pos)) + Val 41 Friction (Force = f(velocity)) and Inertia (Force = f(acceleration)) + + +02 Axes affected and trigger + Bits 4-7: Val 2 = effect along one axis. Byte 05 indicates direction + Val 4 = X axis only. Byte 05 must contain 5a + Val 8 = Y axis only. Byte 05 must contain b4 + Val c = X and Y axes. Bytes 05 must contain 60 + Bits 0-3: Val 0 = No trigger + Val x+1 = Button x triggers the effect + When the whole byte is 0, cancel the previously set trigger + +03-04 Duration of effect (little endian encoding, in ms) + +05 Direction of effect, if applicable. Else, see 02 for value to assign. + +06-07 Minimum time between triggering. + +08-09 Address of periodicity or magnitude parameters +0a-0b Address of attack and fade parameters, or ffff if none. +*or* +08-09 Address of interactive parameters for X-axis, or ffff if not applicable +0a-0b Address of interactive parameters for Y-axis, or ffff if not applicable + +0c-0d Delay before execution of effect (little endian encoding, in ms) + + +** Time based parameters ** + +*** Attack and fade *** +OP= 02 +LEN= 08 +00-01 Address where to store the parameteres +02-03 Duration of attack (little endian encoding, in ms) +04 Level at end of attack. Signed byte. +05-06 Duration of fade. +07 Level at end of fade. + +*** Magnitude *** +OP= 03 +LEN= 03 +00-01 Address +02 Level. Signed byte. + +*** Periodicity *** +OP= 04 +LEN= 07 +00-01 Address +02 Magnitude. Signed byte. +03 Offset. Signed byte. +04 Phase. Val 00 = 0 deg, Val 40 = 90 degs. +05-06 Period (little endian encoding, in ms) + +** Interactive parameters ** +OP= 05 +LEN= 0a +00-01 Address +02 Positive Coeff +03 Negative Coeff +04+05 Offset (center) +06+07 Dead band (Val 01F4 = 5000 (decimal)) +08 Positive saturation (Val 0a = 1000 (decimal) Val 64 = 10000 (decimal)) +09 Negative saturation + +The encoding is a bit funny here: For coeffs, these are signed values. The +maximum value is 64 (100 decimal), the min is 9c. +For the offset, the minimum value is FE0C, the maximum value is 01F4. +For the deadband, the minimum value is 0, the max is 03E8. + +** Controls ** +OP= 41 +LEN= 03 +00 Channel +01 Start/Stop + Val 00: Stop + Val 01: Start and play once. + Val 41: Start and play n times (See byte 02 below) +02 Number of iterations n. + +** Init ** + +*** Querying features *** +OP= ff +Query command. Length varies according to the query type. +The general format of this packet is: +ff 01 QUERY [INDEX] CHECKSUM +reponses are of the same form: +FF LEN QUERY VALUE_QUERIED CHECKSUM2 +where LEN = 1 + length(VALUE_QUERIED) + +**** Query ram size **** +QUERY = 42 ('B'uffer size) +The device should reply with the same packet plus two additionnal bytes +containing the size of the memory: +ff 03 42 03 e8 CS would mean that the device has 1000 bytes of ram available. + +**** Query number of effects **** +QUERY = 4e ('N'umber of effects) +The device should respond by sending the number of effects that can be played +at the same time (one byte) +ff 02 4e 14 CS would stand for 20 effects. + +**** Vendor's id **** +QUERY = 4d ('M'anufacturer) +Query the vendors'id (2 bytes) + +**** Product id ***** +QUERY = 50 ('P'roduct) +Query the product id (2 bytes) + +**** Open device **** +QUERY = 4f ('O'pen) +No data returned. + +**** Close device ***** +QUERY = 43 ('C')lose +No data returned. + +**** Query effect **** +QUERY = 45 ('E') +Send effect type. +Returns nonzero if supported (2 bytes) + +**** Firmware Version **** +QUERY = 56 ('V'ersion) +Sends back 3 bytes - major, minor, subminor + +*** Initialisation of the device *** + +**** Set Control **** +!!! Device dependent, can be different on different models !!! +OP= 40 [] +LEN= 2 or 3 +00 Idx + Idx 00 Set dead zone (0..2048) + Idx 01 Ignore Deadman sensor (0..1) + Idx 02 Enable comm watchdog (0..1) + Idx 03 Set the strength of the spring (0..100) + Idx 04 Enable or disable the spring (0/1) + Idx 05 Set axis saturation threshold (0..2048) + +**** Set Effect State **** +OP= 42 +LEN= 1 +00 State + Bit 3 Pause force feedback + Bit 2 Enable force feedback + Bit 0 Stop all effects + +**** Set overall gain **** +OP= 43 +LEN= 1 +00 Gain + Val 00 = 0% + Val 40 = 50% + Val 80 = 100% + +** Parameter memory ** + +Each device has a certain amount of memory to store parameters of effects. +The amount of RAM may vary, I encountered values from 200 to 1000 bytes. Below +is the amount of memory apparently needed for every set of parameters: + - period : 0c + - magnitude : 02 + - attack and fade : 0e + - interactive : 08 + +** Appendix: How to study the protocol ? ** + +1. Generate effects using the force editor provided with the DirectX SDK, or use Immersion Studio (freely available at their web site in the developer section: www.immersion.com) +2. Start a soft spying RS232 or USB (depending on where you connected your joystick/wheel). I used ComPortSpy from fCoder (alpha version!) +3. Play the effect, and watch what happens on the spy screen. + +A few words about ComPortSpy: +At first glance, this soft seems, hum, well... buggy. In fact, data appear with a few seconds latency. Personnaly, I restart it every time I play an effect. +Remember it's free (as in free beer) and alpha! + +** URLS ** +Check www.immerse.com for Immersion Studio, and www.fcoder.com for ComPortSpy. + +** Author of this document ** +Johann Deneux +Home page at http://www.esil.univ-mrs.fr/~jdeneux/projects/ff/ + +Additions by Vojtech Pavlik. + +I-Force is trademark of Immersion Corp. diff --git a/trunk/Documentation/lguest/lguest.c b/trunk/Documentation/lguest/lguest.c index 73c5f1f3d5d2..f7918401a007 100644 --- a/trunk/Documentation/lguest/lguest.c +++ b/trunk/Documentation/lguest/lguest.c @@ -882,7 +882,7 @@ static u32 handle_block_output(int fd, const struct iovec *iov, * of the block file (possibly extending it). */ if (off + len > device_len) { /* Trim it back to the correct length */ - ftruncate64(dev->fd, device_len); + ftruncate(dev->fd, device_len); /* Die, bad Guest, die. */ errx(1, "Write past end %llu+%u", off, len); } diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 9a91d9e3f1f2..9c54a5ef0ba7 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -2622,8 +2622,8 @@ P: Harald Welte P: Jozsef Kadlecsik P: Patrick McHardy M: kaber@trash.net -L: netfilter-devel@vger.kernel.org -L: netfilter@vger.kernel.org +L: netfilter-devel@lists.netfilter.org +L: netfilter@lists.netfilter.org (subscribers-only) L: coreteam@netfilter.org W: http://www.netfilter.org/ W: http://www.iptables.org/ @@ -2676,7 +2676,7 @@ M: jmorris@namei.org P: Hideaki YOSHIFUJI M: yoshfuji@linux-ipv6.org P: Patrick McHardy -M: kaber@trash.net +M: kaber@coreworks.de L: netdev@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git S: Maintained diff --git a/trunk/Makefile b/trunk/Makefile index 4dac25301d5f..c265e41ec55a 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 23 -EXTRAVERSION =-rc8 +EXTRAVERSION =-rc7 NAME = Arr Matey! A Hairy Bilge Rat! # *DOCUMENTATION* diff --git a/trunk/arch/arm/mach-ep93xx/core.c b/trunk/arch/arm/mach-ep93xx/core.c index 70b2c7801110..851cc7158ca3 100644 --- a/trunk/arch/arm/mach-ep93xx/core.c +++ b/trunk/arch/arm/mach-ep93xx/core.c @@ -336,7 +336,7 @@ static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) if (line >= 0 && line < 16) { gpio_line_config(line, GPIO_IN); } else { - gpio_line_config(EP93XX_GPIO_LINE_F(line-16), GPIO_IN); + gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN); } port = line >> 3; diff --git a/trunk/arch/arm/mm/cache-l2x0.c b/trunk/arch/arm/mm/cache-l2x0.c index 76b800a95191..b4e9b734e0bd 100644 --- a/trunk/arch/arm/mm/cache-l2x0.c +++ b/trunk/arch/arm/mm/cache-l2x0.c @@ -57,17 +57,7 @@ static void l2x0_inv_range(unsigned long start, unsigned long end) { unsigned long addr; - if (start & (CACHE_LINE_SIZE - 1)) { - start &= ~(CACHE_LINE_SIZE - 1); - sync_writel(start, L2X0_CLEAN_INV_LINE_PA, 1); - start += CACHE_LINE_SIZE; - } - - if (end & (CACHE_LINE_SIZE - 1)) { - end &= ~(CACHE_LINE_SIZE - 1); - sync_writel(end, L2X0_CLEAN_INV_LINE_PA, 1); - } - + start &= ~(CACHE_LINE_SIZE - 1); for (addr = start; addr < end; addr += CACHE_LINE_SIZE) sync_writel(addr, L2X0_INV_LINE_PA, 1); cache_sync(); diff --git a/trunk/arch/i386/boot/memory.c b/trunk/arch/i386/boot/memory.c index 1a2e62db8bed..bccaa1cf6645 100644 --- a/trunk/arch/i386/boot/memory.c +++ b/trunk/arch/i386/boot/memory.c @@ -20,6 +20,7 @@ static int detect_memory_e820(void) { + int count = 0; u32 next = 0; u32 size, id; u8 err; @@ -33,14 +34,24 @@ static int detect_memory_e820(void) "=m" (*desc) : "D" (desc), "a" (0xe820)); - if (err || id != SMAP) + /* Some BIOSes stop returning SMAP in the middle of + the search loop. We don't know exactly how the BIOS + screwed up the map at that point, we might have a + partial map, the full map, or complete garbage, so + just return failure. */ + if (id != SMAP) { + count = 0; break; + } - boot_params.e820_entries++; + if (err) + break; + + count++; desc++; - } while (next && boot_params.e820_entries < E820MAX); + } while (next && count < E820MAX); - return boot_params.e820_entries; + return boot_params.e820_entries = count; } static int detect_memory_e801(void) @@ -89,11 +100,16 @@ static int detect_memory_88(void) int detect_memory(void) { + int err = -1; + if (detect_memory_e820() > 0) - return 0; + err = 0; if (!detect_memory_e801()) - return 0; + err = 0; + + if (!detect_memory_88()) + err = 0; - return detect_memory_88(); + return err; } diff --git a/trunk/arch/i386/xen/mmu.c b/trunk/arch/i386/xen/mmu.c index 874db0cd1d2a..4ae038aa6c24 100644 --- a/trunk/arch/i386/xen/mmu.c +++ b/trunk/arch/i386/xen/mmu.c @@ -559,9 +559,6 @@ void xen_exit_mmap(struct mm_struct *mm) put_cpu(); spin_lock(&mm->page_table_lock); - - /* pgd may not be pinned in the error exit path of execve */ - if (PagePinned(virt_to_page(mm->pgd))) - xen_pgd_unpin(mm->pgd); + xen_pgd_unpin(mm->pgd); spin_unlock(&mm->page_table_lock); } diff --git a/trunk/arch/mips/kernel/i8259.c b/trunk/arch/mips/kernel/i8259.c index 3a2d255361bc..b6c30800c667 100644 --- a/trunk/arch/mips/kernel/i8259.c +++ b/trunk/arch/mips/kernel/i8259.c @@ -177,7 +177,10 @@ void mask_and_ack_8259A(unsigned int irq) outb(cached_master_mask, PIC_MASTER_IMR); outb(0x60+irq,PIC_MASTER_CMD); /* 'Specific EOI to master */ } - smtc_im_ack_irq(irq); +#ifdef CONFIG_MIPS_MT_SMTC + if (irq_hwmask[irq] & ST0_IM) + set_c0_status(irq_hwmask[irq] & ST0_IM); +#endif /* CONFIG_MIPS_MT_SMTC */ spin_unlock_irqrestore(&i8259A_lock, flags); return; diff --git a/trunk/arch/mips/kernel/irq-msc01.c b/trunk/arch/mips/kernel/irq-msc01.c index 1ecdd50bfc60..410868b5ea5f 100644 --- a/trunk/arch/mips/kernel/irq-msc01.c +++ b/trunk/arch/mips/kernel/irq-msc01.c @@ -52,8 +52,11 @@ static void level_mask_and_ack_msc_irq(unsigned int irq) mask_msc_irq(irq); if (!cpu_has_veic) MSCIC_WRITE(MSC01_IC_EOI, 0); +#ifdef CONFIG_MIPS_MT_SMTC /* This actually needs to be a call into platform code */ - smtc_im_ack_irq(irq); + if (irq_hwmask[irq] & ST0_IM) + set_c0_status(irq_hwmask[irq] & ST0_IM); +#endif /* CONFIG_MIPS_MT_SMTC */ } /* @@ -70,7 +73,10 @@ static void edge_mask_and_ack_msc_irq(unsigned int irq) MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT); MSCIC_WRITE(MSC01_IC_SUP+irq*8, r); } - smtc_im_ack_irq(irq); +#ifdef CONFIG_MIPS_MT_SMTC + if (irq_hwmask[irq] & ST0_IM) + set_c0_status(irq_hwmask[irq] & ST0_IM); +#endif /* CONFIG_MIPS_MT_SMTC */ } /* diff --git a/trunk/arch/mips/kernel/irq.c b/trunk/arch/mips/kernel/irq.c index a990aad2f049..aeded6c17de5 100644 --- a/trunk/arch/mips/kernel/irq.c +++ b/trunk/arch/mips/kernel/irq.c @@ -74,12 +74,20 @@ EXPORT_SYMBOL_GPL(free_irqno); */ void ack_bad_irq(unsigned int irq) { - smtc_im_ack_irq(irq); printk("unexpected IRQ # %d\n", irq); } atomic_t irq_err_count; +#ifdef CONFIG_MIPS_MT_SMTC +/* + * SMTC Kernel needs to manipulate low-level CPU interrupt mask + * in do_IRQ. These are passed in setup_irq_smtc() and stored + * in this table. + */ +unsigned long irq_hwmask[NR_IRQS]; +#endif /* CONFIG_MIPS_MT_SMTC */ + /* * Generic, controller-independent functions: */ diff --git a/trunk/arch/mips/kernel/smtc.c b/trunk/arch/mips/kernel/smtc.c index f09404377ef1..43826c16101d 100644 --- a/trunk/arch/mips/kernel/smtc.c +++ b/trunk/arch/mips/kernel/smtc.c @@ -25,11 +25,8 @@ #include /* - * SMTC Kernel needs to manipulate low-level CPU interrupt mask - * in do_IRQ. These are passed in setup_irq_smtc() and stored - * in this table. + * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */ -unsigned long irq_hwmask[NR_IRQS]; #define LOCK_MT_PRA() \ local_irq_save(flags); \ diff --git a/trunk/arch/mips/sibyte/bcm1480/setup.c b/trunk/arch/mips/sibyte/bcm1480/setup.c index 7e1aa348b8e0..bb28f28e8042 100644 --- a/trunk/arch/mips/sibyte/bcm1480/setup.c +++ b/trunk/arch/mips/sibyte/bcm1480/setup.c @@ -15,7 +15,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include #include #include #include @@ -36,7 +35,6 @@ unsigned int soc_type; EXPORT_SYMBOL(soc_type); unsigned int periph_rev; unsigned int zbbus_mhz; -EXPORT_SYMBOL(zbbus_mhz); static unsigned int part_type; diff --git a/trunk/arch/powerpc/kernel/process.c b/trunk/arch/powerpc/kernel/process.c index 8a1b001d0b11..e477c9d0498b 100644 --- a/trunk/arch/powerpc/kernel/process.c +++ b/trunk/arch/powerpc/kernel/process.c @@ -605,13 +605,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) regs->ccr = 0; regs->gpr[1] = sp; - /* - * We have just cleared all the nonvolatile GPRs, so make - * FULL_REGS(regs) return true. This is necessary to allow - * ptrace to examine the thread immediately after exec. - */ - regs->trap &= ~1UL; - #ifdef CONFIG_PPC32 regs->mq = 0; regs->nip = start; diff --git a/trunk/arch/powerpc/platforms/cell/spufs/file.c b/trunk/arch/powerpc/platforms/cell/spufs/file.c index 7de4e919687b..4100ddc52f02 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/file.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/file.c @@ -2177,8 +2177,8 @@ struct tree_descr spufs_dir_contents[] = { { "mbox_stat", &spufs_mbox_stat_fops, 0444, }, { "ibox_stat", &spufs_ibox_stat_fops, 0444, }, { "wbox_stat", &spufs_wbox_stat_fops, 0444, }, - { "signal1", &spufs_signal1_fops, 0666, }, - { "signal2", &spufs_signal2_fops, 0666, }, + { "signal1", &spufs_signal1_nosched_fops, 0222, }, + { "signal2", &spufs_signal2_nosched_fops, 0222, }, { "signal1_type", &spufs_signal1_type, 0666, }, { "signal2_type", &spufs_signal2_type, 0666, }, { "cntl", &spufs_cntl_fops, 0666, }, diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig index b4d9089a6a06..ffa036406289 100644 --- a/trunk/arch/x86_64/Kconfig +++ b/trunk/arch/x86_64/Kconfig @@ -60,6 +60,14 @@ config ZONE_DMA bool default y +config QUICKLIST + bool + default y + +config NR_QUICK + int + default 2 + config ISA bool diff --git a/trunk/arch/x86_64/ia32/ia32entry.S b/trunk/arch/x86_64/ia32/ia32entry.S index 18b231810908..938278697e20 100644 --- a/trunk/arch/x86_64/ia32/ia32entry.S +++ b/trunk/arch/x86_64/ia32/ia32entry.S @@ -38,18 +38,6 @@ movq %rax,R8(%rsp) .endm - .macro LOAD_ARGS32 offset - movl \offset(%rsp),%r11d - movl \offset+8(%rsp),%r10d - movl \offset+16(%rsp),%r9d - movl \offset+24(%rsp),%r8d - movl \offset+40(%rsp),%ecx - movl \offset+48(%rsp),%edx - movl \offset+56(%rsp),%esi - movl \offset+64(%rsp),%edi - movl \offset+72(%rsp),%eax - .endm - .macro CFI_STARTPROC32 simple CFI_STARTPROC \simple CFI_UNDEFINED r8 @@ -164,7 +152,7 @@ sysenter_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST movl %ebp, %ebp /* no need to do an access_ok check here because rbp has been @@ -267,7 +255,7 @@ cstar_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST movl RSP-ARGOFFSET(%rsp), %r8d /* no need to do an access_ok check here because r8 has been @@ -346,7 +334,7 @@ ia32_tracesys: movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter - LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST jmp ia32_do_syscall END(ia32_syscall) diff --git a/trunk/arch/x86_64/kernel/process.c b/trunk/arch/x86_64/kernel/process.c index 98956555450b..2842f50cbe3f 100644 --- a/trunk/arch/x86_64/kernel/process.c +++ b/trunk/arch/x86_64/kernel/process.c @@ -208,6 +208,7 @@ void cpu_idle (void) if (__get_cpu_var(cpu_idle_state)) __get_cpu_var(cpu_idle_state) = 0; + check_pgt_cache(); rmb(); idle = pm_idle; if (!idle) diff --git a/trunk/arch/x86_64/kernel/ptrace.c b/trunk/arch/x86_64/kernel/ptrace.c index eea3702427b4..e83cc67155ac 100644 --- a/trunk/arch/x86_64/kernel/ptrace.c +++ b/trunk/arch/x86_64/kernel/ptrace.c @@ -232,6 +232,10 @@ static int putreg(struct task_struct *child, { unsigned long tmp; + /* Some code in the 64bit emulation may not be 64bit clean. + Don't take any chances. */ + if (test_tsk_thread_flag(child, TIF_IA32)) + value &= 0xffffffff; switch (regno) { case offsetof(struct user_regs_struct,fs): if (value && (value & 3) != 3) diff --git a/trunk/arch/x86_64/kernel/smp.c b/trunk/arch/x86_64/kernel/smp.c index df4a82812adb..673a300b5944 100644 --- a/trunk/arch/x86_64/kernel/smp.c +++ b/trunk/arch/x86_64/kernel/smp.c @@ -241,7 +241,7 @@ void flush_tlb_mm (struct mm_struct * mm) } if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, FLUSH_ALL); - + check_pgt_cache(); preempt_enable(); } EXPORT_SYMBOL(flush_tlb_mm); diff --git a/trunk/crypto/async_tx/async_tx.c b/trunk/crypto/async_tx/async_tx.c index bc18cbb8ea79..035007145e78 100644 --- a/trunk/crypto/async_tx/async_tx.c +++ b/trunk/crypto/async_tx/async_tx.c @@ -80,7 +80,6 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) { enum dma_status status; struct dma_async_tx_descriptor *iter; - struct dma_async_tx_descriptor *parent; if (!tx) return DMA_SUCCESS; @@ -88,15 +87,8 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx) /* poll through the dependency chain, return when tx is complete */ do { iter = tx; - - /* find the root of the unsubmitted dependency chain */ - while (iter->cookie == -EBUSY) { - parent = iter->parent; - if (parent && parent->cookie == -EBUSY) - iter = iter->parent; - else - break; - } + while (iter->cookie == -EBUSY) + iter = iter->parent; status = dma_sync_wait(iter->chan, iter->cookie); } while (status == DMA_IN_PROGRESS || (iter != tx)); diff --git a/trunk/drivers/acpi/processor_core.c b/trunk/drivers/acpi/processor_core.c index 9f11dc296cdd..2afb3d2086b3 100644 --- a/trunk/drivers/acpi/processor_core.c +++ b/trunk/drivers/acpi/processor_core.c @@ -102,8 +102,6 @@ static struct acpi_driver acpi_processor_driver = { .add = acpi_processor_add, .remove = acpi_processor_remove, .start = acpi_processor_start, - .suspend = acpi_processor_suspend, - .resume = acpi_processor_resume, }, }; diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index f18261368e76..d9b8af763e1e 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -325,23 +325,6 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, #endif -/* - * Suspend / resume control - */ -static int acpi_idle_suspend; - -int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) -{ - acpi_idle_suspend = 1; - return 0; -} - -int acpi_processor_resume(struct acpi_device * device) -{ - acpi_idle_suspend = 0; - return 0; -} - static void acpi_processor_idle(void) { struct acpi_processor *pr = NULL; @@ -372,7 +355,7 @@ static void acpi_processor_idle(void) } cx = pr->power.state; - if (!cx || acpi_idle_suspend) { + if (!cx) { if (pm_idle_save) pm_idle_save(); else diff --git a/trunk/drivers/acpi/sleep/Makefile b/trunk/drivers/acpi/sleep/Makefile index f1fb888c2d29..195a4f69c0f7 100644 --- a/trunk/drivers/acpi/sleep/Makefile +++ b/trunk/drivers/acpi/sleep/Makefile @@ -1,5 +1,5 @@ -obj-y := wakeup.o -obj-y += main.o +obj-y := poweroff.o wakeup.o +obj-$(CONFIG_ACPI_SLEEP) += main.o obj-$(CONFIG_ACPI_SLEEP) += proc.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/trunk/drivers/acpi/sleep/main.c b/trunk/drivers/acpi/sleep/main.c index 2cbb9aabd00e..c52ade816fb4 100644 --- a/trunk/drivers/acpi/sleep/main.c +++ b/trunk/drivers/acpi/sleep/main.c @@ -15,39 +15,13 @@ #include #include #include - -#include - #include #include #include "sleep.h" u8 sleep_states[ACPI_S_STATE_COUNT]; -#ifdef CONFIG_PM_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; -#endif - -int acpi_sleep_prepare(u32 acpi_state) -{ -#ifdef CONFIG_ACPI_SLEEP - /* do we have a wakeup address for S2 and S3? */ - if (acpi_state == ACPI_STATE_S3) { - if (!acpi_wakeup_address) { - return -EFAULT; - } - acpi_set_firmware_waking_vector((acpi_physical_address) - virt_to_phys((void *) - acpi_wakeup_address)); - - } - ACPI_FLUSH_CPU_CACHE(); - acpi_enable_wakeup_device_prep(acpi_state); -#endif - acpi_gpe_sleep_prepare(acpi_state); - acpi_enter_sleep_state_prep(acpi_state); - return 0; -} #ifdef CONFIG_SUSPEND static struct pm_ops acpi_pm_ops; @@ -301,7 +275,6 @@ int acpi_suspend(u32 acpi_state) return -EINVAL; } -#ifdef CONFIG_PM_SLEEP /** * acpi_pm_device_sleep_state - return preferred power state of ACPI device * in the system sleep state given by %acpi_target_sleep_state @@ -376,21 +349,6 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) *d_min_p = d_min; return d_max; } -#endif - -static void acpi_power_off_prepare(void) -{ - /* Prepare to power off the system */ - acpi_sleep_prepare(ACPI_STATE_S5); -} - -static void acpi_power_off(void) -{ - /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ - printk("%s called\n", __FUNCTION__); - local_irq_disable(); - acpi_enter_sleep_state(ACPI_STATE_S5); -} int __init acpi_sleep_init(void) { @@ -405,17 +363,16 @@ int __init acpi_sleep_init(void) if (acpi_disabled) return 0; - sleep_states[ACPI_STATE_S0] = 1; - printk(KERN_INFO PREFIX "(supports S0"); - #ifdef CONFIG_SUSPEND - for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) { + printk(KERN_INFO PREFIX "(supports"); + for (i = ACPI_STATE_S0; i < ACPI_STATE_S4; i++) { status = acpi_get_sleep_type_data(i, &type_a, &type_b); if (ACPI_SUCCESS(status)) { sleep_states[i] = 1; printk(" S%d", i); } } + printk(")\n"); pm_set_ops(&acpi_pm_ops); #endif @@ -425,16 +382,10 @@ int __init acpi_sleep_init(void) if (ACPI_SUCCESS(status)) { hibernation_set_ops(&acpi_hibernation_ops); sleep_states[ACPI_STATE_S4] = 1; - printk(" S4"); } +#else + sleep_states[ACPI_STATE_S4] = 0; #endif - status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); - if (ACPI_SUCCESS(status)) { - sleep_states[ACPI_STATE_S5] = 1; - printk(" S5"); - pm_power_off_prepare = acpi_power_off_prepare; - pm_power_off = acpi_power_off; - } - printk(")\n"); + return 0; } diff --git a/trunk/drivers/acpi/sleep/poweroff.c b/trunk/drivers/acpi/sleep/poweroff.c new file mode 100644 index 000000000000..39e40d56b034 --- /dev/null +++ b/trunk/drivers/acpi/sleep/poweroff.c @@ -0,0 +1,75 @@ +/* + * poweroff.c - ACPI handler for powering off the system. + * + * AKA S5, but it is independent of whether or not the kernel supports + * any other sleep support in the system. + * + * Copyright (c) 2005 Alexey Starikovskiy + * + * This file is released under the GPLv2. + */ + +#include +#include +#include +#include +#include +#include "sleep.h" + +int acpi_sleep_prepare(u32 acpi_state) +{ +#ifdef CONFIG_ACPI_SLEEP + /* do we have a wakeup address for S2 and S3? */ + if (acpi_state == ACPI_STATE_S3) { + if (!acpi_wakeup_address) { + return -EFAULT; + } + acpi_set_firmware_waking_vector((acpi_physical_address) + virt_to_phys((void *) + acpi_wakeup_address)); + + } + ACPI_FLUSH_CPU_CACHE(); + acpi_enable_wakeup_device_prep(acpi_state); +#endif + acpi_gpe_sleep_prepare(acpi_state); + acpi_enter_sleep_state_prep(acpi_state); + return 0; +} + +#ifdef CONFIG_PM + +static void acpi_power_off_prepare(void) +{ + /* Prepare to power off the system */ + acpi_sleep_prepare(ACPI_STATE_S5); +} + +static void acpi_power_off(void) +{ + /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ + printk("%s called\n", __FUNCTION__); + local_irq_disable(); + /* Some SMP machines only can poweroff in boot CPU */ + acpi_enter_sleep_state(ACPI_STATE_S5); +} + +static int acpi_poweroff_init(void) +{ + if (!acpi_disabled) { + u8 type_a, type_b; + acpi_status status; + + status = + acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { + pm_power_off_prepare = acpi_power_off_prepare; + pm_power_off = acpi_power_off; + } + } + return 0; +} + +late_initcall(acpi_poweroff_init); + +#endif /* CONFIG_PM */ diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index d05891f16282..3c9bb85a6a93 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -417,6 +417,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) arg0.integer.value = level; status = acpi_evaluate_object(device->dev->handle, "_BCM", &args, NULL); + printk(KERN_DEBUG "set_level status: %x\n", status); return status; } @@ -1753,7 +1754,7 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) static int acpi_video_bus_start_devices(struct acpi_video_bus *video) { - return acpi_video_bus_DOS(video, 0, 0); + return acpi_video_bus_DOS(video, 1, 0); } static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index c16820325d7b..06f212ff2b4f 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -418,12 +418,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */ - { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4394), board_ahci_sb600 }, /* ATI SB700/800 */ - { PCI_VDEVICE(ATI, 0x4395), board_ahci_sb600 }, /* ATI SB700/800 */ + { PCI_VDEVICE(ATI, 0x4390), board_ahci_sb600 }, /* ATI SB700 IDE */ + { PCI_VDEVICE(ATI, 0x4391), board_ahci_sb600 }, /* ATI SB700 AHCI */ + { PCI_VDEVICE(ATI, 0x4392), board_ahci_sb600 }, /* ATI SB700 nraid5 */ + { PCI_VDEVICE(ATI, 0x4393), board_ahci_sb600 }, /* ATI SB700 raid5 */ /* VIA */ { PCI_VDEVICE(VIA, 0x3349), board_ahci_vt8251 }, /* VIA VT8251 */ diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 772be09b4689..c43de9a710db 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -3778,9 +3778,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "Maxtor 6L250S0", "BANC1G10", ATA_HORKAGE_NONCQ }, { "Maxtor 6B200M0", "BANC1BM0", ATA_HORKAGE_NONCQ }, { "Maxtor 6B200M0", "BANC1B10", ATA_HORKAGE_NONCQ }, - { "Maxtor 7B250S0", "BANC1B70", ATA_HORKAGE_NONCQ, }, - { "Maxtor 7B300S0", "BANC1B70", ATA_HORKAGE_NONCQ }, - { "Maxtor 7V300F0", "VA111630", ATA_HORKAGE_NONCQ }, { "HITACHI HDS7250SASUN500G 0621KTAWSD", "K2AOAJ0AHITACHI", ATA_HORKAGE_NONCQ }, /* NCQ hard hangs device under heavier load, needs hard power cycle */ @@ -3797,7 +3794,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, }, { "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, }, { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, }, - { "ST3160812AS", "3.AD", ATA_HORKAGE_NONCQ, }, { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, }, /* devices which puke on READ_NATIVE_MAX */ diff --git a/trunk/drivers/ata/libata-sff.c b/trunk/drivers/ata/libata-sff.c index 8023167bbbeb..1cce2198baaf 100644 --- a/trunk/drivers/ata/libata-sff.c +++ b/trunk/drivers/ata/libata-sff.c @@ -297,7 +297,7 @@ void ata_bmdma_start (struct ata_queued_cmd *qc) dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); iowrite8(dmactl | ATA_DMA_START, ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - /* Strictly, one may wish to issue an ioread8() here, to + /* Strictly, one may wish to issue a readb() here, to * flush the mmio write. However, control also passes * to the hardware at this point, and it will interrupt * us when we are to resume control. So, in effect, @@ -307,9 +307,6 @@ void ata_bmdma_start (struct ata_queued_cmd *qc) * is expected, so I think it is best to not add a readb() * without first all the MMIO ATA cards/mobos. * Or maybe I'm just being paranoid. - * - * FIXME: The posting of this write means I/O starts are - * unneccessarily delayed for MMIO */ } diff --git a/trunk/drivers/ata/pata_sis.c b/trunk/drivers/ata/pata_sis.c index cce2834b2b60..2bd7645f1a88 100644 --- a/trunk/drivers/ata/pata_sis.c +++ b/trunk/drivers/ata/pata_sis.c @@ -375,9 +375,8 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev) int drive_pci = sis_old_port_base(adev); u16 timing; - /* MWDMA 0-2 and UDMA 0-5 */ const u16 mwdma_bits[] = { 0x008, 0x302, 0x301 }; - const u16 udma_bits[] = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000, 0x8000 }; + const u16 udma_bits[] = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000}; pci_read_config_word(pdev, drive_pci, &timing); diff --git a/trunk/drivers/ata/sata_sil24.c b/trunk/drivers/ata/sata_sil24.c index 233e88693395..ef83e6b1e314 100644 --- a/trunk/drivers/ata/sata_sil24.c +++ b/trunk/drivers/ata/sata_sil24.c @@ -888,16 +888,6 @@ static inline void sil24_host_intr(struct ata_port *ap) u32 slot_stat, qc_active; int rc; - /* If PCIX_IRQ_WOC, there's an inherent race window between - * clearing IRQ pending status and reading PORT_SLOT_STAT - * which may cause spurious interrupts afterwards. This is - * unavoidable and much better than losing interrupts which - * happens if IRQ pending is cleared after reading - * PORT_SLOT_STAT. - */ - if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) - writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); - slot_stat = readl(port + PORT_SLOT_STAT); if (unlikely(slot_stat & HOST_SSTAT_ATTN)) { @@ -905,6 +895,9 @@ static inline void sil24_host_intr(struct ata_port *ap) return; } + if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) + writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); + qc_active = slot_stat & ~HOST_SSTAT_ATTN; rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc); if (rc > 0) @@ -917,8 +910,7 @@ static inline void sil24_host_intr(struct ata_port *ap) return; } - /* spurious interrupts are expected if PCIX_IRQ_WOC */ - if (!(ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) && ata_ratelimit()) + if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " "(slot_stat 0x%x active_tag %d sactive 0x%x)\n", slot_stat, ap->active_tag, ap->sactive); diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c index 67c92582d6ef..6de33d7a29ba 100644 --- a/trunk/drivers/base/core.c +++ b/trunk/drivers/base/core.c @@ -284,7 +284,6 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr, /* let the kset specific function add its keys */ pos = data; - memset(envp, 0, sizeof(envp)); retval = kset->uevent_ops->uevent(kset, &dev->kobj, envp, ARRAY_SIZE(envp), pos, PAGE_SIZE); diff --git a/trunk/drivers/cdrom/cdrom.c b/trunk/drivers/cdrom/cdrom.c index 79245714f0a7..67ee3d4b2878 100644 --- a/trunk/drivers/cdrom/cdrom.c +++ b/trunk/drivers/cdrom/cdrom.c @@ -1032,10 +1032,6 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp) check_disk_change(ip->i_bdev); return 0; err_release: - if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { - cdi->ops->lock_door(cdi, 0); - cdinfo(CD_OPEN, "door unlocked.\n"); - } cdi->ops->release(cdi); err: cdi->use_count--; diff --git a/trunk/drivers/char/hpet.c b/trunk/drivers/char/hpet.c index 4c16778e3f84..7ecffc9c738f 100644 --- a/trunk/drivers/char/hpet.c +++ b/trunk/drivers/char/hpet.c @@ -62,8 +62,6 @@ static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; -/* This clocksource driver currently only works on ia64 */ -#ifdef CONFIG_IA64 static void __iomem *hpet_mctr; static cycle_t read_hpet(void) @@ -81,7 +79,6 @@ static struct clocksource clocksource_hpet = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; static struct clocksource *hpet_clocksource; -#endif /* A lock for concurrent access by app and isr hpet activity. */ static DEFINE_SPINLOCK(hpet_lock); @@ -946,14 +943,14 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) printk(KERN_DEBUG "%s: 0x%lx is busy\n", __FUNCTION__, hdp->hd_phys_address); iounmap(hdp->hd_address); - return AE_ALREADY_EXISTS; + return -EBUSY; } } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { struct acpi_resource_fixed_memory32 *fixmem32; fixmem32 = &res->data.fixed_memory32; if (!fixmem32) - return AE_NO_MEMORY; + return -EINVAL; hdp->hd_phys_address = fixmem32->address; hdp->hd_address = ioremap(fixmem32->address, @@ -963,7 +960,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) printk(KERN_DEBUG "%s: 0x%lx is busy\n", __FUNCTION__, hdp->hd_phys_address); iounmap(hdp->hd_address); - return AE_ALREADY_EXISTS; + return -EBUSY; } } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { struct acpi_resource_extended_irq *irqp; diff --git a/trunk/drivers/char/mspec.c b/trunk/drivers/char/mspec.c index 04ac155d3a07..049a46cc9f87 100644 --- a/trunk/drivers/char/mspec.c +++ b/trunk/drivers/char/mspec.c @@ -155,22 +155,23 @@ mspec_open(struct vm_area_struct *vma) * mspec_close * * Called when unmapping a device mapping. Frees all mspec pages - * belonging to all the vma's sharing this vma_data structure. + * belonging to the vma. */ static void mspec_close(struct vm_area_struct *vma) { struct vma_data *vdata; - int index, last_index; + int index, last_index, result; unsigned long my_page; vdata = vma->vm_private_data; - if (!atomic_dec_and_test(&vdata->refcnt)) - return; + BUG_ON(vma->vm_start < vdata->vm_start || vma->vm_end > vdata->vm_end); - last_index = (vdata->vm_end - vdata->vm_start) >> PAGE_SHIFT; - for (index = 0; index < last_index; index++) { + spin_lock(&vdata->lock); + index = (vma->vm_start - vdata->vm_start) >> PAGE_SHIFT; + last_index = (vma->vm_end - vdata->vm_start) >> PAGE_SHIFT; + for (; index < last_index; index++) { if (vdata->maddr[index] == 0) continue; /* @@ -179,12 +180,20 @@ mspec_close(struct vm_area_struct *vma) */ my_page = vdata->maddr[index]; vdata->maddr[index] = 0; - if (!mspec_zero_block(my_page, PAGE_SIZE)) + spin_unlock(&vdata->lock); + result = mspec_zero_block(my_page, PAGE_SIZE); + if (!result) uncached_free_page(my_page); else printk(KERN_WARNING "mspec_close(): " - "failed to zero page %ld\n", my_page); + "failed to zero page %i\n", + result); + spin_lock(&vdata->lock); } + spin_unlock(&vdata->lock); + + if (!atomic_dec_and_test(&vdata->refcnt)) + return; if (vdata->flags & VMD_VMALLOCED) vfree(vdata); @@ -192,6 +201,7 @@ mspec_close(struct vm_area_struct *vma) kfree(vdata); } + /* * mspec_nopfn * diff --git a/trunk/drivers/ieee1394/ieee1394_core.c b/trunk/drivers/ieee1394/ieee1394_core.c index 98fd985a32ff..ee45259573c8 100644 --- a/trunk/drivers/ieee1394/ieee1394_core.c +++ b/trunk/drivers/ieee1394/ieee1394_core.c @@ -1273,7 +1273,7 @@ static void __exit ieee1394_cleanup(void) unregister_chrdev_region(IEEE1394_CORE_DEV, 256); } -module_init(ieee1394_init); +fs_initcall(ieee1394_init); /* same as ohci1394 */ module_exit(ieee1394_cleanup); /* Exported symbols */ diff --git a/trunk/drivers/ieee1394/ohci1394.c b/trunk/drivers/ieee1394/ohci1394.c index 372c5c16eb31..5667c8102efc 100644 --- a/trunk/drivers/ieee1394/ohci1394.c +++ b/trunk/drivers/ieee1394/ohci1394.c @@ -3537,5 +3537,7 @@ static int __init ohci1394_init(void) return pci_register_driver(&ohci1394_pci_driver); } -module_init(ohci1394_init); +/* Register before most other device drivers. + * Useful for remote debugging via physical DMA, e.g. using firescope. */ +fs_initcall(ohci1394_init); module_exit(ohci1394_cleanup); diff --git a/trunk/drivers/infiniband/hw/mlx4/qp.c b/trunk/drivers/infiniband/hw/mlx4/qp.c index 85c51bdc36f1..ba0428d872aa 100644 --- a/trunk/drivers/infiniband/hw/mlx4/qp.c +++ b/trunk/drivers/infiniband/hw/mlx4/qp.c @@ -1211,42 +1211,12 @@ static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg, dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey); } -static void set_mlx_icrc_seg(void *dseg) -{ - u32 *t = dseg; - struct mlx4_wqe_inline_seg *iseg = dseg; - - t[1] = 0; - - /* - * Need a barrier here before writing the byte_count field to - * make sure that all the data is visible before the - * byte_count field is set. Otherwise, if the segment begins - * a new cacheline, the HCA prefetcher could grab the 64-byte - * chunk and get a valid (!= * 0xffffffff) byte count but - * stale data, and end up sending the wrong data. - */ - wmb(); - - iseg->byte_count = cpu_to_be32((1 << 31) | 4); -} - -static void set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg) +static void set_data_seg(struct mlx4_wqe_data_seg *dseg, + struct ib_sge *sg) { + dseg->byte_count = cpu_to_be32(sg->length); dseg->lkey = cpu_to_be32(sg->lkey); dseg->addr = cpu_to_be64(sg->addr); - - /* - * Need a barrier here before writing the byte_count field to - * make sure that all the data is visible before the - * byte_count field is set. Otherwise, if the segment begins - * a new cacheline, the HCA prefetcher could grab the 64-byte - * chunk and get a valid (!= * 0xffffffff) byte count but - * stale data, and end up sending the wrong data. - */ - wmb(); - - dseg->byte_count = cpu_to_be32(sg->length); } int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, @@ -1255,7 +1225,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, struct mlx4_ib_qp *qp = to_mqp(ibqp); void *wqe; struct mlx4_wqe_ctrl_seg *ctrl; - struct mlx4_wqe_data_seg *dseg; unsigned long flags; int nreq; int err = 0; @@ -1355,27 +1324,22 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, break; } - /* - * Write data segments in reverse order, so as to - * overwrite cacheline stamp last within each - * cacheline. This avoids issues with WQE - * prefetching. - */ + for (i = 0; i < wr->num_sge; ++i) { + set_data_seg(wqe, wr->sg_list + i); - dseg = wqe; - dseg += wr->num_sge - 1; - size += wr->num_sge * (sizeof (struct mlx4_wqe_data_seg) / 16); + wqe += sizeof (struct mlx4_wqe_data_seg); + size += sizeof (struct mlx4_wqe_data_seg) / 16; + } /* Add one more inline data segment for ICRC for MLX sends */ - if (unlikely(qp->ibqp.qp_type == IB_QPT_SMI || - qp->ibqp.qp_type == IB_QPT_GSI)) { - set_mlx_icrc_seg(dseg + 1); + if (qp->ibqp.qp_type == IB_QPT_SMI || qp->ibqp.qp_type == IB_QPT_GSI) { + ((struct mlx4_wqe_inline_seg *) wqe)->byte_count = + cpu_to_be32((1 << 31) | 4); + ((u32 *) wqe)[1] = 0; + wqe += sizeof (struct mlx4_wqe_data_seg); size += sizeof (struct mlx4_wqe_data_seg) / 16; } - for (i = wr->num_sge - 1; i >= 0; --i, --dseg) - set_data_seg(dseg, wr->sg_list + i); - ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ? MLX4_WQE_CTRL_FENCE : 0) | size; diff --git a/trunk/drivers/input/mouse/appletouch.c b/trunk/drivers/input/mouse/appletouch.c index a1804bfdbb8c..2bea1b2c631c 100644 --- a/trunk/drivers/input/mouse/appletouch.c +++ b/trunk/drivers/input/mouse/appletouch.c @@ -328,7 +328,6 @@ static void atp_complete(struct urb* urb) { int x, y, x_z, y_z, x_f, y_f; int retval, i, j; - int key; struct atp *dev = urb->context; switch (urb->status) { @@ -469,7 +468,6 @@ static void atp_complete(struct urb* urb) ATP_XFACT, &x_z, &x_f); y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS, ATP_YFACT, &y_z, &y_f); - key = dev->data[dev->datalen - 1] & 1; if (x && y) { if (dev->x_old != -1) { @@ -507,7 +505,7 @@ static void atp_complete(struct urb* urb) the first touch unless reinitialised. Do so if it's been idle for a while in order to avoid waking the kernel up several hundred times a second */ - if (!key && atp_is_geyser_3(dev)) { + if (atp_is_geyser_3(dev)) { dev->idlecount++; if (dev->idlecount == 10) { dev->valid = 0; @@ -516,7 +514,7 @@ static void atp_complete(struct urb* urb) } } - input_report_key(dev->input, BTN_LEFT, key); + input_report_key(dev->input, BTN_LEFT, dev->data[dev->datalen - 1] & 1); input_sync(dev->input); exit: diff --git a/trunk/drivers/kvm/Kconfig b/trunk/drivers/kvm/Kconfig index 0a419a0de603..7b64fd4aa2f3 100644 --- a/trunk/drivers/kvm/Kconfig +++ b/trunk/drivers/kvm/Kconfig @@ -6,8 +6,7 @@ menuconfig VIRTUALIZATION depends on X86 default y ---help--- - Say Y here to get to see options for using your Linux host to run other - operating systems inside virtual machines (guests). + Say Y here to get to see options for virtualization guest drivers. This option alone does not add any kernel code. If you say N, all options in this submenu will be skipped and disabled. diff --git a/trunk/drivers/lguest/lguest_asm.S b/trunk/drivers/lguest/lguest_asm.S index 1ddcd5cd20f6..f182c6a36209 100644 --- a/trunk/drivers/lguest/lguest_asm.S +++ b/trunk/drivers/lguest/lguest_asm.S @@ -22,9 +22,8 @@ jmp lguest_init /*G:055 We create a macro which puts the assembler code between lgstart_ and - * lgend_ markers. These templates are put in the .text section: they can't be - * discarded after boot as we may need to patch modules, too. */ -.text + * lgend_ markers. These templates end up in the .init.text section, so they + * are discarded after boot. */ #define LGUEST_PATCH(name, insns...) \ lgstart_##name: insns; lgend_##name:; \ .globl lgstart_##name; .globl lgend_##name @@ -35,6 +34,7 @@ LGUEST_PATCH(popf, movl %eax, lguest_data+LGUEST_DATA_irq_enabled) LGUEST_PATCH(pushf, movl lguest_data+LGUEST_DATA_irq_enabled, %eax) /*:*/ +.text /* These demark the EIP range where host should never deliver interrupts. */ .global lguest_noirq_start .global lguest_noirq_end diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index f96dea975fa5..4d63773ee73a 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -514,7 +514,7 @@ static void ops_complete_biofill(void *stripe_head_ref) struct stripe_head *sh = stripe_head_ref; struct bio *return_bi = NULL; raid5_conf_t *conf = sh->raid_conf; - int i; + int i, more_to_read = 0; pr_debug("%s: stripe %llu\n", __FUNCTION__, (unsigned long long)sh->sector); @@ -522,14 +522,16 @@ static void ops_complete_biofill(void *stripe_head_ref) /* clear completed biofills */ for (i = sh->disks; i--; ) { struct r5dev *dev = &sh->dev[i]; + /* check if this stripe has new incoming reads */ + if (dev->toread) + more_to_read++; /* acknowledge completion of a biofill operation */ - /* and check if we need to reply to a read request, - * new R5_Wantfill requests are held off until - * !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending) - */ - if (test_and_clear_bit(R5_Wantfill, &dev->flags)) { + /* and check if we need to reply to a read request + */ + if (test_bit(R5_Wantfill, &dev->flags) && !dev->toread) { struct bio *rbi, *rbi2; + clear_bit(R5_Wantfill, &dev->flags); /* The access to dev->read is outside of the * spin_lock_irq(&conf->device_lock), but is protected @@ -556,7 +558,8 @@ static void ops_complete_biofill(void *stripe_head_ref) return_io(return_bi); - set_bit(STRIPE_HANDLE, &sh->state); + if (more_to_read) + set_bit(STRIPE_HANDLE, &sh->state); release_stripe(sh); } diff --git a/trunk/drivers/media/video/usbvision/usbvision-video.c b/trunk/drivers/media/video/usbvision/usbvision-video.c index 0cb006f2943d..e3371f972240 100644 --- a/trunk/drivers/media/video/usbvision/usbvision-video.c +++ b/trunk/drivers/media/video/usbvision/usbvision-video.c @@ -1387,6 +1387,7 @@ static const struct file_operations usbvision_fops = { .ioctl = video_ioctl2, .llseek = no_llseek, /* .poll = video_poll, */ + .mmap = usbvision_v4l2_mmap, .compat_ioctl = v4l_compat_ioctl32, }; static struct video_device usbvision_video_template = { @@ -1412,7 +1413,7 @@ static struct video_device usbvision_video_template = { .vidioc_s_input = vidioc_s_input, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_audio = vidioc_s_audio, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, @@ -1458,7 +1459,7 @@ static struct video_device usbvision_radio_template= .vidioc_s_input = vidioc_s_input, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_audio = vidioc_s_audio, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_tuner = vidioc_g_tuner, diff --git a/trunk/drivers/net/bnx2.c b/trunk/drivers/net/bnx2.c index 66eed22cbd21..854d80c330ec 100644 --- a/trunk/drivers/net/bnx2.c +++ b/trunk/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.6.5" -#define DRV_MODULE_RELDATE "September 20, 2007" +#define DRV_MODULE_VERSION "1.6.4" +#define DRV_MODULE_RELDATE "August 3, 2007" #define RUN_AT(x) (jiffies + (x)) @@ -6727,8 +6727,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) } else if (CHIP_NUM(bp) == CHIP_NUM_5706 || CHIP_NUM(bp) == CHIP_NUM_5708) bp->phy_flags |= PHY_CRC_FIX_FLAG; - else if (CHIP_ID(bp) == CHIP_ID_5709_A0 || - CHIP_ID(bp) == CHIP_ID_5709_A1) + else if (CHIP_ID(bp) == CHIP_ID_5709_A0) bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG; if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || diff --git a/trunk/drivers/net/mv643xx_eth.c b/trunk/drivers/net/mv643xx_eth.c index 456d1e1c98bd..6a117e9968cb 100644 --- a/trunk/drivers/net/mv643xx_eth.c +++ b/trunk/drivers/net/mv643xx_eth.c @@ -2768,6 +2768,8 @@ static const struct ethtool_ops mv643xx_ethtool_ops = { .get_stats_count = mv643xx_get_stats_count, .get_ethtool_stats = mv643xx_get_ethtool_stats, .get_strings = mv643xx_get_strings, + .get_stats_count = mv643xx_get_stats_count, + .get_ethtool_stats = mv643xx_get_ethtool_stats, .nway_reset = mv643xx_eth_nway_restart, }; diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 556962f9612d..1c42266bf889 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -3094,12 +3094,9 @@ static void myri10ge_remove(struct pci_dev *pdev) } #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 0x0008 -#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9 0x0009 static struct pci_device_id myri10ge_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)}, - {PCI_DEVICE - (PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9)}, {0}, }; diff --git a/trunk/drivers/net/pcmcia/3c589_cs.c b/trunk/drivers/net/pcmcia/3c589_cs.c index 503f2685fb73..c06cae3f0b56 100644 --- a/trunk/drivers/net/pcmcia/3c589_cs.c +++ b/trunk/drivers/net/pcmcia/3c589_cs.c @@ -116,7 +116,7 @@ struct el3_private { spinlock_t lock; }; -static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; +static const char *if_names[] = { "auto", "10base2", "10baseT", "AUI" }; /*====================================================================*/ diff --git a/trunk/drivers/net/phy/phy.c b/trunk/drivers/net/phy/phy.c index cb230f44d6fc..0cc4369cacba 100644 --- a/trunk/drivers/net/phy/phy.c +++ b/trunk/drivers/net/phy/phy.c @@ -409,7 +409,6 @@ int phy_mii_ioctl(struct phy_device *phydev, return 0; } -EXPORT_SYMBOL(phy_mii_ioctl); /** * phy_start_aneg - start auto-negotiation for this PHY device diff --git a/trunk/drivers/net/ppp_mppe.c b/trunk/drivers/net/ppp_mppe.c index c0b6d19d1457..f79cf87a2bff 100644 --- a/trunk/drivers/net/ppp_mppe.c +++ b/trunk/drivers/net/ppp_mppe.c @@ -136,7 +136,7 @@ struct ppp_mppe_state { * Key Derivation, from RFC 3078, RFC 3079. * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. */ -static void get_new_key_from_sha(struct ppp_mppe_state * state) +static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *InterimKey) { struct hash_desc desc; struct scatterlist sg[4]; @@ -153,6 +153,8 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state) desc.flags = 0; crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest); + + memcpy(InterimKey, state->sha1_digest, state->keylen); } /* @@ -161,21 +163,21 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state) */ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) { + unsigned char InterimKey[MPPE_MAX_KEY_LEN]; struct scatterlist sg_in[1], sg_out[1]; struct blkcipher_desc desc = { .tfm = state->arc4 }; - get_new_key_from_sha(state); + get_new_key_from_sha(state, InterimKey); if (!initial_key) { - crypto_blkcipher_setkey(state->arc4, state->sha1_digest, - state->keylen); - setup_sg(sg_in, state->sha1_digest, state->keylen); + crypto_blkcipher_setkey(state->arc4, InterimKey, state->keylen); + setup_sg(sg_in, InterimKey, state->keylen); setup_sg(sg_out, state->session_key, state->keylen); if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, state->keylen) != 0) { printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); } } else { - memcpy(state->session_key, state->sha1_digest, state->keylen); + memcpy(state->session_key, InterimKey, state->keylen); } if (state->keylen == 8) { /* See RFC 3078 */ diff --git a/trunk/drivers/net/pppoe.c b/trunk/drivers/net/pppoe.c index 9b30cd600a64..0d7f570b9a54 100644 --- a/trunk/drivers/net/pppoe.c +++ b/trunk/drivers/net/pppoe.c @@ -879,7 +879,8 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) dev->hard_header(skb, dev, ETH_P_PPP_SES, po->pppoe_pa.remote, NULL, data_len); - dev_queue_xmit(skb); + if (dev_queue_xmit(skb) < 0) + goto abort; return 1; diff --git a/trunk/drivers/net/pppol2tp.c b/trunk/drivers/net/pppol2tp.c index abe91cb595f4..266e8b38fe10 100644 --- a/trunk/drivers/net/pppol2tp.c +++ b/trunk/drivers/net/pppol2tp.c @@ -491,46 +491,44 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) u16 hdrflags; u16 tunnel_id, session_id; int length; - int offset; + struct udphdr *uh; tunnel = pppol2tp_sock_to_tunnel(sock); if (tunnel == NULL) goto error; - /* UDP always verifies the packet length. */ - __skb_pull(skb, sizeof(struct udphdr)); - /* Short packet? */ - if (!pskb_may_pull(skb, 12)) { + if (skb->len < sizeof(struct udphdr)) { PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO, "%s: recv short packet (len=%d)\n", tunnel->name, skb->len); goto error; } /* Point to L2TP header */ - ptr = skb->data; + ptr = skb->data + sizeof(struct udphdr); /* Get L2TP header flags */ hdrflags = ntohs(*(__be16*)ptr); /* Trace packet contents, if enabled */ if (tunnel->debug & PPPOL2TP_MSG_DATA) { - length = min(16u, skb->len); - if (!pskb_may_pull(skb, length)) - goto error; - printk(KERN_DEBUG "%s: recv: ", tunnel->name); - offset = 0; - do { - printk(" %02X", ptr[offset]); - } while (++offset < length); - + for (length = 0; length < 16; length++) + printk(" %02X", ptr[length]); printk("\n"); } /* Get length of L2TP packet */ - length = skb->len; + uh = (struct udphdr *) skb_transport_header(skb); + length = ntohs(uh->len) - sizeof(struct udphdr); + + /* Too short? */ + if (length < 12) { + PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO, + "%s: recv short L2TP packet (len=%d)\n", tunnel->name, length); + goto error; + } /* If type is control packet, it is handled by userspace. */ if (hdrflags & L2TP_HDRFLAG_T) { @@ -608,6 +606,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) "%s: recv data has no seq numbers when required. " "Discarding\n", session->name); session->stats.rx_seq_discards++; + session->stats.rx_errors++; goto discard; } @@ -626,6 +625,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) "%s: recv data has no seq numbers when required. " "Discarding\n", session->name); session->stats.rx_seq_discards++; + session->stats.rx_errors++; goto discard; } @@ -634,14 +634,10 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) } /* If offset bit set, skip it. */ - if (hdrflags & L2TP_HDRFLAG_O) { - offset = ntohs(*(__be16 *)ptr); - skb->transport_header += 2 + offset; - if (!pskb_may_pull(skb, skb_transport_offset(skb) + 2)) - goto discard; - } + if (hdrflags & L2TP_HDRFLAG_O) + ptr += 2 + ntohs(*(__be16 *) ptr); - __skb_pull(skb, skb_transport_offset(skb)); + skb_pull(skb, ptr - skb->data); /* Skip PPP header, if present. In testing, Microsoft L2TP clients * don't send the PPP header (PPP header compression enabled), but @@ -677,6 +673,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) */ if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) { session->stats.rx_seq_discards++; + session->stats.rx_errors++; PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG, "%s: oos pkt %hu len %d discarded, " "waiting for %hu, reorder_q_len=%d\n", @@ -701,7 +698,6 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) return 0; discard: - session->stats.rx_errors++; kfree_skb(skb); sock_put(session->sock); @@ -962,6 +958,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) int data_len = skb->len; struct inet_sock *inet; __wsum csum = 0; + struct sk_buff *skb2 = NULL; struct udphdr *uh; unsigned int len; @@ -992,30 +989,41 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) */ headroom = NET_SKB_PAD + sizeof(struct iphdr) + sizeof(struct udphdr) + hdr_len + sizeof(ppph); - if (skb_cow_head(skb, headroom)) - goto abort; + if (skb_headroom(skb) < headroom) { + skb2 = skb_realloc_headroom(skb, headroom); + if (skb2 == NULL) + goto abort; + } else + skb2 = skb; + + /* Check that the socket has room */ + if (atomic_read(&sk_tun->sk_wmem_alloc) < sk_tun->sk_sndbuf) + skb_set_owner_w(skb2, sk_tun); + else + goto discard; /* Setup PPP header */ - __skb_push(skb, sizeof(ppph)); - skb->data[0] = ppph[0]; - skb->data[1] = ppph[1]; + skb_push(skb2, sizeof(ppph)); + skb2->data[0] = ppph[0]; + skb2->data[1] = ppph[1]; /* Setup L2TP header */ - pppol2tp_build_l2tp_header(session, __skb_push(skb, hdr_len)); + skb_push(skb2, hdr_len); + pppol2tp_build_l2tp_header(session, skb2->data); /* Setup UDP header */ inet = inet_sk(sk_tun); - __skb_push(skb, sizeof(*uh)); - skb_reset_transport_header(skb); - uh = udp_hdr(skb); + skb_push(skb2, sizeof(struct udphdr)); + skb_reset_transport_header(skb2); + uh = (struct udphdr *) skb2->data; uh->source = inet->sport; uh->dest = inet->dport; uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len); uh->check = 0; - /* *BROKEN* Calculate UDP checksum if configured to do so */ + /* Calculate UDP checksum if configured to do so */ if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT) - csum = udp_csum_outgoing(sk_tun, skb); + csum = udp_csum_outgoing(sk_tun, skb2); /* Debug */ if (session->send_seq) @@ -1028,7 +1036,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (session->debug & PPPOL2TP_MSG_DATA) { int i; - unsigned char *datap = skb->data; + unsigned char *datap = skb2->data; printk(KERN_DEBUG "%s: xmit:", session->name); for (i = 0; i < data_len; i++) { @@ -1041,18 +1049,18 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) printk("\n"); } - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | - IPSKB_REROUTED); - nf_reset(skb); + memset(&(IPCB(skb2)->opt), 0, sizeof(IPCB(skb2)->opt)); + IPCB(skb2)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | + IPSKB_REROUTED); + nf_reset(skb2); /* Get routing info from the tunnel socket */ - dst_release(skb->dst); - skb->dst = sk_dst_get(sk_tun); + dst_release(skb2->dst); + skb2->dst = sk_dst_get(sk_tun); /* Queue the packet to IP for output */ - len = skb->len; - rc = ip_queue_xmit(skb, 1); + len = skb2->len; + rc = ip_queue_xmit(skb2, 1); /* Update stats */ if (rc >= 0) { @@ -1065,12 +1073,17 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) session->stats.tx_errors++; } - return 1; - -abort: /* Free the original skb */ kfree_skb(skb); + return 1; + +discard: + /* Free the new skb. Caller will free original skb. */ + if (skb2 != skb) + kfree_skb(skb2); +abort: + return 0; } /***************************************************************************** @@ -1313,14 +1326,12 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id, goto err; } - sk = sock->sk; - /* Quick sanity checks */ - err = -EPROTONOSUPPORT; - if (sk->sk_protocol != IPPROTO_UDP) { + err = -ESOCKTNOSUPPORT; + if (sock->type != SOCK_DGRAM) { PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR, - "tunl %hu: fd %d wrong protocol, got %d, expected %d\n", - tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP); + "tunl %hu: fd %d wrong type, got %d, expected %d\n", + tunnel_id, fd, sock->type, SOCK_DGRAM); goto err; } err = -EAFNOSUPPORT; @@ -1332,6 +1343,7 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id, } err = -ENOTCONN; + sk = sock->sk; /* Check if this socket has already been prepped */ tunnel = (struct pppol2tp_tunnel *)sk->sk_user_data; diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c index c921ec32c232..b85ab4a8f2a3 100644 --- a/trunk/drivers/net/r8169.c +++ b/trunk/drivers/net/r8169.c @@ -1228,10 +1228,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev) return; } - if ((tp->mac_version != RTL_GIGA_MAC_VER_02) && - (tp->mac_version != RTL_GIGA_MAC_VER_03)) - return; - + /* phy config for RTL8169s mac_version C chip */ mdio_write(ioaddr, 31, 0x0001); //w 31 2 0 1 mdio_write(ioaddr, 21, 0x1000); //w 21 15 0 1000 mdio_write(ioaddr, 24, 0x65c7); //w 24 15 0 65c7 @@ -2570,15 +2567,6 @@ static void rtl8169_tx_interrupt(struct net_device *dev, (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { netif_wake_queue(dev); } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(TxPoll, NPQ); } } diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index 0792031a5cf9..5d812de65d90 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -51,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.18" +#define DRV_VERSION "1.17" #define PFX DRV_NAME " " /* @@ -118,15 +118,12 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ @@ -150,7 +147,6 @@ static const char *yukon2_name[] = { "Extreme", /* 0xb5 */ "EC", /* 0xb6 */ "FE", /* 0xb7 */ - "FE+", /* 0xb8 */ }; static void sky2_set_multicast(struct net_device *dev); @@ -221,7 +217,8 @@ static void sky2_power_on(struct sky2_hw *hw) else sky2_write8(hw, B2_Y2_CLK_GATE, 0); - if (hw->flags & SKY2_HW_ADV_POWER_CTL) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U || + hw->chip_id == CHIP_ID_YUKON_EX) { u32 reg; sky2_pci_write32(hw, PCI_DEV_REG3, 0); @@ -314,8 +311,10 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) struct sky2_port *sky2 = netdev_priv(hw->dev[port]); u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; - if (sky2->autoneg == AUTONEG_ENABLE && - !(hw->flags & SKY2_HW_NEWER_PHY)) { + if (sky2->autoneg == AUTONEG_ENABLE + && !(hw->chip_id == CHIP_ID_YUKON_XL + || hw->chip_id == CHIP_ID_YUKON_EC_U + || hw->chip_id == CHIP_ID_YUKON_EX)) { u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | @@ -335,19 +334,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); if (sky2_is_copper(hw)) { - if (!(hw->flags & SKY2_HW_GIGABIT)) { + if (hw->chip_id == CHIP_ID_YUKON_FE) { /* enable automatic crossover */ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; - - if (hw->chip_id == CHIP_ID_YUKON_FE_P && - hw->chip_rev == CHIP_REV_YU_FE2_A0) { - u16 spec; - - /* Enable Class A driver for FE+ A0 */ - spec = gm_phy_read(hw, port, PHY_MARV_FE_SPEC_2); - spec |= PHY_M_FESC_SEL_CL_A; - gm_phy_write(hw, port, PHY_MARV_FE_SPEC_2, spec); - } } else { /* disable energy detect */ ctrl &= ~PHY_M_PC_EN_DET_MSK; @@ -357,7 +346,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* downshift on PHY 88E1112 and 88E1149 is changed */ if (sky2->autoneg == AUTONEG_ENABLE - && (hw->flags & SKY2_HW_NEWER_PHY)) { + && (hw->chip_id == CHIP_ID_YUKON_XL + || hw->chip_id == CHIP_ID_YUKON_EC_U + || hw->chip_id == CHIP_ID_YUKON_EX)) { /* set downshift counter to 3x and enable downshift */ ctrl &= ~PHY_M_PC_DSC_MSK; ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; @@ -373,7 +364,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); /* special setup for PHY 88E1112 Fiber */ - if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) { + if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) { pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ @@ -464,7 +455,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gma_write16(hw, port, GM_GP_CTRL, reg); - if (hw->flags & SKY2_HW_GIGABIT) + if (hw->chip_id != CHIP_ID_YUKON_FE) gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); @@ -488,23 +479,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); break; - case CHIP_ID_YUKON_FE_P: - /* Enable Link Partner Next Page */ - ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); - ctrl |= PHY_M_PC_ENA_LIP_NP; - - /* disable Energy Detect and enable scrambler */ - ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB); - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); - - /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */ - ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) | - PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) | - PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED); - - gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); - break; - case CHIP_ID_YUKON_XL: pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); @@ -574,13 +548,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* set page register to 0 */ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); - } else if (hw->chip_id == CHIP_ID_YUKON_FE_P && - hw->chip_rev == CHIP_REV_YU_FE2_A0) { - /* apply workaround for integrated resistors calibration */ - gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17); - gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60); } else if (hw->chip_id != CHIP_ID_YUKON_EX) { - /* no effect on Yukon-XL */ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { @@ -701,25 +669,25 @@ static void sky2_wol_init(struct sky2_port *sky2) static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) { - struct net_device *dev = hw->dev[port]; - - if (dev->mtu <= ETH_DATA_LEN) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); - - else if (hw->chip_id != CHIP_ID_YUKON_EC_U) + if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) { sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_STFW_ENA | TX_JUMBO_ENA); - else { - /* set Tx GMAC FIFO Almost Empty Threshold */ - sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), - (ECU_JUMBO_WM << 16) | ECU_AE_THR); + TX_STFW_ENA | + (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS); + } else { + if (hw->dev[port]->mtu > ETH_DATA_LEN) { + /* set Tx GMAC FIFO Almost Empty Threshold */ + sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), + (ECU_JUMBO_WM << 16) | ECU_AE_THR); - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_ENA | TX_STFW_DIS); + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_ENA | TX_STFW_DIS); - /* Can't do offload because of lack of store/forward */ - dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM); + /* Can't do offload because of lack of store/forward */ + hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG + | NETIF_F_ALL_CSUM); + } else + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), + TX_JUMBO_DIS | TX_STFW_ENA); } } @@ -805,8 +773,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) /* Configure Rx MAC FIFO */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON; - if (hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_FE_P) + if (hw->chip_id == CHIP_ID_YUKON_EX) rx_reg |= GMF_RX_OVER_ON; sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg); @@ -815,19 +782,13 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ - reg = RX_GMF_FL_THR_DEF + 1; - /* Another magic mystery workaround from sk98lin */ - if (hw->chip_id == CHIP_ID_YUKON_FE_P && - hw->chip_rev == CHIP_REV_YU_FE2_A0) - reg = 0x178; - sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg); + sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1); /* Configure Tx MAC FIFO */ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); - /* On chips without ram buffer, pause is controled by MAC level */ - if (sky2_read8(hw, B2_E_0) == 0) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) { sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); @@ -1006,15 +967,19 @@ static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re) */ static void rx_set_checksum(struct sky2_port *sky2) { - struct sky2_rx_le *le = sky2_next_rx(sky2); + struct sky2_rx_le *le; - le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); - le->ctrl = 0; - le->opcode = OP_TCPSTART | HW_OWNER; + if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) { + le = sky2_next_rx(sky2); + le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN); + le->ctrl = 0; + le->opcode = OP_TCPSTART | HW_OWNER; + + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[sky2->port], Q_CSR), + sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + } - sky2_write32(sky2->hw, - Q_ADDR(rxqaddr[sky2->port], Q_CSR), - sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } /* @@ -1210,8 +1175,7 @@ static int sky2_rx_start(struct sky2_port *sky2) sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); - if (!(hw->flags & SKY2_HW_NEW_LE)) - rx_set_checksum(sky2); + rx_set_checksum(sky2); /* Space needed for frame data + headers rounded up */ size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); @@ -1282,7 +1246,7 @@ static int sky2_up(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u32 imask, ramsize; + u32 ramsize, imask; int cap, err = -ENOMEM; struct net_device *otherdev = hw->dev[sky2->port^1]; @@ -1339,10 +1303,11 @@ static int sky2_up(struct net_device *dev) /* Register is number of 4K blocks on internal RAM buffer. */ ramsize = sky2_read8(hw, B2_E_0) * 4; + printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize); + if (ramsize > 0) { u32 rxspace; - pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); if (ramsize < 16) rxspace = ramsize / 2; else @@ -1471,15 +1436,13 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* Check for TCP Segmentation Offload */ mss = skb_shinfo(skb)->gso_size; if (mss != 0) { - - if (!(hw->flags & SKY2_HW_NEW_LE)) + if (hw->chip_id != CHIP_ID_YUKON_EX) mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb); if (mss != sky2->tx_last_mss) { le = get_tx_le(sky2); le->addr = cpu_to_le32(mss); - - if (hw->flags & SKY2_HW_NEW_LE) + if (hw->chip_id == CHIP_ID_YUKON_EX) le->opcode = OP_MSS | HW_OWNER; else le->opcode = OP_LRGLEN | HW_OWNER; @@ -1505,7 +1468,8 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* Handle TCP checksum offload */ if (skb->ip_summed == CHECKSUM_PARTIAL) { /* On Yukon EX (some versions) encoding change. */ - if (hw->flags & SKY2_HW_AUTO_TX_SUM) + if (hw->chip_id == CHIP_ID_YUKON_EX + && hw->chip_rev != CHIP_REV_YU_EX_B0) ctrl |= CALSUM; /* auto checksum */ else { const unsigned offset = skb_transport_offset(skb); @@ -1658,6 +1622,9 @@ static int sky2_down(struct net_device *dev) if (netif_msg_ifdown(sky2)) printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + if (netif_carrier_ok(dev) && --hw->active == 0) + del_timer(&hw->watchdog_timer); + /* Stop more packets from being queued */ netif_stop_queue(dev); @@ -1741,15 +1708,11 @@ static int sky2_down(struct net_device *dev) static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) { - if (hw->flags & SKY2_HW_FIBRE_PHY) + if (!sky2_is_copper(hw)) return SPEED_1000; - if (!(hw->flags & SKY2_HW_GIGABIT)) { - if (aux & PHY_M_PS_SPEED_100) - return SPEED_100; - else - return SPEED_10; - } + if (hw->chip_id == CHIP_ID_YUKON_FE) + return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10; switch (aux & PHY_M_PS_SPEED_MSK) { case PHY_M_PS_SPEED_1000: @@ -1782,13 +1745,17 @@ static void sky2_link_up(struct sky2_port *sky2) netif_carrier_on(sky2->netdev); - mod_timer(&hw->watchdog_timer, jiffies + 1); + if (hw->active++ == 0) + mod_timer(&hw->watchdog_timer, jiffies + 1); + /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); - if (hw->flags & SKY2_HW_NEWER_PHY) { + if (hw->chip_id == CHIP_ID_YUKON_XL + || hw->chip_id == CHIP_ID_YUKON_EC_U + || hw->chip_id == CHIP_ID_YUKON_EX) { u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ @@ -1833,6 +1800,11 @@ static void sky2_link_down(struct sky2_port *sky2) netif_carrier_off(sky2->netdev); + /* Stop watchdog if both ports are not active */ + if (--hw->active == 0) + del_timer(&hw->watchdog_timer); + + /* Turn on link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); @@ -1875,7 +1847,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) /* Since the pause result bits seem to in different positions on * different chips. look at registers. */ - if (hw->flags & SKY2_HW_FIBRE_PHY) { + if (!sky2_is_copper(hw)) { /* Shift for bits in fiber PHY */ advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM); lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM); @@ -1986,9 +1958,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; - if (new_mtu > ETH_DATA_LEN && - (hw->chip_id == CHIP_ID_YUKON_FE || - hw->chip_id == CHIP_ID_YUKON_FE_P)) + if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE) return -EINVAL; if (!netif_running(dev)) { @@ -2005,7 +1975,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) synchronize_irq(hw->pdev->irq); - if (sky2_read8(hw, B2_E_0) == 0) + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) sky2_set_tx_stfwd(hw, port); ctl = gma_read16(hw, port, GM_GP_CTRL); @@ -2133,13 +2103,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev, struct sky2_port *sky2 = netdev_priv(dev); struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next; struct sk_buff *skb = NULL; - u16 count = (status & GMR_FS_LEN) >> 16; - -#ifdef SKY2_VLAN_TAG_USED - /* Account for vlan tag */ - if (sky2->vlgrp && (status & GMR_FS_VLAN)) - count -= VLAN_HLEN; -#endif if (unlikely(netif_msg_rx_status(sky2))) printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", @@ -2154,8 +2117,7 @@ static struct sk_buff *sky2_receive(struct net_device *dev, if (!(status & GMR_FS_RX_OK)) goto resubmit; - /* if length reported by DMA does not match PHY, packet was truncated */ - if (length != count) + if (status >> 16 != length) goto len_mismatch; if (length < copybreak) @@ -2171,10 +2133,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev, /* Truncation of overlength packets causes PHY length to not match MAC length */ ++sky2->net_stats.rx_length_errors; - if (netif_msg_rx_err(sky2) && net_ratelimit()) - pr_info(PFX "%s: rx length mismatch: length %d status %#x\n", - dev->name, length, status); - goto resubmit; error: ++sky2->net_stats.rx_errors; @@ -2244,7 +2202,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) } /* This chip reports checksum status differently */ - if (hw->flags & SKY2_HW_NEW_LE) { + if (hw->chip_id == CHIP_ID_YUKON_EX) { if (sky2->rx_csum && (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && (le->css & CSS_TCPUDPCSOK)) @@ -2285,14 +2243,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) if (!sky2->rx_csum) break; - /* If this happens then driver assuming wrong format */ - if (unlikely(hw->flags & SKY2_HW_NEW_LE)) { - if (net_ratelimit()) - printk(KERN_NOTICE "%s: unexpected" - " checksum status\n", - dev->name); + if (hw->chip_id == CHIP_ID_YUKON_EX) break; - } /* Both checksum counters are programmed to start at * the same offset, so unless there is a problem they @@ -2484,72 +2436,20 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port, sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); } -static int sky2_rx_hung(struct net_device *dev) -{ - struct sky2_port *sky2 = netdev_priv(dev); - struct sky2_hw *hw = sky2->hw; - unsigned port = sky2->port; - unsigned rxq = rxqaddr[port]; - u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP)); - u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV)); - u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP)); - u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL)); - - /* If idle and MAC or PCI is stuck */ - if (sky2->check.last == dev->last_rx && - ((mac_rp == sky2->check.mac_rp && - mac_lev != 0 && mac_lev >= sky2->check.mac_lev) || - /* Check if the PCI RX hang */ - (fifo_rp == sky2->check.fifo_rp && - fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) { - printk(KERN_DEBUG PFX "%s: hung mac %d:%d fifo %d (%d:%d)\n", - dev->name, mac_lev, mac_rp, fifo_lev, fifo_rp, - sky2_read8(hw, Q_ADDR(rxq, Q_WP))); - return 1; - } else { - sky2->check.last = dev->last_rx; - sky2->check.mac_rp = mac_rp; - sky2->check.mac_lev = mac_lev; - sky2->check.fifo_rp = fifo_rp; - sky2->check.fifo_lev = fifo_lev; - return 0; - } -} - +/* Check for lost IRQ once a second */ static void sky2_watchdog(unsigned long arg) { struct sky2_hw *hw = (struct sky2_hw *) arg; - struct net_device *dev; - /* Check for lost IRQ once a second */ if (sky2_read32(hw, B0_ISRC)) { - dev = hw->dev[0]; + struct net_device *dev = hw->dev[0]; + if (__netif_rx_schedule_prep(dev)) __netif_rx_schedule(dev); - } else { - int i, active = 0; - - for (i = 0; i < hw->ports; i++) { - dev = hw->dev[i]; - if (!netif_running(dev)) - continue; - ++active; - - /* For chips with Rx FIFO, check if stuck */ - if ((hw->flags & SKY2_HW_FIFO_HANG_CHECK) && - sky2_rx_hung(dev)) { - pr_info(PFX "%s: receiver hang detected\n", - dev->name); - schedule_work(&hw->restart_work); - return; - } - } - - if (active == 0) - return; } - mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); + if (hw->active > 0) + mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); } /* Hardware/software error handling */ @@ -2646,25 +2546,17 @@ static void sky2_netpoll(struct net_device *dev) #endif /* Chip internal frequency for clock calculations */ -static u32 sky2_mhz(const struct sky2_hw *hw) +static inline u32 sky2_mhz(const struct sky2_hw *hw) { switch (hw->chip_id) { case CHIP_ID_YUKON_EC: case CHIP_ID_YUKON_EC_U: case CHIP_ID_YUKON_EX: - return 125; - + return 125; /* 125 Mhz */ case CHIP_ID_YUKON_FE: - return 100; - - case CHIP_ID_YUKON_FE_P: - return 50; - - case CHIP_ID_YUKON_XL: - return 156; - - default: - BUG(); + return 100; /* 100 Mhz */ + default: /* YUKON_XL */ + return 156; /* 156 Mhz */ } } @@ -2689,63 +2581,23 @@ static int __devinit sky2_init(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_RST_CLR); hw->chip_id = sky2_read8(hw, B2_CHIP_ID); - hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; - - switch(hw->chip_id) { - case CHIP_ID_YUKON_XL: - hw->flags = SKY2_HW_GIGABIT - | SKY2_HW_NEWER_PHY; - if (hw->chip_rev < 3) - hw->flags |= SKY2_HW_FIFO_HANG_CHECK; - - break; - - case CHIP_ID_YUKON_EC_U: - hw->flags = SKY2_HW_GIGABIT - | SKY2_HW_NEWER_PHY - | SKY2_HW_ADV_POWER_CTL; - break; - - case CHIP_ID_YUKON_EX: - hw->flags = SKY2_HW_GIGABIT - | SKY2_HW_NEWER_PHY - | SKY2_HW_NEW_LE - | SKY2_HW_ADV_POWER_CTL; - - /* New transmit checksum */ - if (hw->chip_rev != CHIP_REV_YU_EX_B0) - hw->flags |= SKY2_HW_AUTO_TX_SUM; - break; - - case CHIP_ID_YUKON_EC: - /* This rev is really old, and requires untested workarounds */ - if (hw->chip_rev == CHIP_REV_YU_EC_A1) { - dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); - return -EOPNOTSUPP; - } - hw->flags = SKY2_HW_GIGABIT | SKY2_HW_FIFO_HANG_CHECK; - break; - - case CHIP_ID_YUKON_FE: - break; - - case CHIP_ID_YUKON_FE_P: - hw->flags = SKY2_HW_NEWER_PHY - | SKY2_HW_NEW_LE - | SKY2_HW_AUTO_TX_SUM - | SKY2_HW_ADV_POWER_CTL; - break; - default: + if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) { dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", hw->chip_id); return -EOPNOTSUPP; } - hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); - if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') - hw->flags |= SKY2_HW_FIBRE_PHY; + hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4; + /* This rev is really old, and requires untested workarounds */ + if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) { + dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n", + yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL], + hw->chip_id, hw->chip_rev); + return -EOPNOTSUPP; + } + hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); hw->ports = 1; t8 = sky2_read8(hw, B2_Y2_HW_RES); if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { @@ -2939,9 +2791,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) sky2->wol = wol->wolopts; - if (hw->chip_id == CHIP_ID_YUKON_EC_U || - hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_FE_P) + if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) sky2_write32(hw, B0_CTST, sky2->wol ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); @@ -2959,7 +2809,7 @@ static u32 sky2_supported_modes(const struct sky2_hw *hw) | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP; - if (hw->flags & SKY2_HW_GIGABIT) + if (hw->chip_id != CHIP_ID_YUKON_FE) modes |= SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; return modes; @@ -2979,6 +2829,13 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->supported = sky2_supported_modes(hw); ecmd->phy_address = PHY_ADDR_MARV; if (sky2_is_copper(hw)) { + ecmd->supported = SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full + | SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full + | SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full + | SUPPORTED_Autoneg | SUPPORTED_TP; ecmd->port = PORT_TP; ecmd->speed = sky2->speed; } else { @@ -3934,13 +3791,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->hw = hw; sky2->msg_enable = netif_msg_init(debug, default_msg); - /* This chip has hardware problems that generates - * bogus PHY receive status so by default shut up the message. - */ - if (hw->chip_id == CHIP_ID_YUKON_FE_P && - hw->chip_rev == CHIP_REV_YU_FE2_A0) - sky2->msg_enable &= ~NETIF_MSG_RX_ERR; - /* Auto speed and flow control */ sky2->autoneg = AUTONEG_ENABLE; sky2->flow_mode = FC_BOTH; @@ -3996,7 +3846,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id) return IRQ_NONE; if (status & Y2_IS_IRQ_SW) { - hw->flags |= SKY2_HW_USE_MSI; + hw->msi = 1; wake_up(&hw->msi_wait); sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); } @@ -4024,9 +3874,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); sky2_read8(hw, B0_CTST); - wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10); + wait_event_timeout(hw->msi_wait, hw->msi, HZ/10); - if (!(hw->flags & SKY2_HW_USE_MSI)) { + if (!hw->msi) { /* MSI test failed, go back to INTx mode */ dev_info(&pdev->dev, "No interrupt generated using MSI, " "switching to INTx mode.\n"); @@ -4159,8 +4009,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_netdev; } - err = request_irq(pdev->irq, sky2_intr, - (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED, + err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED, dev->name, hw); if (err) { dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq); @@ -4193,7 +4042,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, return 0; err_out_unregister: - if (hw->flags & SKY2_HW_USE_MSI) + if (hw->msi) pci_disable_msi(pdev); unregister_netdev(dev); err_out_free_netdev: @@ -4242,7 +4091,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) sky2_read8(hw, B0_CTST); free_irq(pdev->irq, hw); - if (hw->flags & SKY2_HW_USE_MSI) + if (hw->msi) pci_disable_msi(pdev); pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); pci_release_regions(pdev); @@ -4310,9 +4159,7 @@ static int sky2_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D0, 0); /* Re-enable all clocks */ - if (hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_EC_U || - hw->chip_id == CHIP_ID_YUKON_FE_P) + if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) sky2_pci_write32(hw, PCI_DEV_REG3, 0); sky2_reset(hw); diff --git a/trunk/drivers/net/sky2.h b/trunk/drivers/net/sky2.h index 8bc5c54e3efa..72e12b7cfa40 100644 --- a/trunk/drivers/net/sky2.h +++ b/trunk/drivers/net/sky2.h @@ -470,24 +470,18 @@ enum { CHIP_ID_YUKON_EX = 0xb5, /* Chip ID for YUKON-2 Extreme */ CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */ CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */ - CHIP_ID_YUKON_FE_P = 0xb8, /* Chip ID for YUKON-2 FE+ */ -}; -enum yukon_ec_rev { + CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */ CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */ CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */ -}; -enum yukon_ec_u_rev { + CHIP_REV_YU_EC_U_A0 = 1, CHIP_REV_YU_EC_U_A1 = 2, CHIP_REV_YU_EC_U_B0 = 3, -}; -enum yukon_fe_rev { + CHIP_REV_YU_FE_A1 = 1, CHIP_REV_YU_FE_A2 = 2, -}; -enum yukon_fe_p_rev { - CHIP_REV_YU_FE2_A0 = 0, + }; enum yukon_ex_rev { CHIP_REV_YU_EX_A0 = 1, @@ -1674,7 +1668,7 @@ enum { /* Receive Frame Status Encoding */ enum { - GMR_FS_LEN = 0x7fff<<16, /* Bit 30..16: Rx Frame Length */ + GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ GMR_FS_VLAN = 1<<13, /* VLAN Packet */ GMR_FS_JABBER = 1<<12, /* Jabber Packet */ GMR_FS_UN_SIZE = 1<<11, /* Undersize Packet */ @@ -1735,10 +1729,6 @@ enum { GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON, }; -/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */ -enum { - TX_DYN_WM_ENA = 3, /* Yukon-FE+ specific */ -}; /* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ enum { @@ -2027,14 +2017,6 @@ struct sky2_port { u16 rx_tag; struct vlan_group *vlgrp; #endif - struct { - unsigned long last; - u32 mac_rp; - u8 mac_lev; - u8 fifo_rp; - u8 fifo_lev; - } check; - dma_addr_t rx_le_map; dma_addr_t tx_le_map; @@ -2058,20 +2040,12 @@ struct sky2_hw { void __iomem *regs; struct pci_dev *pdev; struct net_device *dev[2]; - unsigned long flags; -#define SKY2_HW_USE_MSI 0x00000001 -#define SKY2_HW_FIBRE_PHY 0x00000002 -#define SKY2_HW_GIGABIT 0x00000004 -#define SKY2_HW_NEWER_PHY 0x00000008 -#define SKY2_HW_FIFO_HANG_CHECK 0x00000010 -#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ -#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ -#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ u8 chip_id; u8 chip_rev; u8 pmd_type; u8 ports; + u8 active; struct sky2_status_le *st_le; u32 st_idx; @@ -2079,12 +2053,13 @@ struct sky2_hw { struct timer_list watchdog_timer; struct work_struct restart_work; + int msi; wait_queue_head_t msi_wait; }; static inline int sky2_is_copper(const struct sky2_hw *hw) { - return !(hw->flags & SKY2_HW_FIBRE_PHY); + return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P'); } /* Register accessor for memory mapped device */ diff --git a/trunk/drivers/power/power_supply_sysfs.c b/trunk/drivers/power/power_supply_sysfs.c index de3155b21285..c7c4574729b1 100644 --- a/trunk/drivers/power/power_supply_sysfs.c +++ b/trunk/drivers/power/power_supply_sysfs.c @@ -289,7 +289,6 @@ int power_supply_uevent(struct device *dev, char **envp, int num_envp, if (ret) goto out; } - envp[i] = NULL; out: free_page((unsigned long)prop_buf); diff --git a/trunk/drivers/scsi/esp_scsi.c b/trunk/drivers/scsi/esp_scsi.c index 95cf7b6cd622..77b06a983fa7 100644 --- a/trunk/drivers/scsi/esp_scsi.c +++ b/trunk/drivers/scsi/esp_scsi.c @@ -2314,7 +2314,6 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev) esp->host->transportt = esp_transport_template; esp->host->max_lun = ESP_MAX_LUN; esp->host->cmd_per_lun = 2; - esp->host->unique_id = instance; esp_set_clock_params(esp); @@ -2338,7 +2337,7 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev) if (err) return err; - instance++; + esp->host->unique_id = instance++; scsi_scan_host(esp->host); diff --git a/trunk/drivers/scsi/scsi_transport_spi.c b/trunk/drivers/scsi/scsi_transport_spi.c index 4df21c92ff1e..6f56f8750635 100644 --- a/trunk/drivers/scsi/scsi_transport_spi.c +++ b/trunk/drivers/scsi/scsi_transport_spi.c @@ -787,12 +787,10 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) struct scsi_target *starget = sdev->sdev_target; struct Scsi_Host *shost = sdev->host; int len = sdev->inquiry_len; - int min_period = spi_min_period(starget); - int max_width = spi_max_width(starget); /* first set us up for narrow async */ DV_SET(offset, 0); DV_SET(width, 0); - + if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS) != SPI_COMPARE_SUCCESS) { starget_printk(KERN_ERR, starget, "Domain Validation Initial Inquiry Failed\n"); @@ -800,13 +798,9 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) return; } - if (!scsi_device_wide(sdev)) { - spi_max_width(starget) = 0; - max_width = 0; - } - /* test width */ - if (i->f->set_width && max_width) { + if (i->f->set_width && spi_max_width(starget) && + scsi_device_wide(sdev)) { i->f->set_width(starget, 1); if (spi_dv_device_compare_inquiry(sdev, buffer, @@ -815,11 +809,6 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) != SPI_COMPARE_SUCCESS) { starget_printk(KERN_ERR, starget, "Wide Transfers Fail\n"); i->f->set_width(starget, 0); - /* Make sure we don't force wide back on by asking - * for a transfer period that requires it */ - max_width = 0; - if (min_period < 10) - min_period = 10; } } @@ -839,8 +828,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) /* now set up to the maximum */ DV_SET(offset, spi_max_offset(starget)); - DV_SET(period, min_period); - + DV_SET(period, spi_min_period(starget)); /* try QAS requests; this should be harmless to set if the * target supports it */ if (scsi_device_qas(sdev)) { @@ -849,14 +837,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) DV_SET(qas, 0); } - if (scsi_device_ius(sdev) && min_period < 9) { + if (scsi_device_ius(sdev) && spi_min_period(starget) < 9) { /* This u320 (or u640). Set IU transfers */ DV_SET(iu, 1); /* Then set the optional parameters */ DV_SET(rd_strm, 1); DV_SET(wr_flow, 1); DV_SET(rti, 1); - if (min_period == 8) + if (spi_min_period(starget) == 8) DV_SET(pcomp_en, 1); } else { DV_SET(iu, 0); @@ -874,10 +862,6 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) } else { DV_SET(dt, 1); } - /* set width last because it will pull all the other - * parameters down to required values */ - DV_SET(width, max_width); - /* Do the read only INQUIRY tests */ spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, spi_dv_device_compare_inquiry); diff --git a/trunk/drivers/serial/sunsab.c b/trunk/drivers/serial/sunsab.c index ff610c23314b..e348ba684050 100644 --- a/trunk/drivers/serial/sunsab.c +++ b/trunk/drivers/serial/sunsab.c @@ -38,7 +38,7 @@ #include #include -#if defined(CONFIG_SERIAL_SUNSAB_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif diff --git a/trunk/drivers/w1/w1.c b/trunk/drivers/w1/w1.c index a593f900eff4..8d7ab74170d5 100644 --- a/trunk/drivers/w1/w1.c +++ b/trunk/drivers/w1/w1.c @@ -431,7 +431,6 @@ static int w1_uevent(struct device *dev, char **envp, int num_envp, err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (unsigned long long)sl->reg_num.id); - envp[cur_index] = NULL; if (err) return err; diff --git a/trunk/fs/compat_ioctl.c b/trunk/fs/compat_ioctl.c index 37310b0e8107..5a5b7116cefb 100644 --- a/trunk/fs/compat_ioctl.c +++ b/trunk/fs/compat_ioctl.c @@ -3190,8 +3190,6 @@ COMPATIBLE_IOCTL(SIOCSIWRETRY) COMPATIBLE_IOCTL(SIOCGIWRETRY) COMPATIBLE_IOCTL(SIOCSIWPOWER) COMPATIBLE_IOCTL(SIOCGIWPOWER) -COMPATIBLE_IOCTL(SIOCSIWAUTH) -COMPATIBLE_IOCTL(SIOCGIWAUTH) /* hiddev */ COMPATIBLE_IOCTL(HIDIOCGVERSION) COMPATIBLE_IOCTL(HIDIOCAPPLICATION) diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 073b0b8c6d05..c21a8cc06277 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -783,6 +784,7 @@ static int de_thread(struct task_struct *tsk) * and we can just re-use it all. */ if (atomic_read(&oldsighand->count) <= 1) { + signalfd_detach(tsk); exit_itimers(sig); return 0; } @@ -921,6 +923,7 @@ static int de_thread(struct task_struct *tsk) sig->flags = 0; no_thread_group: + signalfd_detach(tsk); exit_itimers(sig); if (leader) release_task(leader); diff --git a/trunk/fs/lockd/svclock.c b/trunk/fs/lockd/svclock.c index d098c7af0d22..a21e4bc5444b 100644 --- a/trunk/fs/lockd/svclock.c +++ b/trunk/fs/lockd/svclock.c @@ -171,14 +171,19 @@ nlmsvc_find_block(struct nlm_cookie *cookie) * GRANTED_RES message by cookie, without having to rely on the client's IP * address. --okir */ -static struct nlm_block * -nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host, - struct nlm_file *file, struct nlm_lock *lock, - struct nlm_cookie *cookie) +static inline struct nlm_block * +nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, + struct nlm_lock *lock, struct nlm_cookie *cookie) { struct nlm_block *block; + struct nlm_host *host; struct nlm_rqst *call = NULL; + /* Create host handle for callback */ + host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len); + if (host == NULL) + return NULL; + call = nlm_alloc_call(host); if (call == NULL) return NULL; @@ -361,7 +366,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) { struct nlm_block *block = NULL; - struct nlm_host *host; int error; __be32 ret; @@ -373,10 +377,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, (long long)lock->fl.fl_end, wait); - /* Create host handle for callback */ - host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len); - if (host == NULL) - return nlm_lck_denied_nolocks; /* Lock file against concurrent access */ mutex_lock(&file->f_mutex); @@ -385,8 +385,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, */ block = nlmsvc_lookup_block(file, lock); if (block == NULL) { - block = nlmsvc_create_block(rqstp, nlm_get_host(host), file, - lock, cookie); + block = nlmsvc_create_block(rqstp, file, lock, cookie); ret = nlm_lck_denied_nolocks; if (block == NULL) goto out; @@ -450,7 +449,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, out: mutex_unlock(&file->f_mutex); nlmsvc_release_block(block); - nlm_release_host(host); dprintk("lockd: nlmsvc_lock returned %u\n", ret); return ret; } @@ -479,15 +477,10 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, if (block == NULL) { struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL); - struct nlm_host *host; if (conf == NULL) return nlm_granted; - /* Create host handle for callback */ - host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len); - if (host == NULL) - return nlm_lck_denied_nolocks; - block = nlmsvc_create_block(rqstp, host, file, lock, cookie); + block = nlmsvc_create_block(rqstp, file, lock, cookie); if (block == NULL) { kfree(conf); return nlm_granted; diff --git a/trunk/fs/ocfs2/aops.c b/trunk/fs/ocfs2/aops.c index f37f25c931f5..50cd8a209012 100644 --- a/trunk/fs/ocfs2/aops.c +++ b/trunk/fs/ocfs2/aops.c @@ -930,11 +930,18 @@ static void ocfs2_write_failure(struct inode *inode, loff_t user_pos, unsigned user_len) { int i; - unsigned from = user_pos & (PAGE_CACHE_SIZE - 1), - to = user_pos + user_len; + unsigned from, to; struct page *tmppage; - ocfs2_zero_new_buffers(wc->w_target_page, from, to); + ocfs2_zero_new_buffers(wc->w_target_page, user_pos, user_len); + + if (wc->w_large_pages) { + from = wc->w_target_from; + to = wc->w_target_to; + } else { + from = 0; + to = PAGE_CACHE_SIZE; + } for(i = 0; i < wc->w_num_pages; i++) { tmppage = wc->w_pages[i]; @@ -984,6 +991,9 @@ static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno, map_from = cluster_start; map_to = cluster_end; } + + wc->w_target_from = map_from; + wc->w_target_to = map_to; } else { /* * If we haven't allocated the new page yet, we @@ -1201,33 +1211,18 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping, loff_t pos, unsigned len) { int ret, i; - loff_t cluster_off; - unsigned int local_len = len; struct ocfs2_write_cluster_desc *desc; - struct ocfs2_super *osb = OCFS2_SB(mapping->host->i_sb); for (i = 0; i < wc->w_clen; i++) { desc = &wc->w_desc[i]; - /* - * We have to make sure that the total write passed in - * doesn't extend past a single cluster. - */ - local_len = len; - cluster_off = pos & (osb->s_clustersize - 1); - if ((cluster_off + local_len) > osb->s_clustersize) - local_len = osb->s_clustersize - cluster_off; - ret = ocfs2_write_cluster(mapping, desc->c_phys, desc->c_unwritten, data_ac, meta_ac, - wc, desc->c_cpos, pos, local_len); + wc, desc->c_cpos, pos, len); if (ret) { mlog_errno(ret); goto out; } - - len -= local_len; - pos += local_len; } ret = 0; diff --git a/trunk/fs/ocfs2/file.c b/trunk/fs/ocfs2/file.c index f3bc3658e7a5..7e34e66159c6 100644 --- a/trunk/fs/ocfs2/file.c +++ b/trunk/fs/ocfs2/file.c @@ -491,8 +491,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb, goto leave; } - status = __ocfs2_claim_clusters(osb, handle, data_ac, 1, - clusters_to_add, &bit_off, &num_bits); + status = ocfs2_claim_clusters(osb, handle, data_ac, 1, + &bit_off, &num_bits); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); diff --git a/trunk/fs/ocfs2/localalloc.c b/trunk/fs/ocfs2/localalloc.c index de984d272576..545f7892cdf3 100644 --- a/trunk/fs/ocfs2/localalloc.c +++ b/trunk/fs/ocfs2/localalloc.c @@ -524,12 +524,13 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, handle_t *handle, struct ocfs2_alloc_context *ac, - u32 bits_wanted, + u32 min_bits, u32 *bit_off, u32 *num_bits) { int status, start; struct inode *local_alloc_inode; + u32 bits_wanted; void *bitmap; struct ocfs2_dinode *alloc; struct ocfs2_local_alloc *la; @@ -537,6 +538,7 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, mlog_entry_void(); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL); + bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; local_alloc_inode = ac->ac_inode; alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; la = OCFS2_LOCAL_ALLOC(alloc); diff --git a/trunk/fs/ocfs2/localalloc.h b/trunk/fs/ocfs2/localalloc.h index 3f76631e110c..385a10152f9c 100644 --- a/trunk/fs/ocfs2/localalloc.h +++ b/trunk/fs/ocfs2/localalloc.h @@ -48,7 +48,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, handle_t *handle, struct ocfs2_alloc_context *ac, - u32 bits_wanted, + u32 min_bits, u32 *bit_off, u32 *num_bits); diff --git a/trunk/fs/ocfs2/suballoc.c b/trunk/fs/ocfs2/suballoc.c index 8f09f5235e3a..d9c5c9fcb30f 100644 --- a/trunk/fs/ocfs2/suballoc.c +++ b/trunk/fs/ocfs2/suballoc.c @@ -1486,21 +1486,21 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode, * contig. allocation, set to '1' to indicate we can deal with extents * of any size. */ -int __ocfs2_claim_clusters(struct ocfs2_super *osb, - handle_t *handle, - struct ocfs2_alloc_context *ac, - u32 min_clusters, - u32 max_clusters, - u32 *cluster_start, - u32 *num_clusters) +int ocfs2_claim_clusters(struct ocfs2_super *osb, + handle_t *handle, + struct ocfs2_alloc_context *ac, + u32 min_clusters, + u32 *cluster_start, + u32 *num_clusters) { int status; - unsigned int bits_wanted = max_clusters; + unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; u64 bg_blkno = 0; u16 bg_bit_off; mlog_entry_void(); + BUG_ON(!ac); BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL @@ -1557,19 +1557,6 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, return status; } -int ocfs2_claim_clusters(struct ocfs2_super *osb, - handle_t *handle, - struct ocfs2_alloc_context *ac, - u32 min_clusters, - u32 *cluster_start, - u32 *num_clusters) -{ - unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; - - return __ocfs2_claim_clusters(osb, handle, ac, min_clusters, - bits_wanted, cluster_start, num_clusters); -} - static inline int ocfs2_block_group_clear_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, diff --git a/trunk/fs/ocfs2/suballoc.h b/trunk/fs/ocfs2/suballoc.h index cafe93703095..f212dc01a84b 100644 --- a/trunk/fs/ocfs2/suballoc.h +++ b/trunk/fs/ocfs2/suballoc.h @@ -85,17 +85,6 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, u32 min_clusters, u32 *cluster_start, u32 *num_clusters); -/* - * Use this variant of ocfs2_claim_clusters to specify a maxiumum - * number of clusters smaller than the allocation reserved. - */ -int __ocfs2_claim_clusters(struct ocfs2_super *osb, - handle_t *handle, - struct ocfs2_alloc_context *ac, - u32 min_clusters, - u32 max_clusters, - u32 *cluster_start, - u32 *num_clusters); int ocfs2_free_suballoc_bits(handle_t *handle, struct inode *alloc_inode, diff --git a/trunk/fs/ocfs2/vote.c b/trunk/fs/ocfs2/vote.c index c05358538f2b..66a13ee63d4c 100644 --- a/trunk/fs/ocfs2/vote.c +++ b/trunk/fs/ocfs2/vote.c @@ -66,7 +66,7 @@ struct ocfs2_vote_msg { struct ocfs2_msg_hdr v_hdr; __be32 v_reserved1; -} __attribute__ ((packed)); +}; /* Responses are given these values to maintain backwards * compatibility with older ocfs2 versions */ @@ -78,7 +78,7 @@ struct ocfs2_response_msg { struct ocfs2_msg_hdr r_hdr; __be32 r_response; -} __attribute__ ((packed)); +}; struct ocfs2_vote_work { struct list_head w_list; diff --git a/trunk/fs/signalfd.c b/trunk/fs/signalfd.c index aefb0be07942..a8e293d30034 100644 --- a/trunk/fs/signalfd.c +++ b/trunk/fs/signalfd.c @@ -11,10 +11,8 @@ * Now using anonymous inode source. * Thanks to Oleg Nesterov for useful code review and suggestions. * More comments and suggestions from Arnd Bergmann. - * Sat May 19, 2007: Davi E. M. Arnaut + * Sat May 19, 2007: Davi E. M. Arnaut * Retrieve multiple signals with one read() call - * Sun Jul 15, 2007: Davide Libenzi - * Attach to the sighand only during read() and poll(). */ #include @@ -29,12 +27,102 @@ #include struct signalfd_ctx { + struct list_head lnk; + wait_queue_head_t wqh; sigset_t sigmask; + struct task_struct *tsk; }; +struct signalfd_lockctx { + struct task_struct *tsk; + unsigned long flags; +}; + +/* + * Tries to acquire the sighand lock. We do not increment the sighand + * use count, and we do not even pin the task struct, so we need to + * do it inside an RCU read lock, and we must be prepared for the + * ctx->tsk going to NULL (in signalfd_deliver()), and for the sighand + * being detached. We return 0 if the sighand has been detached, or + * 1 if we were able to pin the sighand lock. + */ +static int signalfd_lock(struct signalfd_ctx *ctx, struct signalfd_lockctx *lk) +{ + struct sighand_struct *sighand = NULL; + + rcu_read_lock(); + lk->tsk = rcu_dereference(ctx->tsk); + if (likely(lk->tsk != NULL)) + sighand = lock_task_sighand(lk->tsk, &lk->flags); + rcu_read_unlock(); + + if (!sighand) + return 0; + + if (!ctx->tsk) { + unlock_task_sighand(lk->tsk, &lk->flags); + return 0; + } + + if (lk->tsk->tgid == current->tgid) + lk->tsk = current; + + return 1; +} + +static void signalfd_unlock(struct signalfd_lockctx *lk) +{ + unlock_task_sighand(lk->tsk, &lk->flags); +} + +/* + * This must be called with the sighand lock held. + */ +void signalfd_deliver(struct task_struct *tsk, int sig) +{ + struct sighand_struct *sighand = tsk->sighand; + struct signalfd_ctx *ctx, *tmp; + + BUG_ON(!sig); + list_for_each_entry_safe(ctx, tmp, &sighand->signalfd_list, lnk) { + /* + * We use a negative signal value as a way to broadcast that the + * sighand has been orphaned, so that we can notify all the + * listeners about this. Remember the ctx->sigmask is inverted, + * so if the user is interested in a signal, that corresponding + * bit will be zero. + */ + if (sig < 0) { + if (ctx->tsk == tsk) { + ctx->tsk = NULL; + list_del_init(&ctx->lnk); + wake_up(&ctx->wqh); + } + } else { + if (!sigismember(&ctx->sigmask, sig)) + wake_up(&ctx->wqh); + } + } +} + +static void signalfd_cleanup(struct signalfd_ctx *ctx) +{ + struct signalfd_lockctx lk; + + /* + * This is tricky. If the sighand is gone, we do not need to remove + * context from the list, the list itself won't be there anymore. + */ + if (signalfd_lock(ctx, &lk)) { + list_del(&ctx->lnk); + signalfd_unlock(&lk); + } + kfree(ctx); +} + static int signalfd_release(struct inode *inode, struct file *file) { - kfree(file->private_data); + signalfd_cleanup(file->private_data); return 0; } @@ -42,15 +130,23 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait) { struct signalfd_ctx *ctx = file->private_data; unsigned int events = 0; + struct signalfd_lockctx lk; - poll_wait(file, ¤t->sighand->signalfd_wqh, wait); + poll_wait(file, &ctx->wqh, wait); - spin_lock_irq(¤t->sighand->siglock); - if (next_signal(¤t->pending, &ctx->sigmask) || - next_signal(¤t->signal->shared_pending, - &ctx->sigmask)) + /* + * Let the caller get a POLLIN in this case, ala socket recv() when + * the peer disconnects. + */ + if (signalfd_lock(ctx, &lk)) { + if ((lk.tsk == current && + next_signal(&lk.tsk->pending, &ctx->sigmask) > 0) || + next_signal(&lk.tsk->signal->shared_pending, + &ctx->sigmask) > 0) + events |= POLLIN; + signalfd_unlock(&lk); + } else events |= POLLIN; - spin_unlock_irq(¤t->sighand->siglock); return events; } @@ -123,46 +219,59 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info, int nonblock) { ssize_t ret; + struct signalfd_lockctx lk; DECLARE_WAITQUEUE(wait, current); - spin_lock_irq(¤t->sighand->siglock); - ret = dequeue_signal(current, &ctx->sigmask, info); + if (!signalfd_lock(ctx, &lk)) + return 0; + + ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); switch (ret) { case 0: if (!nonblock) break; ret = -EAGAIN; default: - spin_unlock_irq(¤t->sighand->siglock); + signalfd_unlock(&lk); return ret; } - add_wait_queue(¤t->sighand->signalfd_wqh, &wait); + add_wait_queue(&ctx->wqh, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); - ret = dequeue_signal(current, &ctx->sigmask, info); + ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); + signalfd_unlock(&lk); if (ret != 0) break; if (signal_pending(current)) { ret = -ERESTARTSYS; break; } - spin_unlock_irq(¤t->sighand->siglock); schedule(); - spin_lock_irq(¤t->sighand->siglock); + ret = signalfd_lock(ctx, &lk); + if (unlikely(!ret)) { + /* + * Let the caller read zero byte, ala socket + * recv() when the peer disconnect. This test + * must be done before doing a dequeue_signal(), + * because if the sighand has been orphaned, + * the dequeue_signal() call is going to crash + * because ->sighand will be long gone. + */ + break; + } } - spin_unlock_irq(¤t->sighand->siglock); - remove_wait_queue(¤t->sighand->signalfd_wqh, &wait); + remove_wait_queue(&ctx->wqh, &wait); __set_current_state(TASK_RUNNING); return ret; } /* - * Returns a multiple of the size of a "struct signalfd_siginfo", or a negative - * error code. The "count" parameter must be at least the size of a - * "struct signalfd_siginfo". + * Returns either the size of a "struct signalfd_siginfo", or zero if the + * sighand we are attached to, has been orphaned. The "count" parameter + * must be at least the size of a "struct signalfd_siginfo". */ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) @@ -178,6 +287,7 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, return -EINVAL; siginfo = (struct signalfd_siginfo __user *) buf; + do { ret = signalfd_dequeue(ctx, &info, nonblock); if (unlikely(ret <= 0)) @@ -190,7 +300,7 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, nonblock = 1; } while (--count); - return total ? total: ret; + return total ? total : ret; } static const struct file_operations signalfd_fops = { @@ -199,13 +309,20 @@ static const struct file_operations signalfd_fops = { .read = signalfd_read, }; +/* + * Create a file descriptor that is associated with our signal + * state. We can pass it around to others if we want to, but + * it will always be _our_ signal state. + */ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask) { int error; sigset_t sigmask; struct signalfd_ctx *ctx; + struct sighand_struct *sighand; struct file *file; struct inode *inode; + struct signalfd_lockctx lk; if (sizemask != sizeof(sigset_t) || copy_from_user(&sigmask, user_mask, sizeof(sigmask))) @@ -218,7 +335,17 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas if (!ctx) return -ENOMEM; + init_waitqueue_head(&ctx->wqh); ctx->sigmask = sigmask; + ctx->tsk = current->group_leader; + + sighand = current->sighand; + /* + * Add this fd to the list of signal listeners. + */ + spin_lock_irq(&sighand->siglock); + list_add_tail(&ctx->lnk, &sighand->signalfd_list); + spin_unlock_irq(&sighand->siglock); /* * When we call this, the initialization must be complete, since @@ -237,18 +364,23 @@ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemas fput(file); return -EINVAL; } - spin_lock_irq(¤t->sighand->siglock); - ctx->sigmask = sigmask; - spin_unlock_irq(¤t->sighand->siglock); - - wake_up(¤t->sighand->signalfd_wqh); + /* + * We need to be prepared of the fact that the sighand this fd + * is attached to, has been detched. In that case signalfd_lock() + * will return 0, and we'll just skip setting the new mask. + */ + if (signalfd_lock(ctx, &lk)) { + ctx->sigmask = sigmask; + signalfd_unlock(&lk); + } + wake_up(&ctx->wqh); fput(file); } return ufd; err_fdalloc: - kfree(ctx); + signalfd_cleanup(ctx); return error; } diff --git a/trunk/fs/ufs/super.c b/trunk/fs/ufs/super.c index 38eb0b7a1f3d..73402c5eeb8a 100644 --- a/trunk/fs/ufs/super.c +++ b/trunk/fs/ufs/super.c @@ -894,7 +894,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) goto again; } - sbi->s_flags = flags;/*after that line some functions use s_flags*/ + ufs_print_super_stuff(sb, usb1, usb2, usb3); /* @@ -1025,6 +1025,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) UFS_MOUNT_UFSTYPE_44BSD) uspi->s_maxsymlinklen = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen); + + sbi->s_flags = flags; inode = iget(sb, UFS_ROOTINO); if (!inode || is_bad_inode(inode)) diff --git a/trunk/fs/xfs/xfs_filestream.c b/trunk/fs/xfs/xfs_filestream.c index 36d8f6aa11af..16f8e175167d 100644 --- a/trunk/fs/xfs/xfs_filestream.c +++ b/trunk/fs/xfs/xfs_filestream.c @@ -350,10 +350,9 @@ _xfs_filestream_update_ag( /* xfs_fstrm_free_func(): callback for freeing cached stream items. */ void xfs_fstrm_free_func( - unsigned long ino, - void *data) + xfs_ino_t ino, + fstrm_item_t *item) { - fstrm_item_t *item = (fstrm_item_t *)data; xfs_inode_t *ip = item->ip; int ref; @@ -439,7 +438,7 @@ xfs_filestream_mount( grp_count = 10; err = xfs_mru_cache_create(&mp->m_filestream, lifetime, grp_count, - xfs_fstrm_free_func); + (xfs_mru_cache_free_func_t)xfs_fstrm_free_func); return err; } diff --git a/trunk/fs/xfs/xfs_log_recover.c b/trunk/fs/xfs/xfs_log_recover.c index 7174991f4bef..dacb19739cc2 100644 --- a/trunk/fs/xfs/xfs_log_recover.c +++ b/trunk/fs/xfs/xfs_log_recover.c @@ -1920,9 +1920,9 @@ xlog_recover_do_reg_buffer( stale_buf = 1; break; } - if (dip->di_core.di_mode) + if (be16_to_cpu(dip->di_core.di_mode)) mode_count++; - if (dip->di_core.di_gen) + if (be16_to_cpu(dip->di_core.di_gen)) gen_count++; } diff --git a/trunk/include/acpi/acpi_drivers.h b/trunk/include/acpi/acpi_drivers.h index f85f77a538aa..202acb9ff4d0 100644 --- a/trunk/include/acpi/acpi_drivers.h +++ b/trunk/include/acpi/acpi_drivers.h @@ -147,6 +147,10 @@ static inline void unregister_hotplug_dock_device(acpi_handle handle) /*-------------------------------------------------------------------------- Suspend/Resume -------------------------------------------------------------------------- */ +#ifdef CONFIG_ACPI_SLEEP extern int acpi_sleep_init(void); +#else +static inline int acpi_sleep_init(void) { return 0; } +#endif #endif /*__ACPI_DRIVERS_H__*/ diff --git a/trunk/include/acpi/processor.h b/trunk/include/acpi/processor.h index 99934a999e66..ec3ffdadb4d2 100644 --- a/trunk/include/acpi/processor.h +++ b/trunk/include/acpi/processor.h @@ -320,8 +320,6 @@ int acpi_processor_power_init(struct acpi_processor *pr, int acpi_processor_cst_has_changed(struct acpi_processor *pr); int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device); -int acpi_processor_suspend(struct acpi_device * device, pm_message_t state); -int acpi_processor_resume(struct acpi_device * device); /* in processor_thermal.c */ int acpi_processor_get_limit_info(struct acpi_processor *pr); diff --git a/trunk/include/asm-mips/irq.h b/trunk/include/asm-mips/irq.h index 2cb52cf8bd4e..97102ebc54b1 100644 --- a/trunk/include/asm-mips/irq.h +++ b/trunk/include/asm-mips/irq.h @@ -24,30 +24,7 @@ static inline int irq_canonicalize(int irq) #define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */ #endif -#ifdef CONFIG_MIPS_MT_SMTC - -struct irqaction; - -extern unsigned long irq_hwmask[]; -extern int setup_irq_smtc(unsigned int irq, struct irqaction * new, - unsigned long hwmask); - -static inline void smtc_im_ack_irq(unsigned int irq) -{ - if (irq_hwmask[irq] & ST0_IM) - set_c0_status(irq_hwmask[irq] & ST0_IM); -} - -#else - -static inline void smtc_im_ack_irq(unsigned int irq) -{ -} - -#endif /* CONFIG_MIPS_MT_SMTC */ - #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP - /* * Clear interrupt mask handling "backstop" if irq_hwmask * entry so indicates. This implies that the ack() or end() @@ -61,7 +38,6 @@ do { \ ~(irq_hwmask[irq] & 0x0000ff00)); \ } while (0) #else - #define __DO_IRQ_SMTC_HOOK(irq) do { } while (0) #endif @@ -84,6 +60,14 @@ do { \ extern void arch_init_irq(void); extern void spurious_interrupt(void); +#ifdef CONFIG_MIPS_MT_SMTC +struct irqaction; + +extern unsigned long irq_hwmask[]; +extern int setup_irq_smtc(unsigned int irq, struct irqaction * new, + unsigned long hwmask); +#endif /* CONFIG_MIPS_MT_SMTC */ + extern int allocate_irqno(void); extern void alloc_legacy_irqno(void); extern void free_irqno(unsigned int irq); diff --git a/trunk/include/asm-x86_64/pgalloc.h b/trunk/include/asm-x86_64/pgalloc.h index 8bb564687860..b467be6d367f 100644 --- a/trunk/include/asm-x86_64/pgalloc.h +++ b/trunk/include/asm-x86_64/pgalloc.h @@ -4,6 +4,10 @@ #include #include #include +#include + +#define QUICK_PGD 0 /* We preserve special mappings over free */ +#define QUICK_PT 1 /* Other page table pages that are zero on free */ #define pmd_populate_kernel(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte))) @@ -20,23 +24,23 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p static inline void pmd_free(pmd_t *pmd) { BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); - free_page((unsigned long)pmd); + quicklist_free(QUICK_PT, NULL, pmd); } static inline pmd_t *pmd_alloc_one (struct mm_struct *mm, unsigned long addr) { - return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + return (pmd_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL); } static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) { - return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + return (pud_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL); } static inline void pud_free (pud_t *pud) { BUG_ON((unsigned long)pud & (PAGE_SIZE-1)); - free_page((unsigned long)pud); + quicklist_free(QUICK_PT, NULL, pud); } static inline void pgd_list_add(pgd_t *pgd) @@ -57,41 +61,57 @@ static inline void pgd_list_del(pgd_t *pgd) spin_unlock(&pgd_lock); } -static inline pgd_t *pgd_alloc(struct mm_struct *mm) +static inline void pgd_ctor(void *x) { unsigned boundary; - pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); - if (!pgd) - return NULL; - pgd_list_add(pgd); + pgd_t *pgd = x; + struct page *page = virt_to_page(pgd); + /* * Copy kernel pointers in from init. - * Could keep a freelist or slab cache of those because the kernel - * part never changes. */ boundary = pgd_index(__PAGE_OFFSET); - memset(pgd, 0, boundary * sizeof(pgd_t)); memcpy(pgd + boundary, - init_level4_pgt + boundary, - (PTRS_PER_PGD - boundary) * sizeof(pgd_t)); + init_level4_pgt + boundary, + (PTRS_PER_PGD - boundary) * sizeof(pgd_t)); + + spin_lock(&pgd_lock); + list_add(&page->lru, &pgd_list); + spin_unlock(&pgd_lock); +} + +static inline void pgd_dtor(void *x) +{ + pgd_t *pgd = x; + struct page *page = virt_to_page(pgd); + + spin_lock(&pgd_lock); + list_del(&page->lru); + spin_unlock(&pgd_lock); +} + +static inline pgd_t *pgd_alloc(struct mm_struct *mm) +{ + pgd_t *pgd = (pgd_t *)quicklist_alloc(QUICK_PGD, + GFP_KERNEL|__GFP_REPEAT, pgd_ctor); return pgd; } static inline void pgd_free(pgd_t *pgd) { BUG_ON((unsigned long)pgd & (PAGE_SIZE-1)); - pgd_list_del(pgd); - free_page((unsigned long)pgd); + quicklist_free(QUICK_PGD, pgd_dtor, pgd); } static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { - return (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + return (pte_t *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL); } static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { - void *p = (void *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + void *p = (void *)quicklist_alloc(QUICK_PT, GFP_KERNEL|__GFP_REPEAT, NULL); + if (!p) return NULL; return virt_to_page(p); @@ -103,17 +123,22 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add static inline void pte_free_kernel(pte_t *pte) { BUG_ON((unsigned long)pte & (PAGE_SIZE-1)); - free_page((unsigned long)pte); + quicklist_free(QUICK_PT, NULL, pte); } static inline void pte_free(struct page *pte) { - __free_page(pte); -} + quicklist_free_page(QUICK_PT, NULL, pte); +} -#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) +#define __pte_free_tlb(tlb,pte) quicklist_free_page(QUICK_PT, NULL,(pte)) -#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) -#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) +#define __pmd_free_tlb(tlb,x) quicklist_free(QUICK_PT, NULL, (x)) +#define __pud_free_tlb(tlb,x) quicklist_free(QUICK_PT, NULL, (x)) +static inline void check_pgt_cache(void) +{ + quicklist_trim(QUICK_PGD, pgd_dtor, 25, 16); + quicklist_trim(QUICK_PT, NULL, 25, 16); +} #endif /* _X86_64_PGALLOC_H */ diff --git a/trunk/include/asm-x86_64/pgtable.h b/trunk/include/asm-x86_64/pgtable.h index 57dd6b3107ea..c9d8764c89d1 100644 --- a/trunk/include/asm-x86_64/pgtable.h +++ b/trunk/include/asm-x86_64/pgtable.h @@ -411,7 +411,6 @@ pte_t *lookup_address(unsigned long addr); #define HAVE_ARCH_UNMAPPED_AREA #define pgtable_cache_init() do { } while (0) -#define check_pgt_cache() do { } while (0) #define PAGE_AGP PAGE_KERNEL_NOCACHE #define HAVE_PAGE_AGP 1 diff --git a/trunk/include/linux/init_task.h b/trunk/include/linux/init_task.h index f8abfa349ef9..cab741c2d603 100644 --- a/trunk/include/linux/init_task.h +++ b/trunk/include/linux/init_task.h @@ -86,7 +86,7 @@ extern struct nsproxy init_nsproxy; .count = ATOMIC_INIT(1), \ .action = { { { .sa_handler = NULL, } }, }, \ .siglock = __SPIN_LOCK_UNLOCKED(sighand.siglock), \ - .signalfd_wqh = __WAIT_QUEUE_HEAD_INITIALIZER(sighand.signalfd_wqh), \ + .signalfd_list = LIST_HEAD_INIT(sighand.signalfd_list), \ } extern struct group_info init_groups; diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index a01ac6dd5f5e..3de79016f2a6 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -438,7 +438,7 @@ struct sighand_struct { atomic_t count; struct k_sigaction action[_NSIG]; spinlock_t siglock; - wait_queue_head_t signalfd_wqh; + struct list_head signalfd_list; }; struct pacct_struct { diff --git a/trunk/include/linux/signalfd.h b/trunk/include/linux/signalfd.h index 4c9ff0910ae0..510429495690 100644 --- a/trunk/include/linux/signalfd.h +++ b/trunk/include/linux/signalfd.h @@ -45,17 +45,49 @@ struct signalfd_siginfo { #ifdef CONFIG_SIGNALFD /* - * Deliver the signal to listening signalfd. + * Deliver the signal to listening signalfd. This must be called + * with the sighand lock held. Same are the following that end up + * calling signalfd_deliver(). + */ +void signalfd_deliver(struct task_struct *tsk, int sig); + +/* + * No need to fall inside signalfd_deliver() if no signal listeners + * are available. */ static inline void signalfd_notify(struct task_struct *tsk, int sig) { - if (unlikely(waitqueue_active(&tsk->sighand->signalfd_wqh))) - wake_up(&tsk->sighand->signalfd_wqh); + if (unlikely(!list_empty(&tsk->sighand->signalfd_list))) + signalfd_deliver(tsk, sig); +} + +/* + * The signal -1 is used to notify the signalfd that the sighand + * is on its way to be detached. + */ +static inline void signalfd_detach_locked(struct task_struct *tsk) +{ + if (unlikely(!list_empty(&tsk->sighand->signalfd_list))) + signalfd_deliver(tsk, -1); +} + +static inline void signalfd_detach(struct task_struct *tsk) +{ + struct sighand_struct *sighand = tsk->sighand; + + if (unlikely(!list_empty(&sighand->signalfd_list))) { + spin_lock_irq(&sighand->siglock); + signalfd_deliver(tsk, -1); + spin_unlock_irq(&sighand->siglock); + } } #else /* CONFIG_SIGNALFD */ -static inline void signalfd_notify(struct task_struct *tsk, int sig) { } +#define signalfd_deliver(t, s) do { } while (0) +#define signalfd_notify(t, s) do { } while (0) +#define signalfd_detach_locked(t) do { } while (0) +#define signalfd_detach(t) do { } while (0) #endif /* CONFIG_SIGNALFD */ diff --git a/trunk/include/net/sctp/sm.h b/trunk/include/net/sctp/sm.h index e8e3a64eb322..991c85bb9e36 100644 --- a/trunk/include/net/sctp/sm.h +++ b/trunk/include/net/sctp/sm.h @@ -114,6 +114,7 @@ sctp_state_fn_t sctp_sf_do_4_C; sctp_state_fn_t sctp_sf_eat_data_6_2; sctp_state_fn_t sctp_sf_eat_data_fast_4_4; sctp_state_fn_t sctp_sf_eat_sack_6_2; +sctp_state_fn_t sctp_sf_tabort_8_4_8; sctp_state_fn_t sctp_sf_operr_notify; sctp_state_fn_t sctp_sf_t1_init_timer_expire; sctp_state_fn_t sctp_sf_t1_cookie_timer_expire; @@ -246,9 +247,6 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *, int, __be16); struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, union sctp_addr *addr); -int sctp_verify_asconf(const struct sctp_association *asoc, - struct sctp_paramhdr *param_hdr, void *chunk_end, - struct sctp_paramhdr **errp); struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, struct sctp_chunk *asconf); int sctp_process_asconf_ack(struct sctp_association *asoc, diff --git a/trunk/include/net/sctp/structs.h b/trunk/include/net/sctp/structs.h index baff49dfcdbd..c2fe2dcc9afc 100644 --- a/trunk/include/net/sctp/structs.h +++ b/trunk/include/net/sctp/structs.h @@ -421,7 +421,6 @@ struct sctp_signed_cookie { * internally. */ union sctp_addr_param { - struct sctp_paramhdr p; struct sctp_ipv4addr_param v4; struct sctp_ipv6addr_param v6; }; @@ -1157,7 +1156,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, __u8 use_as_src, gfp_t gfp); int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *, - void fastcall (*rcu_call)(struct rcu_head *, + void (*rcu_call)(struct rcu_head *, void (*func)(struct rcu_head *))); int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_sock *); diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index 993369ee94d1..06b24b3aa370 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,14 @@ static void __exit_signal(struct task_struct *tsk) sighand = rcu_dereference(tsk->sighand); spin_lock(&sighand->siglock); + /* + * Notify that this sighand has been detached. This must + * be called with the tsk->sighand lock held. Also, this + * access tsk->sighand internally, so it must be called + * before tsk->sighand is reset. + */ + signalfd_detach_locked(tsk); + posix_cpu_timers_exit(tsk); if (atomic_dec_and_test(&sig->count)) posix_cpu_timers_exit_group(tsk); diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 33f12f48684a..7332e236d367 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -1438,7 +1438,7 @@ static void sighand_ctor(void *data, struct kmem_cache *cachep, struct sighand_struct *sighand = data; spin_lock_init(&sighand->siglock); - init_waitqueue_head(&sighand->signalfd_wqh); + INIT_LIST_HEAD(&sighand->signalfd_list); } void __init proc_caches_init(void) diff --git a/trunk/kernel/power/Kconfig b/trunk/kernel/power/Kconfig index 14b0e10dc95c..c8580a1e6873 100644 --- a/trunk/kernel/power/Kconfig +++ b/trunk/kernel/power/Kconfig @@ -110,7 +110,7 @@ config SUSPEND config HIBERNATION_UP_POSSIBLE bool - depends on X86 || PPC64_SWSUSP || PPC32 + depends on X86 || PPC64_SWSUSP || FRV || PPC32 depends on !SMP default y diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index 9fb91a32edda..3169bed0b4d0 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -378,7 +378,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) /* We only dequeue private signals from ourselves, we don't let * signalfd steal them */ - signr = __dequeue_signal(&tsk->pending, mask, info); + if (likely(tsk == current)) + signr = __dequeue_signal(&tsk->pending, mask, info); if (!signr) { signr = __dequeue_signal(&tsk->signal->shared_pending, mask, info); @@ -406,7 +407,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) } } } - recalc_sigpending(); + if (likely(tsk == current)) + recalc_sigpending(); if (signr && unlikely(sig_kernel_stop(signr))) { /* * Set a marker that we have dequeued a stop signal. Our @@ -423,7 +425,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; } - if (signr && + if (signr && likely(tsk == current) && ((info->si_code & __SI_MASK) == __SI_TIMER) && info->si_sys_private){ /* diff --git a/trunk/kernel/time/tick-broadcast.c b/trunk/kernel/time/tick-broadcast.c index 0962e0577660..aab881c86a1a 100644 --- a/trunk/kernel/time/tick-broadcast.c +++ b/trunk/kernel/time/tick-broadcast.c @@ -382,8 +382,23 @@ static int tick_broadcast_set_event(ktime_t expires, int force) int tick_resume_broadcast_oneshot(struct clock_event_device *bc) { + int cpu = smp_processor_id(); + + /* + * If the CPU is marked for broadcast, enforce oneshot + * broadcast mode. The jinxed VAIO does not resume otherwise. + * No idea why it ends up in a lower C State during resume + * without notifying the clock events layer. + */ + if (cpu_isset(cpu, tick_broadcast_mask)) + cpu_set(cpu, tick_broadcast_oneshot_mask); + clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); - return 0; + + if(!cpus_empty(tick_broadcast_oneshot_mask)) + tick_broadcast_set_event(ktime_get(), 1); + + return cpu_isset(cpu, tick_broadcast_oneshot_mask); } /* diff --git a/trunk/lib/Kconfig.debug b/trunk/lib/Kconfig.debug index 495863a500cd..50a94eee4d92 100644 --- a/trunk/lib/Kconfig.debug +++ b/trunk/lib/Kconfig.debug @@ -284,7 +284,7 @@ config LOCKDEP select KALLSYMS_ALL config LOCK_STAT - bool "Lock usage statistics" + bool "Lock usage statisitics" depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT select LOCKDEP select DEBUG_SPINLOCK diff --git a/trunk/net/ieee80211/softmac/ieee80211softmac_assoc.c b/trunk/net/ieee80211/softmac/ieee80211softmac_assoc.c index e475f2e1be13..afb6c6698b27 100644 --- a/trunk/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/trunk/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -273,6 +273,8 @@ ieee80211softmac_assoc_work(struct work_struct *work) ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); if (ieee80211softmac_start_scan(mac)) { dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); + mac->associnfo.associating = 0; + mac->associnfo.associated = 0; } goto out; } else { diff --git a/trunk/net/ieee80211/softmac/ieee80211softmac_wx.c b/trunk/net/ieee80211/softmac/ieee80211softmac_wx.c index 442b9875f3fb..d054e9224b3e 100644 --- a/trunk/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/trunk/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -70,30 +70,44 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, char *extra) { struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + struct ieee80211softmac_network *n; struct ieee80211softmac_auth_queue_item *authptr; int length = 0; check_assoc_again: mutex_lock(&sm->associnfo.mutex); + /* Check if we're already associating to this or another network + * If it's another network, cancel and start over with our new network + * If it's our network, ignore the change, we're already doing it! + */ if((sm->associnfo.associating || sm->associnfo.associated) && (data->essid.flags && data->essid.length)) { - dprintk(KERN_INFO PFX "Canceling existing associate request!\n"); - /* Cancel assoc work */ - cancel_delayed_work(&sm->associnfo.work); - /* We don't have to do this, but it's a little cleaner */ - list_for_each_entry(authptr, &sm->auth_queue, list) - cancel_delayed_work(&authptr->work); - sm->associnfo.bssvalid = 0; - sm->associnfo.bssfixed = 0; - sm->associnfo.associating = 0; - sm->associnfo.associated = 0; - /* We must unlock to avoid deadlocks with the assoc workqueue - * on the associnfo.mutex */ - mutex_unlock(&sm->associnfo.mutex); - flush_scheduled_work(); - /* Avoid race! Check assoc status again. Maybe someone started an - * association while we flushed. */ - goto check_assoc_again; + /* Get the associating network */ + n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid); + if(n && n->essid.len == data->essid.length && + !memcmp(n->essid.data, extra, n->essid.len)) { + dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n", + MAC_ARG(sm->associnfo.bssid)); + goto out; + } else { + dprintk(KERN_INFO PFX "Canceling existing associate request!\n"); + /* Cancel assoc work */ + cancel_delayed_work(&sm->associnfo.work); + /* We don't have to do this, but it's a little cleaner */ + list_for_each_entry(authptr, &sm->auth_queue, list) + cancel_delayed_work(&authptr->work); + sm->associnfo.bssvalid = 0; + sm->associnfo.bssfixed = 0; + sm->associnfo.associating = 0; + sm->associnfo.associated = 0; + /* We must unlock to avoid deadlocks with the assoc workqueue + * on the associnfo.mutex */ + mutex_unlock(&sm->associnfo.mutex); + flush_scheduled_work(); + /* Avoid race! Check assoc status again. Maybe someone started an + * association while we flushed. */ + goto check_assoc_again; + } } sm->associnfo.static_essid = 0; @@ -139,13 +153,13 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev, data->essid.length = sm->associnfo.req_essid.len; data->essid.flags = 1; /* active */ memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len); - dprintk(KERN_INFO PFX "Getting essid from req_essid\n"); - } else if (sm->associnfo.associated || sm->associnfo.associating) { + } + /* If we're associating/associated, return that */ + if (sm->associnfo.associated || sm->associnfo.associating) { data->essid.length = sm->associnfo.associate_essid.len; data->essid.flags = 1; /* active */ memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len); - dprintk(KERN_INFO PFX "Getting essid from associate_essid\n"); } mutex_unlock(&sm->associnfo.mutex); diff --git a/trunk/net/mac80211/ieee80211.c b/trunk/net/mac80211/ieee80211.c index ff2172ffd861..7286c389a4d0 100644 --- a/trunk/net/mac80211/ieee80211.c +++ b/trunk/net/mac80211/ieee80211.c @@ -5259,7 +5259,7 @@ static void __exit ieee80211_exit(void) } -subsys_initcall(ieee80211_init); +module_init(ieee80211_init); module_exit(ieee80211_exit); MODULE_DESCRIPTION("IEEE 802.11 subsystem"); diff --git a/trunk/net/mac80211/rc80211_simple.c b/trunk/net/mac80211/rc80211_simple.c index 17b9f46bbf2b..f6780d63b342 100644 --- a/trunk/net/mac80211/rc80211_simple.c +++ b/trunk/net/mac80211/rc80211_simple.c @@ -431,7 +431,7 @@ static void __exit rate_control_simple_exit(void) } -subsys_initcall(rate_control_simple_init); +module_init(rate_control_simple_init); module_exit(rate_control_simple_exit); MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211"); diff --git a/trunk/net/mac80211/wme.c b/trunk/net/mac80211/wme.c index 7ab82b376e1b..89ce81529694 100644 --- a/trunk/net/mac80211/wme.c +++ b/trunk/net/mac80211/wme.c @@ -424,7 +424,7 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct rtattr *opt) skb_queue_head_init(&q->requeued[i]); q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops, qd->handle); - if (!q->queues[i]) { + if (q->queues[i] == 0) { q->queues[i] = &noop_qdisc; printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i); } diff --git a/trunk/net/netfilter/nfnetlink_log.c b/trunk/net/netfilter/nfnetlink_log.c index 2351533a8507..e185a5b55913 100644 --- a/trunk/net/netfilter/nfnetlink_log.c +++ b/trunk/net/netfilter/nfnetlink_log.c @@ -58,6 +58,7 @@ struct nfulnl_instance { unsigned int qlen; /* number of nlmsgs in skb */ struct sk_buff *skb; /* pre-allocatd skb */ + struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ struct timer_list timer; int peer_pid; /* PID of the peer process */ @@ -344,12 +345,10 @@ static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, static int __nfulnl_send(struct nfulnl_instance *inst) { - int status = -1; + int status; if (inst->qlen > 1) - NLMSG_PUT(inst->skb, 0, 0, - NLMSG_DONE, - sizeof(struct nfgenmsg)); + inst->lastnlh->nlmsg_type = NLMSG_DONE; status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT); if (status < 0) { @@ -359,8 +358,8 @@ __nfulnl_send(struct nfulnl_instance *inst) inst->qlen = 0; inst->skb = NULL; + inst->lastnlh = NULL; -nlmsg_failure: return status; } @@ -539,6 +538,7 @@ __build_packet_message(struct nfulnl_instance *inst, } nlh->nlmsg_len = inst->skb->tail - old_tail; + inst->lastnlh = nlh; return 0; nlmsg_failure: @@ -644,8 +644,7 @@ nfulnl_log_packet(unsigned int pf, } if (inst->qlen >= qthreshold || - (inst->skb && size > - skb_tailroom(inst->skb) - sizeof(struct nfgenmsg))) { + (inst->skb && size > skb_tailroom(inst->skb))) { /* either the queue len is too high or we don't have * enough room in the skb left. flush to userspace. */ UDEBUG("flushing old skb\n"); diff --git a/trunk/net/sched/sch_sfq.c b/trunk/net/sched/sch_sfq.c index 3a23e30bc79e..957957309859 100644 --- a/trunk/net/sched/sch_sfq.c +++ b/trunk/net/sched/sch_sfq.c @@ -270,7 +270,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->tail = x; } } - if (++sch->q.qlen <= q->limit) { + if (++sch->q.qlen < q->limit-1) { sch->bstats.bytes += skb->len; sch->bstats.packets++; return 0; @@ -306,7 +306,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) q->tail = x; } } - if (++sch->q.qlen <= q->limit) { + if (++sch->q.qlen < q->limit - 1) { sch->qstats.requeues++; return 0; } @@ -391,10 +391,10 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) q->quantum = ctl->quantum ? : psched_mtu(sch->dev); q->perturb_period = ctl->perturb_period*HZ; if (ctl->limit) - q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 2); + q->limit = min_t(u32, ctl->limit, SFQ_DEPTH); qlen = sch->q.qlen; - while (sch->q.qlen > q->limit) + while (sch->q.qlen >= q->limit-1) sfq_drop(sch); qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen); @@ -423,7 +423,7 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt) q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH; q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH; } - q->limit = SFQ_DEPTH - 2; + q->limit = SFQ_DEPTH; q->max_depth = 0; q->tail = SFQ_DEPTH; if (opt == NULL) { diff --git a/trunk/net/sctp/bind_addr.c b/trunk/net/sctp/bind_addr.c index dfffa94fb9f6..d35cbf5aae33 100644 --- a/trunk/net/sctp/bind_addr.c +++ b/trunk/net/sctp/bind_addr.c @@ -181,7 +181,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, * structure. */ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr, - void fastcall (*rcu_call)(struct rcu_head *head, + void (*rcu_call)(struct rcu_head *head, void (*func)(struct rcu_head *head))) { struct sctp_sockaddr_entry *addr, *temp; diff --git a/trunk/net/sctp/input.c b/trunk/net/sctp/input.c index f9a0c9276e3b..47e56017f4ce 100644 --- a/trunk/net/sctp/input.c +++ b/trunk/net/sctp/input.c @@ -622,14 +622,6 @@ static int sctp_rcv_ootb(struct sk_buff *skb) if (SCTP_CID_SHUTDOWN_COMPLETE == ch->type) goto discard; - /* RFC 4460, 2.11.2 - * This will discard packets with INIT chunk bundled as - * subsequent chunks in the packet. When INIT is first, - * the normal INIT processing will discard the chunk. - */ - if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data) - goto discard; - /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR * or a COOKIE ACK the SCTP Packet should be silently * discarded. diff --git a/trunk/net/sctp/inqueue.c b/trunk/net/sctp/inqueue.c index e4ea7fdf36ed..88aa22407549 100644 --- a/trunk/net/sctp/inqueue.c +++ b/trunk/net/sctp/inqueue.c @@ -130,14 +130,6 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) /* Force chunk->skb->data to chunk->chunk_end. */ skb_pull(chunk->skb, chunk->chunk_end - chunk->skb->data); - - /* Verify that we have at least chunk headers - * worth of buffer left. - */ - if (skb_headlen(chunk->skb) < sizeof(sctp_chunkhdr_t)) { - sctp_chunk_free(chunk); - chunk = queue->in_progress = NULL; - } } } diff --git a/trunk/net/sctp/sm_make_chunk.c b/trunk/net/sctp/sm_make_chunk.c index 23ae37ec8711..2e34220d94cd 100644 --- a/trunk/net/sctp/sm_make_chunk.c +++ b/trunk/net/sctp/sm_make_chunk.c @@ -2499,52 +2499,6 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, return SCTP_ERROR_NO_ERROR; } -/* Verify the ASCONF packet before we process it. */ -int sctp_verify_asconf(const struct sctp_association *asoc, - struct sctp_paramhdr *param_hdr, void *chunk_end, - struct sctp_paramhdr **errp) { - sctp_addip_param_t *asconf_param; - union sctp_params param; - int length, plen; - - param.v = (sctp_paramhdr_t *) param_hdr; - while (param.v <= chunk_end - sizeof(sctp_paramhdr_t)) { - length = ntohs(param.p->length); - *errp = param.p; - - if (param.v > chunk_end - length || - length < sizeof(sctp_paramhdr_t)) - return 0; - - switch (param.p->type) { - case SCTP_PARAM_ADD_IP: - case SCTP_PARAM_DEL_IP: - case SCTP_PARAM_SET_PRIMARY: - asconf_param = (sctp_addip_param_t *)param.v; - plen = ntohs(asconf_param->param_hdr.length); - if (plen < sizeof(sctp_addip_param_t) + - sizeof(sctp_paramhdr_t)) - return 0; - break; - case SCTP_PARAM_SUCCESS_REPORT: - case SCTP_PARAM_ADAPTATION_LAYER_IND: - if (length != sizeof(sctp_addip_param_t)) - return 0; - - break; - default: - break; - } - - param.v += WORD_ROUND(length); - } - - if (param.v != chunk_end) - return 0; - - return 1; -} - /* Process an incoming ASCONF chunk with the next expected serial no. and * return an ASCONF_ACK chunk to be sent in response. */ diff --git a/trunk/net/sctp/sm_statefuns.c b/trunk/net/sctp/sm_statefuns.c index a583d67cab63..177528ed3e1b 100644 --- a/trunk/net/sctp/sm_statefuns.c +++ b/trunk/net/sctp/sm_statefuns.c @@ -90,11 +90,6 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, const sctp_subtype_t type, void *arg, sctp_cmd_seq_t *commands); -static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands); static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, @@ -103,7 +98,6 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, struct sctp_transport *transport); static sctp_disposition_t sctp_sf_abort_violation( - const struct sctp_endpoint *ep, const struct sctp_association *asoc, void *arg, sctp_cmd_seq_t *commands, @@ -117,13 +111,6 @@ static sctp_disposition_t sctp_sf_violation_chunklen( void *arg, sctp_cmd_seq_t *commands); -static sctp_disposition_t sctp_sf_violation_paramlen( - const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands); - static sctp_disposition_t sctp_sf_violation_ctsn( const struct sctp_endpoint *ep, const struct sctp_association *asoc, @@ -131,13 +118,6 @@ static sctp_disposition_t sctp_sf_violation_ctsn( void *arg, sctp_cmd_seq_t *commands); -static sctp_disposition_t sctp_sf_violation_chunk( - const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands); - /* Small helper function that checks if the chunk length * is of the appropriate length. The 'required_length' argument * is set to be the size of a specific chunk we are testing. @@ -201,21 +181,16 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, struct sctp_chunk *chunk = arg; struct sctp_ulpevent *ev; - if (!sctp_vtag_verify_either(chunk, asoc)) - return sctp_sf_pdiscard(ep, asoc, type, arg, commands); - /* RFC 2960 6.10 Bundling * * An endpoint MUST NOT bundle INIT, INIT ACK or * SHUTDOWN COMPLETE with any other chunks. */ if (!chunk->singleton) - return sctp_sf_violation_chunk(ep, asoc, type, arg, commands); + return SCTP_DISPOSITION_VIOLATION; - /* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */ - if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) - return sctp_sf_violation_chunklen(ep, asoc, type, arg, - commands); + if (!sctp_vtag_verify_either(chunk, asoc)) + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); /* RFC 2960 10.2 SCTP-to-ULP * @@ -475,17 +450,17 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); + /* Make sure that the INIT-ACK chunk has a valid length */ + if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t))) + return sctp_sf_violation_chunklen(ep, asoc, type, arg, + commands); /* 6.10 Bundling * An endpoint MUST NOT bundle INIT, INIT ACK or * SHUTDOWN COMPLETE with any other chunks. */ if (!chunk->singleton) - return sctp_sf_violation_chunk(ep, asoc, type, arg, commands); + return SCTP_DISPOSITION_VIOLATION; - /* Make sure that the INIT-ACK chunk has a valid length */ - if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t))) - return sctp_sf_violation_chunklen(ep, asoc, type, arg, - commands); /* Grab the INIT header. */ chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data; @@ -610,7 +585,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, * control endpoint, respond with an ABORT. */ if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) - return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); + return sctp_sf_ootb(ep, asoc, type, arg, commands); /* Make sure that the COOKIE_ECHO chunk has a valid length. * In this case, we check that we have enough for at least a @@ -2521,11 +2496,6 @@ sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep, struct sctp_chunk *chunk = (struct sctp_chunk *) arg; struct sctp_chunk *reply; - /* Make sure that the chunk has a valid length */ - if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) - return sctp_sf_violation_chunklen(ep, asoc, type, arg, - commands); - /* Since we are not going to really process this INIT, there * is no point in verifying chunk boundries. Just generate * the SHUTDOWN ACK. @@ -2959,7 +2929,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, * * The return value is the disposition of the chunk. */ -static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, +sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, const struct sctp_association *asoc, const sctp_subtype_t type, void *arg, @@ -2995,7 +2965,6 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); - sctp_sf_pdiscard(ep, asoc, type, arg, commands); return SCTP_DISPOSITION_CONSUME; } @@ -3156,14 +3125,14 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, ch = (sctp_chunkhdr_t *) chunk->chunk_hdr; do { - /* Report violation if the chunk is less then minimal */ + /* Break out if chunk length is less then minimal. */ if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t)) - return sctp_sf_violation_chunklen(ep, asoc, type, arg, - commands); + break; + + ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); + if (ch_end > skb_tail_pointer(skb)) + break; - /* Now that we know we at least have a chunk header, - * do things that are type appropriate. - */ if (SCTP_CID_SHUTDOWN_ACK == ch->type) ootb_shut_ack = 1; @@ -3175,19 +3144,15 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, if (SCTP_CID_ABORT == ch->type) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); - /* Report violation if chunk len overflows */ - ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); - if (ch_end > skb_tail_pointer(skb)) - return sctp_sf_violation_chunklen(ep, asoc, type, arg, - commands); - ch = (sctp_chunkhdr_t *) ch_end; } while (ch_end < skb_tail_pointer(skb)); if (ootb_shut_ack) - return sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); + sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); else - return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); + sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); + + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); } /* @@ -3253,11 +3218,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); - /* We need to discard the rest of the packet to prevent - * potential bomming attacks from additional bundled chunks. - * This is documented in SCTP Threats ID. - */ - return sctp_sf_pdiscard(ep, asoc, type, arg, commands); + return SCTP_DISPOSITION_CONSUME; } return SCTP_DISPOSITION_NOMEM; @@ -3280,13 +3241,6 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep, void *arg, sctp_cmd_seq_t *commands) { - struct sctp_chunk *chunk = arg; - - /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ - if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) - return sctp_sf_violation_chunklen(ep, asoc, type, arg, - commands); - /* Although we do have an association in this case, it corresponds * to a restarted association. So the packet is treated as an OOTB * packet and the state function that handles OOTB SHUTDOWN_ACK is @@ -3303,11 +3257,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, { struct sctp_chunk *chunk = arg; struct sctp_chunk *asconf_ack = NULL; - struct sctp_paramhdr *err_param = NULL; sctp_addiphdr_t *hdr; - union sctp_addr_param *addr_param; __u32 serial; - int length; if (!sctp_vtag_verify(chunk, asoc)) { sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, @@ -3323,20 +3274,6 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, hdr = (sctp_addiphdr_t *)chunk->skb->data; serial = ntohl(hdr->serial); - addr_param = (union sctp_addr_param *)hdr->params; - length = ntohs(addr_param->p.length); - if (length < sizeof(sctp_paramhdr_t)) - return sctp_sf_violation_paramlen(ep, asoc, type, - (void *)addr_param, commands); - - /* Verify the ASCONF chunk before processing it. */ - if (!sctp_verify_asconf(asoc, - (sctp_paramhdr_t *)((void *)addr_param + length), - (void *)chunk->chunk_end, - &err_param)) - return sctp_sf_violation_paramlen(ep, asoc, type, - (void *)&err_param, commands); - /* ADDIP 4.2 C1) Compare the value of the serial number to the value * the endpoint stored in a new association variable * 'Peer-Serial-Number'. @@ -3391,7 +3328,6 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, struct sctp_chunk *asconf_ack = arg; struct sctp_chunk *last_asconf = asoc->addip_last_asconf; struct sctp_chunk *abort; - struct sctp_paramhdr *err_param = NULL; sctp_addiphdr_t *addip_hdr; __u32 sent_serial, rcvd_serial; @@ -3409,14 +3345,6 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data; rcvd_serial = ntohl(addip_hdr->serial); - /* Verify the ASCONF-ACK chunk before processing it. */ - if (!sctp_verify_asconf(asoc, - (sctp_paramhdr_t *)addip_hdr->params, - (void *)asconf_ack->chunk_end, - &err_param)) - return sctp_sf_violation_paramlen(ep, asoc, type, - (void *)&err_param, commands); - if (last_asconf) { addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; sent_serial = ntohl(addip_hdr->serial); @@ -3727,16 +3655,6 @@ sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep, void *arg, sctp_cmd_seq_t *commands) { - struct sctp_chunk *chunk = arg; - - /* Make sure that the chunk has a valid length. - * Since we don't know the chunk type, we use a general - * chunkhdr structure to make a comparison. - */ - if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) - return sctp_sf_violation_chunklen(ep, asoc, type, arg, - commands); - SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk); return SCTP_DISPOSITION_DISCARD; } @@ -3792,13 +3710,6 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep, void *arg, sctp_cmd_seq_t *commands) { - struct sctp_chunk *chunk = arg; - - /* Make sure that the chunk has a valid length. */ - if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) - return sctp_sf_violation_chunklen(ep, asoc, type, arg, - commands); - return SCTP_DISPOSITION_VIOLATION; } @@ -3806,14 +3717,12 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep, * Common function to handle a protocol violation. */ static sctp_disposition_t sctp_sf_abort_violation( - const struct sctp_endpoint *ep, const struct sctp_association *asoc, void *arg, sctp_cmd_seq_t *commands, const __u8 *payload, const size_t paylen) { - struct sctp_packet *packet = NULL; struct sctp_chunk *chunk = arg; struct sctp_chunk *abort = NULL; @@ -3822,51 +3731,30 @@ static sctp_disposition_t sctp_sf_abort_violation( if (!abort) goto nomem; - if (asoc) { - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); + SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); - if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { - sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, - SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); - sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, - SCTP_ERROR(ECONNREFUSED)); - sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); - } else { - sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, - SCTP_ERROR(ECONNABORTED)); - sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, - SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); - SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); - } + if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, + SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNREFUSED)); + sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, + SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); } else { - packet = sctp_ootb_pkt_new(asoc, chunk); - - if (!packet) - goto nomem_pkt; - - if (sctp_test_T_bit(abort)) - packet->vtag = ntohl(chunk->sctp_hdr->vtag); - - abort->skb->sk = ep->base.sk; - - sctp_packet_append_chunk(packet, abort); - - sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, - SCTP_PACKET(packet)); - - SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNABORTED)); + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, + SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); + SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); } - sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); + sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); return SCTP_DISPOSITION_ABORT; -nomem_pkt: - sctp_chunk_free(abort); nomem: return SCTP_DISPOSITION_NOMEM; } @@ -3899,24 +3787,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen( { char err_str[]="The following chunk had invalid length:"; - return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, - sizeof(err_str)); -} - -/* - * Handle a protocol violation when the parameter length is invalid. - * "Invalid" length is identified as smaller then the minimal length a - * given parameter can be. - */ -static sctp_disposition_t sctp_sf_violation_paramlen( - const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands) { - char err_str[] = "The following parameter had invalid length:"; - - return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, + return sctp_sf_abort_violation(asoc, arg, commands, err_str, sizeof(err_str)); } @@ -3935,31 +3806,10 @@ static sctp_disposition_t sctp_sf_violation_ctsn( { char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:"; - return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, + return sctp_sf_abort_violation(asoc, arg, commands, err_str, sizeof(err_str)); } -/* Handle protocol violation of an invalid chunk bundling. For example, - * when we have an association and we recieve bundled INIT-ACK, or - * SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle" - * statement from the specs. Additinally, there might be an attacker - * on the path and we may not want to continue this communication. - */ -static sctp_disposition_t sctp_sf_violation_chunk( - const struct sctp_endpoint *ep, - const struct sctp_association *asoc, - const sctp_subtype_t type, - void *arg, - sctp_cmd_seq_t *commands) -{ - char err_str[]="The following chunk violates protocol:"; - - if (!asoc) - return sctp_sf_violation(ep, asoc, type, arg, commands); - - return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, - sizeof(err_str)); -} /*************************************************************************** * These are the state functions for handling primitive (Section 10) events. ***************************************************************************/ @@ -5326,22 +5176,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc * association exists, otherwise, use the peer's vtag. */ if (asoc) { - /* Special case the INIT-ACK as there is no peer's vtag - * yet. - */ - switch(chunk->chunk_hdr->type) { - case SCTP_CID_INIT_ACK: - { - sctp_initack_chunk_t *initack; - - initack = (sctp_initack_chunk_t *)chunk->chunk_hdr; - vtag = ntohl(initack->init_hdr.init_tag); - break; - } - default: - vtag = asoc->peer.i.init_tag; - break; - } + vtag = asoc->peer.i.init_tag; } else { /* Special case the INIT and stale COOKIE_ECHO as there is no * vtag yet. diff --git a/trunk/net/sctp/sm_statetable.c b/trunk/net/sctp/sm_statetable.c index ddb0ba3974b0..70a91ece3c49 100644 --- a/trunk/net/sctp/sm_statetable.c +++ b/trunk/net/sctp/sm_statetable.c @@ -110,7 +110,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_EMPTY */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ @@ -173,7 +173,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_EMPTY */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ @@ -194,7 +194,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_EMPTY */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ @@ -216,7 +216,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_EMPTY */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ TYPE_SCTP_FUNC(sctp_sf_violation), \ /* SCTP_STATE_COOKIE_ECHOED */ \ @@ -258,7 +258,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_EMPTY */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ @@ -300,7 +300,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_EMPTY */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ @@ -499,7 +499,7 @@ static const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_ /* SCTP_STATE_EMPTY */ \ TYPE_SCTP_FUNC(sctp_sf_ootb), \ /* SCTP_STATE_CLOSED */ \ - TYPE_SCTP_FUNC(sctp_sf_ootb), \ + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \ /* SCTP_STATE_COOKIE_WAIT */ \ TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ /* SCTP_STATE_COOKIE_ECHOED */ \ @@ -528,7 +528,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { /* SCTP_STATE_EMPTY */ TYPE_SCTP_FUNC(sctp_sf_ootb), /* SCTP_STATE_CLOSED */ - TYPE_SCTP_FUNC(sctp_sf_ootb), + TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), /* SCTP_STATE_COOKIE_WAIT */ TYPE_SCTP_FUNC(sctp_sf_unk_chunk), /* SCTP_STATE_COOKIE_ECHOED */ diff --git a/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index 036ab520df21..1a899924023f 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -1110,8 +1110,7 @@ svc_tcp_accept(struct svc_sock *svsk) serv->sv_name); printk(KERN_NOTICE "%s: last TCP connect from %s\n", - serv->sv_name, __svc_print_addr(sin, - buf, sizeof(buf))); + serv->sv_name, buf); } /* * Always select the oldest socket. It's not fair, diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c index 9771451eae21..7eabd55417a5 100644 --- a/trunk/net/wireless/core.c +++ b/trunk/net/wireless/core.c @@ -213,7 +213,7 @@ static int cfg80211_init(void) out_fail_sysfs: return err; } -subsys_initcall(cfg80211_init); +module_init(cfg80211_init); static void cfg80211_exit(void) { diff --git a/trunk/net/wireless/sysfs.c b/trunk/net/wireless/sysfs.c index 2d5d2255a27c..88aaacd9f822 100644 --- a/trunk/net/wireless/sysfs.c +++ b/trunk/net/wireless/sysfs.c @@ -52,14 +52,12 @@ static void wiphy_dev_release(struct device *dev) cfg80211_dev_free(rdev); } -#ifdef CONFIG_HOTPLUG static int wiphy_uevent(struct device *dev, char **envp, int num_envp, char *buf, int size) { /* TODO, we probably need stuff here */ return 0; } -#endif struct class ieee80211_class = { .name = "ieee80211", diff --git a/trunk/sound/core/memalloc.c b/trunk/sound/core/memalloc.c index 9b5656d8bcca..f057430db0d0 100644 --- a/trunk/sound/core/memalloc.c +++ b/trunk/sound/core/memalloc.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -482,54 +481,53 @@ static void free_all_reserved_pages(void) #define SND_MEM_PROC_FILE "driver/snd-page-alloc" static struct proc_dir_entry *snd_mem_proc; -static int snd_mem_proc_read(struct seq_file *seq, void *offset) +static int snd_mem_proc_read(char *page, char **start, off_t off, + int count, int *eof, void *data) { + int len = 0; long pages = snd_allocated_pages >> (PAGE_SHIFT-12); struct snd_mem_list *mem; int devno; static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" }; mutex_lock(&list_mutex); - seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n", - pages * PAGE_SIZE, pages, PAGE_SIZE / 1024); + len += snprintf(page + len, count - len, + "pages : %li bytes (%li pages per %likB)\n", + pages * PAGE_SIZE, pages, PAGE_SIZE / 1024); devno = 0; list_for_each_entry(mem, &mem_list_head, list) { devno++; - seq_printf(seq, "buffer %d : ID %08x : type %s\n", - devno, mem->id, types[mem->buffer.dev.type]); - seq_printf(seq, " addr = 0x%lx, size = %d bytes\n", - (unsigned long)mem->buffer.addr, - (int)mem->buffer.bytes); + len += snprintf(page + len, count - len, + "buffer %d : ID %08x : type %s\n", + devno, mem->id, types[mem->buffer.dev.type]); + len += snprintf(page + len, count - len, + " addr = 0x%lx, size = %d bytes\n", + (unsigned long)mem->buffer.addr, (int)mem->buffer.bytes); } mutex_unlock(&list_mutex); - return 0; -} - -static int snd_mem_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, snd_mem_proc_read, NULL); + return len; } /* FIXME: for pci only - other bus? */ #ifdef CONFIG_PCI #define gettoken(bufp) strsep(bufp, " \t\n") -static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) +static int snd_mem_proc_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) { char buf[128]; char *token, *p; - if (count > sizeof(buf) - 1) - return -EINVAL; + if (count > ARRAY_SIZE(buf) - 1) + count = ARRAY_SIZE(buf) - 1; if (copy_from_user(buf, buffer, count)) return -EFAULT; - buf[count] = '\0'; + buf[ARRAY_SIZE(buf) - 1] = '\0'; p = buf; token = gettoken(&p); if (! token || *token == '#') - return count; + return (int)count; if (strcmp(token, "add") == 0) { char *endp; int vendor, device, size, buffers; @@ -550,7 +548,7 @@ static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer, (buffers = simple_strtol(token, NULL, 0)) <= 0 || buffers > 4) { printk(KERN_ERR "snd-page-alloc: invalid proc write format\n"); - return count; + return (int)count; } vendor &= 0xffff; device &= 0xffff; @@ -562,7 +560,7 @@ static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer, if (pci_set_dma_mask(pci, mask) < 0 || pci_set_consistent_dma_mask(pci, mask) < 0) { printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device); - return count; + return (int)count; } } for (i = 0; i < buffers; i++) { @@ -572,7 +570,7 @@ static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer, size, &dmab) < 0) { printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); pci_dev_put(pci); - return count; + return (int)count; } snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci)); } @@ -598,21 +596,9 @@ static ssize_t snd_mem_proc_write(struct file *file, const char __user * buffer, free_all_reserved_pages(); else printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n"); - return count; + return (int)count; } #endif /* CONFIG_PCI */ - -static const struct file_operations snd_mem_proc_fops = { - .owner = THIS_MODULE, - .open = snd_mem_proc_open, - .read = seq_read, -#ifdef CONFIG_PCI - .write = snd_mem_proc_write, -#endif - .llseek = seq_lseek, - .release = single_release, -}; - #endif /* CONFIG_PROC_FS */ /* @@ -623,8 +609,12 @@ static int __init snd_mem_init(void) { #ifdef CONFIG_PROC_FS snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL); - if (snd_mem_proc) - snd_mem_proc->proc_fops = &snd_mem_proc_fops; + if (snd_mem_proc) { + snd_mem_proc->read_proc = snd_mem_proc_read; +#ifdef CONFIG_PCI + snd_mem_proc->write_proc = snd_mem_proc_write; +#endif + } #endif return 0; }