diff --git a/[refs] b/[refs] index 66efcdc4418b..8ebe0e799ec5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 56b880e2e38da6c76c454052a93c0a92aa3586f7 +refs/heads/master: b3b02ae5865c2dcd506322e0fc6def59a042e72f diff --git a/trunk/.mailmap b/trunk/.mailmap index 2909c33bc54e..9b0d0267a3c3 100644 --- a/trunk/.mailmap +++ b/trunk/.mailmap @@ -113,5 +113,3 @@ Uwe Kleine-König Valdis Kletnieks Takashi YOSHII Yusuke Goda -Gustavo Padovan -Gustavo Padovan diff --git a/trunk/Documentation/ABI/testing/sysfs-block-rssd b/trunk/Documentation/ABI/testing/sysfs-block-rssd index 679ce3543122..d535757799fe 100644 --- a/trunk/Documentation/ABI/testing/sysfs-block-rssd +++ b/trunk/Documentation/ABI/testing/sysfs-block-rssd @@ -6,21 +6,13 @@ Description: This is a read-only file. Dumps below driver information and hardware registers. - S ACTive - Command Issue + - Allocated - Completed - PORT IRQ STAT - HOST IRQ STAT - - Allocated - - Commands in Q What: /sys/block/rssd*/status Date: April 2012 KernelVersion: 3.4 Contact: Asai Thambi S P -Description: This is a read-only file. Indicates the status of the device. - -What: /sys/block/rssd*/flags -Date: May 2012 -KernelVersion: 3.5 -Contact: Asai Thambi S P -Description: This is a read-only file. Dumps the flags in port and driver - data structure +Description: This is a read-only file. Indicates the status of the device. diff --git a/trunk/Documentation/ABI/testing/sysfs-bus-fcoe b/trunk/Documentation/ABI/testing/sysfs-bus-fcoe deleted file mode 100644 index 469d09c02f6b..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-bus-fcoe +++ /dev/null @@ -1,77 +0,0 @@ -What: /sys/bus/fcoe/ctlr_X -Date: March 2012 -KernelVersion: TBD -Contact: Robert Love , devel@open-fcoe.org -Description: 'FCoE Controller' instances on the fcoe bus -Attributes: - - fcf_dev_loss_tmo: Device loss timeout peroid (see below). Changing - this value will change the dev_loss_tmo for all - FCFs discovered by this controller. - - lesb_link_fail: Link Error Status Block (LESB) link failure count. - - lesb_vlink_fail: Link Error Status Block (LESB) virtual link - failure count. - - lesb_miss_fka: Link Error Status Block (LESB) missed FCoE - Initialization Protocol (FIP) Keep-Alives (FKA). - - lesb_symb_err: Link Error Status Block (LESB) symbolic error count. - - lesb_err_block: Link Error Status Block (LESB) block error count. - - lesb_fcs_error: Link Error Status Block (LESB) Fibre Channel - Serivces error count. - -Notes: ctlr_X (global increment starting at 0) - -What: /sys/bus/fcoe/fcf_X -Date: March 2012 -KernelVersion: TBD -Contact: Robert Love , devel@open-fcoe.org -Description: 'FCoE FCF' instances on the fcoe bus. A FCF is a Fibre Channel - Forwarder, which is a FCoE switch that can accept FCoE - (Ethernet) packets, unpack them, and forward the embedded - Fibre Channel frames into a FC fabric. It can also take - outbound FC frames and pack them in Ethernet packets to - be sent to their destination on the Ethernet segment. -Attributes: - - fabric_name: Identifies the fabric that the FCF services. - - switch_name: Identifies the FCF. - - priority: The switch's priority amongst other FCFs on the same - fabric. - - selected: 1 indicates that the switch has been selected for use; - 0 indicates that the swich will not be used. - - fc_map: The Fibre Channel MAP - - vfid: The Virtual Fabric ID - - mac: The FCF's MAC address - - fka_peroid: The FIP Keep-Alive peroid - - fabric_state: The internal kernel state - "Unknown" - Initialization value - "Disconnected" - No link to the FCF/fabric - "Connected" - Host is connected to the FCF - "Deleted" - FCF is being removed from the system - - dev_loss_tmo: The device loss timeout peroid for this FCF. - -Notes: A device loss infrastructre similar to the FC Transport's - is present in fcoe_sysfs. It is nice to have so that a - link flapping adapter doesn't continually advance the count - used to identify the discovered FCF. FCFs will exist in a - "Disconnected" state until either the timer expires and the - FCF becomes "Deleted" or the FCF is rediscovered and becomes - "Connected." - - -Users: The first user of this interface will be the fcoeadm application, - which is commonly packaged in the fcoe-utils package. diff --git a/trunk/Documentation/ABI/testing/sysfs-class-mtd b/trunk/Documentation/ABI/testing/sysfs-class-mtd index db1ad7e34fc3..4d55a1888981 100644 --- a/trunk/Documentation/ABI/testing/sysfs-class-mtd +++ b/trunk/Documentation/ABI/testing/sysfs-class-mtd @@ -123,54 +123,3 @@ Description: half page, or a quarter page). In the case of ECC NOR, it is the ECC block size. - -What: /sys/class/mtd/mtdX/ecc_strength -Date: April 2012 -KernelVersion: 3.4 -Contact: linux-mtd@lists.infradead.org -Description: - Maximum number of bit errors that the device is capable of - correcting within each region covering an ecc step. This will - always be a non-negative integer. Note that some devices will - have multiple ecc steps within each writesize region. - - In the case of devices lacking any ECC capability, it is 0. - -What: /sys/class/mtd/mtdX/bitflip_threshold -Date: April 2012 -KernelVersion: 3.4 -Contact: linux-mtd@lists.infradead.org -Description: - This allows the user to examine and adjust the criteria by which - mtd returns -EUCLEAN from mtd_read(). If the maximum number of - bit errors that were corrected on any single region comprising - an ecc step (as reported by the driver) equals or exceeds this - value, -EUCLEAN is returned. Otherwise, absent an error, 0 is - returned. Higher layers (e.g., UBI) use this return code as an - indication that an erase block may be degrading and should be - scrutinized as a candidate for being marked as bad. - - The initial value may be specified by the flash device driver. - If not, then the default value is ecc_strength. - - The introduction of this feature brings a subtle change to the - meaning of the -EUCLEAN return code. Previously, it was - interpreted to mean simply "one or more bit errors were - corrected". Its new interpretation can be phrased as "a - dangerously high number of bit errors were corrected on one or - more regions comprising an ecc step". The precise definition of - "dangerously high" can be adjusted by the user with - bitflip_threshold. Users are discouraged from doing this, - however, unless they know what they are doing and have intimate - knowledge of the properties of their device. Broadly speaking, - bitflip_threshold should be low enough to detect genuine erase - block degradation, but high enough to avoid the consequences of - a persistent return value of -EUCLEAN on devices where sticky - bitflips occur. Note that if bitflip_threshold exceeds - ecc_strength, -EUCLEAN is never returned by mtd_read(). - Conversely, if bitflip_threshold is zero, -EUCLEAN is always - returned, absent a hard error. - - This is generally applicable only to NAND flash devices with ECC - capability. It is ignored on devices lacking ECC capability; - i.e., devices for which ecc_strength is zero. diff --git a/trunk/Documentation/CodingStyle b/trunk/Documentation/CodingStyle index cb9258b8fd35..c58b236bbe04 100644 --- a/trunk/Documentation/CodingStyle +++ b/trunk/Documentation/CodingStyle @@ -671,9 +671,8 @@ ones already enabled by DEBUG. Chapter 14: Allocating memory The kernel provides the following general purpose memory allocators: -kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), and -vzalloc(). Please refer to the API documentation for further information -about them. +kmalloc(), kzalloc(), kcalloc(), vmalloc(), and vzalloc(). Please refer to +the API documentation for further information about them. The preferred form for passing a size of a struct is the following: @@ -687,17 +686,6 @@ Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. -The preferred form for allocating an array is the following: - - p = kmalloc_array(n, sizeof(...), ...); - -The preferred form for allocating a zeroed array is the following: - - p = kcalloc(n, sizeof(...), ...); - -Both forms check for overflow on the allocation size n * sizeof(...), -and return NULL if that occurred. - Chapter 15: The inline disease diff --git a/trunk/Documentation/DocBook/mtdnand.tmpl b/trunk/Documentation/DocBook/mtdnand.tmpl index e0aedb7a7827..0c674be0d3c6 100644 --- a/trunk/Documentation/DocBook/mtdnand.tmpl +++ b/trunk/Documentation/DocBook/mtdnand.tmpl @@ -1119,6 +1119,8 @@ in this page These constants are defined in nand.h. They are ored together to describe the chip functionality. +/* Chip can not auto increment pages */ +#define NAND_NO_AUTOINCR 0x00000001 /* Buswitdh is 16 bit */ #define NAND_BUSWIDTH_16 0x00000002 /* Device supports partial programming without padding */ diff --git a/trunk/Documentation/arm/OMAP/DSS b/trunk/Documentation/arm/OMAP/DSS index a564ceea9e98..888ae7b83ae4 100644 --- a/trunk/Documentation/arm/OMAP/DSS +++ b/trunk/Documentation/arm/OMAP/DSS @@ -47,51 +47,6 @@ flexible way to enable non-common multi-display configuration. In addition to modelling the hardware overlays, omapdss supports virtual overlays and overlay managers. These can be used when updating a display with CPU or system DMA. -omapdss driver support for audio --------------------------------- -There exist several display technologies and standards that support audio as -well. Hence, it is relevant to update the DSS device driver to provide an audio -interface that may be used by an audio driver or any other driver interested in -the functionality. - -The audio_enable function is intended to prepare the relevant -IP for playback (e.g., enabling an audio FIFO, taking in/out of reset -some IP, enabling companion chips, etc). It is intended to be called before -audio_start. The audio_disable function performs the reverse operation and is -intended to be called after audio_stop. - -While a given DSS device driver may support audio, it is possible that for -certain configurations audio is not supported (e.g., an HDMI display using a -VESA video timing). The audio_supported function is intended to query whether -the current configuration of the display supports audio. - -The audio_config function is intended to configure all the relevant audio -parameters of the display. In order to make the function independent of any -specific DSS device driver, a struct omap_dss_audio is defined. Its purpose -is to contain all the required parameters for audio configuration. At the -moment, such structure contains pointers to IEC-60958 channel status word -and CEA-861 audio infoframe structures. This should be enough to support -HDMI and DisplayPort, as both are based on CEA-861 and IEC-60958. - -The audio_enable/disable, audio_config and audio_supported functions could be -implemented as functions that may sleep. Hence, they should not be called -while holding a spinlock or a readlock. - -The audio_start/audio_stop function is intended to effectively start/stop audio -playback after the configuration has taken place. These functions are designed -to be used in an atomic context. Hence, audio_start should return quickly and be -called only after all the needed resources for audio playback (audio FIFOs, -DMA channels, companion chips, etc) have been enabled to begin data transfers. -audio_stop is designed to only stop the audio transfers. The resources used -for playback are released using audio_disable. - -The enum omap_dss_audio_state may be used to help the implementations of -the interface to keep track of the audio state. The initial state is _DISABLED; -then, the state transitions to _CONFIGURED, and then, when it is ready to -play audio, to _ENABLED. The state _PLAYING is used when the audio is being -rendered. - - Panel and controller drivers ---------------------------- @@ -201,7 +156,6 @@ timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw) "pal" and "ntsc" panel_name tear_elim Tearing elimination 0=off, 1=on -output_type Output type (video encoder only): "composite" or "svideo" There are also some debugfs files at /omapdss/ which show information about clocks and registers. diff --git a/trunk/Documentation/device-mapper/thin-provisioning.txt b/trunk/Documentation/device-mapper/thin-provisioning.txt index f5cfc62b7ad3..3370bc4d7b98 100644 --- a/trunk/Documentation/device-mapper/thin-provisioning.txt +++ b/trunk/Documentation/device-mapper/thin-provisioning.txt @@ -287,17 +287,6 @@ iii) Messages the current transaction id is when you change it with this compare-and-swap message. - reserve_metadata_snap - - Reserve a copy of the data mapping btree for use by userland. - This allows userland to inspect the mappings as they were when - this message was executed. Use the pool's status command to - get the root block associated with the metadata snapshot. - - release_metadata_snap - - Release a previously reserved copy of the data mapping btree. - 'thin' target ------------- diff --git a/trunk/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt b/trunk/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt deleted file mode 100644 index ae8af1694e95..000000000000 --- a/trunk/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt +++ /dev/null @@ -1,93 +0,0 @@ -Pinctrl-based I2C Bus Mux - -This binding describes an I2C bus multiplexer that uses pin multiplexing to -route the I2C signals, and represents the pin multiplexing configuration -using the pinctrl device tree bindings. - - +-----+ +-----+ - | dev | | dev | - +------------------------+ +-----+ +-----+ - | SoC | | | - | /----|------+--------+ - | +---+ +------+ | child bus A, on first set of pins - | |I2C|---|Pinmux| | - | +---+ +------+ | child bus B, on second set of pins - | \----|------+--------+--------+ - | | | | | - +------------------------+ +-----+ +-----+ +-----+ - | dev | | dev | | dev | - +-----+ +-----+ +-----+ - -Required properties: -- compatible: i2c-mux-pinctrl -- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side - port is connected to. - -Also required are: - -* Standard pinctrl properties that specify the pin mux state for each child - bus. See ../pinctrl/pinctrl-bindings.txt. - -* Standard I2C mux properties. See mux.txt in this directory. - -* I2C child bus nodes. See mux.txt in this directory. - -For each named state defined in the pinctrl-names property, an I2C child bus -will be created. I2C child bus numbers are assigned based on the index into -the pinctrl-names property. - -The only exception is that no bus will be created for a state named "idle". If -such a state is defined, it must be the last entry in pinctrl-names. For -example: - - pinctrl-names = "ddc", "pta", "idle" -> ddc = bus 0, pta = bus 1 - pinctrl-names = "ddc", "idle", "pta" -> Invalid ("idle" not last) - pinctrl-names = "idle", "ddc", "pta" -> Invalid ("idle" not last) - -Whenever an access is made to a device on a child bus, the relevant pinctrl -state will be programmed into hardware. - -If an idle state is defined, whenever an access is not being made to a device -on a child bus, the idle pinctrl state will be programmed into hardware. - -If an idle state is not defined, the most recently used pinctrl state will be -left programmed into hardware whenever no access is being made of a device on -a child bus. - -Example: - - i2cmux { - compatible = "i2c-mux-pinctrl"; - #address-cells = <1>; - #size-cells = <0>; - - i2c-parent = <&i2c1>; - - pinctrl-names = "ddc", "pta", "idle"; - pinctrl-0 = <&state_i2cmux_ddc>; - pinctrl-1 = <&state_i2cmux_pta>; - pinctrl-2 = <&state_i2cmux_idle>; - - i2c@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - eeprom { - compatible = "eeprom"; - reg = <0x50>; - }; - }; - - i2c@1 { - reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - - eeprom { - compatible = "eeprom"; - reg = <0x50>; - }; - }; - }; - diff --git a/trunk/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/trunk/Documentation/devicetree/bindings/mtd/gpmi-nand.txt deleted file mode 100644 index 1a5bbd346d22..000000000000 --- a/trunk/Documentation/devicetree/bindings/mtd/gpmi-nand.txt +++ /dev/null @@ -1,33 +0,0 @@ -* Freescale General-Purpose Media Interface (GPMI) - -The GPMI nand controller provides an interface to control the -NAND flash chips. We support only one NAND chip now. - -Required properties: - - compatible : should be "fsl,-gpmi-nand" - - reg : should contain registers location and length for gpmi and bch. - - reg-names: Should contain the reg names "gpmi-nand" and "bch" - - interrupts : The first is the DMA interrupt number for GPMI. - The second is the BCH interrupt number. - - interrupt-names : The interrupt names "gpmi-dma", "bch"; - - fsl,gpmi-dma-channel : Should contain the dma channel it uses. - -The device tree may optionally contain sub-nodes describing partitions of the -address space. See partition.txt for more detail. - -Examples: - -gpmi-nand@8000c000 { - compatible = "fsl,imx28-gpmi-nand"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0x8000c000 2000>, <0x8000a000 2000>; - reg-names = "gpmi-nand", "bch"; - interrupts = <88>, <41>; - interrupt-names = "gpmi-dma", "bch"; - fsl,gpmi-dma-channel = <4>; - - partition@0 { - ... - }; -}; diff --git a/trunk/Documentation/devicetree/bindings/mtd/mxc-nand.txt b/trunk/Documentation/devicetree/bindings/mtd/mxc-nand.txt deleted file mode 100644 index b5833d11c7be..000000000000 --- a/trunk/Documentation/devicetree/bindings/mtd/mxc-nand.txt +++ /dev/null @@ -1,19 +0,0 @@ -* Freescale's mxc_nand - -Required properties: -- compatible: "fsl,imxXX-nand" -- reg: address range of the nfc block -- interrupts: irq to be used -- nand-bus-width: see nand.txt -- nand-ecc-mode: see nand.txt -- nand-on-flash-bbt: see nand.txt - -Example: - - nand@d8000000 { - compatible = "fsl,imx27-nand"; - reg = <0xd8000000 0x1000>; - interrupts = <29>; - nand-bus-width = <8>; - nand-ecc-mode = "hw"; - }; diff --git a/trunk/Documentation/filesystems/Locking b/trunk/Documentation/filesystems/Locking index 8e2da1e06e3b..d449e632e6a0 100644 --- a/trunk/Documentation/filesystems/Locking +++ b/trunk/Documentation/filesystems/Locking @@ -61,7 +61,6 @@ ata *); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); - void (*update_time)(struct inode *, struct timespec *, int); locking rules: all may block @@ -88,8 +87,6 @@ getxattr: no listxattr: no removexattr: yes fiemap: no -update_time: no - Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on victim. cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. diff --git a/trunk/Documentation/filesystems/proc.txt b/trunk/Documentation/filesystems/proc.txt index fb0a6aeb936c..912af6ce5626 100644 --- a/trunk/Documentation/filesystems/proc.txt +++ b/trunk/Documentation/filesystems/proc.txt @@ -40,7 +40,6 @@ Table of Contents 3.4 /proc//coredump_filter - Core dump filtering settings 3.5 /proc//mountinfo - Information about mounts 3.6 /proc//comm & /proc//task//comm - 3.7 /proc//task//children - Information about task children 4 Configuring procfs 4.1 Mount options @@ -311,11 +310,6 @@ Table 1-4: Contents of the stat files (as of 2.6.30-rc7) start_data address above which program data+bss is placed end_data address below which program data+bss is placed start_brk address above which program heap can be expanded with brk() - arg_start address above which program command line is placed - arg_end address below which program command line is placed - env_start address above which program environment is placed - env_end address below which program environment is placed - exit_code the thread's exit_code in the form reported by the waitpid system call .............................................................................. The /proc/PID/maps file containing the currently mapped memory regions and @@ -1584,23 +1578,6 @@ then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated comm value. -3.7 /proc//task//children - Information about task children -------------------------------------------------------------------------- -This file provides a fast way to retrieve first level children pids -of a task pointed by / pair. The format is a space separated -stream of pids. - -Note the "first level" here -- if a child has own children they will -not be listed here, one needs to read /proc//task//children -to obtain the descendants. - -Since this interface is intended to be fast and cheap it doesn't -guarantee to provide precise results and some children might be -skipped, especially if they've exited right after we printed their -pids, so one need to either stop or freeze processes being inspected -if precise results are needed. - - ------------------------------------------------------------------------------ Configuring procfs ------------------------------------------------------------------------------ diff --git a/trunk/Documentation/filesystems/vfs.txt b/trunk/Documentation/filesystems/vfs.txt index efd23f481704..ef19f91a0f12 100644 --- a/trunk/Documentation/filesystems/vfs.txt +++ b/trunk/Documentation/filesystems/vfs.txt @@ -363,7 +363,6 @@ struct inode_operations { ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); - void (*update_time)(struct inode *, struct timespec *, int); }; Again, all methods are called without any locks being held, unless @@ -472,9 +471,6 @@ otherwise noted. removexattr: called by the VFS to remove an extended attribute from a file. This method is called by removexattr(2) system call. - update_time: called by the VFS to update a specific time or the i_version of - an inode. If this is not defined the VFS will update the inode itself - and call mark_inode_dirty_sync. The Address Space Object ======================== diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index a92c5ebf373e..c45513d806ab 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -2543,15 +2543,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. sched_debug [KNL] Enables verbose scheduler debug messages. - skew_tick= [KNL] Offset the periodic timer tick per cpu to mitigate - xtime_lock contention on larger systems, and/or RCU lock - contention on all systems with CONFIG_MAXSMP set. - Format: { "0" | "1" } - 0 -- disable. (may be 1 via CONFIG_CMDLINE="skew_tick=1" - 1 -- enable. - Note: increases power consumption, thus should only be - enabled if running jitter sensitive (HPC/RT) workloads. - security= [SECURITY] Choose a security module to enable at boot. If this boot parameter is not specified, only the first security module asking for security registration will be diff --git a/trunk/Documentation/networking/stmmac.txt b/trunk/Documentation/networking/stmmac.txt index 5cb9a1972460..ab1e8d7004c5 100644 --- a/trunk/Documentation/networking/stmmac.txt +++ b/trunk/Documentation/networking/stmmac.txt @@ -10,8 +10,8 @@ Currently this network device driver is for all STM embedded MAC/GMAC (i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000 FF1152AMT0221 D1215994A VIRTEX FPGA board. -DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether -MAC 10/100 Universal version 4.0 have been used for developing this driver. +DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether MAC 10/100 +Universal version 4.0 have been used for developing this driver. This driver supports both the platform bus and PCI. @@ -54,27 +54,27 @@ net_device structure enabling the scatter/gather feature. When one or more packets are received, an interrupt happens. The interrupts are not queued so the driver has to scan all the descriptors in the ring during the receive process. -This is based on NAPI so the interrupt handler signals only if there is work -to be done, and it exits. +This is based on NAPI so the interrupt handler signals only if there is work to be +done, and it exits. Then the poll method will be scheduled at some future point. The incoming packets are stored, by the DMA, in a list of pre-allocated socket buffers in order to avoid the memcpy (Zero-copy). 4.3) Timer-Driver Interrupt -Instead of having the device that asynchronously notifies the frame receptions, -the driver configures a timer to generate an interrupt at regular intervals. -Based on the granularity of the timer, the frames that are received by the -device will experience different levels of latency. Some NICs have dedicated -timer device to perform this task. STMMAC can use either the RTC device or the -TMU channel 2 on STLinux platforms. +Instead of having the device that asynchronously notifies the frame receptions, the +driver configures a timer to generate an interrupt at regular intervals. +Based on the granularity of the timer, the frames that are received by the device +will experience different levels of latency. Some NICs have dedicated timer +device to perform this task. STMMAC can use either the RTC device or the TMU +channel 2 on STLinux platforms. The timers frequency can be passed to the driver as parameter; when change it, take care of both hardware capability and network stability/performance impact. -Several performance tests on STM platforms showed this optimisation allows to -spare the CPU while having the maximum throughput. +Several performance tests on STM platforms showed this optimisation allows to spare +the CPU while having the maximum throughput. 4.4) WOL -Wake up on Lan feature through Magic and Unicast frames are supported for the -GMAC core. +Wake up on Lan feature through Magic and Unicast frames are supported for the GMAC +core. 4.5) DMA descriptors Driver handles both normal and enhanced descriptors. The latter has been only @@ -106,8 +106,7 @@ Several driver's information can be passed through the platform These are included in the include/linux/stmmac.h header file and detailed below as well: -struct plat_stmmacenet_data { - char *phy_bus_name; + struct plat_stmmacenet_data { int bus_id; int phy_addr; int interface; @@ -125,24 +124,19 @@ struct plat_stmmacenet_data { void (*bus_setup)(void __iomem *ioaddr); int (*init)(struct platform_device *pdev); void (*exit)(struct platform_device *pdev); - void *custom_cfg; - void *custom_data; void *bsp_priv; }; Where: - o phy_bus_name: phy bus name to attach to the stmmac. o bus_id: bus identifier. o phy_addr: the physical address can be passed from the platform. If it is set to -1 the driver will automatically detect it at run-time by probing all the 32 addresses. o interface: PHY device's interface. o mdio_bus_data: specific platform fields for the MDIO bus. - o dma_cfg: internal DMA parameters - o pbl: the Programmable Burst Length is maximum number of beats to + o pbl: the Programmable Burst Length is maximum number of beats to be transferred in one DMA transaction. GMAC also enables the 4xPBL by default. - o fixed_burst/mixed_burst/burst_len o clk_csr: fixed CSR Clock range selection. o has_gmac: uses the GMAC core. o enh_desc: if sets the MAC will use the enhanced descriptor structure. @@ -166,9 +160,8 @@ Where: this is sometime necessary on some platforms (e.g. ST boxes) where the HW needs to have set some PIO lines or system cfg registers. - o custom_cfg/custom_data: this is a custom configuration that can be passed - while initialising the resources. - o bsp_priv: another private poiter. + o custom_cfg: this is a custom configuration that can be passed while + initialising the resources. For MDIO bus The we have: @@ -187,6 +180,7 @@ Where: o irqs: list of IRQs, one per PHY. o probed_phy_irq: if irqs is NULL, use this for probed PHY. + For DMA engine we have the following internal fields that should be tuned according to the HW capabilities. diff --git a/trunk/Documentation/power/charger-manager.txt b/trunk/Documentation/power/charger-manager.txt index b4f7f4b23f64..fdcca991df30 100644 --- a/trunk/Documentation/power/charger-manager.txt +++ b/trunk/Documentation/power/charger-manager.txt @@ -44,16 +44,6 @@ Charger Manager supports the following: Normally, the platform will need to resume and suspend some devices that are used by Charger Manager. -* Support for premature full-battery event handling - If the battery voltage drops by "fullbatt_vchkdrop_uV" after - "fullbatt_vchkdrop_ms" from the full-battery event, the framework - restarts charging. This check is also performed while suspended by - setting wakeup time accordingly and using suspend_again. - -* Support for uevent-notify - With the charger-related events, the device sends - notification to users with UEVENT. - 2. Global Charger-Manager Data related with suspend_again ======================================================== In order to setup Charger Manager with suspend-again feature @@ -65,7 +55,7 @@ if there are multiple batteries. If there are multiple batteries, the multiple instances of Charger Manager share the same charger_global_desc and it will manage in-suspend monitoring for all instances of Charger Manager. -The user needs to provide all the three entries properly in order to activate +The user needs to provide all the two entries properly in order to activate in-suspend monitoring: struct charger_global_desc { @@ -84,11 +74,6 @@ bool (*rtc_only_wakeup)(void); same struct. If there is any other wakeup source triggered the wakeup, it should return false. If the "rtc" is the only wakeup reason, it should return true. - -bool assume_timer_stops_in_suspend; - : if true, Charger Manager assumes that - the timer (CM uses jiffies as timer) stops during suspend. Then, CM - assumes that the suspend-duration is same as the alarm length. }; 3. How to setup suspend_again @@ -126,16 +111,6 @@ enum polling_modes polling_mode; CM_POLL_CHARGING_ONLY: poll this battery if and only if the battery is being charged. -unsigned int fullbatt_vchkdrop_ms; -unsigned int fullbatt_vchkdrop_uV; - : If both have non-zero values, Charger Manager will check the - battery voltage drop fullbatt_vchkdrop_ms after the battery is fully - charged. If the voltage drop is over fullbatt_vchkdrop_uV, Charger - Manager will try to recharge the battery by disabling and enabling - chargers. Recharge with voltage drop condition only (without delay - condition) is needed to be implemented with hardware interrupts from - fuel gauges or charger devices/chips. - unsigned int fullbatt_uV; : If specified with a non-zero value, Charger Manager assumes that the battery is full (capacity = 100) if the battery is not being @@ -147,8 +122,6 @@ unsigned int polling_interval_ms; this battery every polling_interval_ms or more frequently. enum data_source battery_present; - : CM_BATTERY_PRESENT: assume that the battery exists. - CM_NO_BATTERY: assume that the battery does not exists. CM_FUEL_GAUGE: get battery presence information from fuel gauge. CM_CHARGER_STAT: get battery presence from chargers. @@ -178,17 +151,7 @@ bool measure_battery_temp; the value of measure_battery_temp. }; -5. Notify Charger-Manager of charger events: cm_notify_event() -========================================================= -If there is an charger event is required to notify -Charger Manager, a charger device driver that triggers the event can call -cm_notify_event(psy, type, msg) to notify the corresponding Charger Manager. -In the function, psy is the charger driver's power_supply pointer, which is -associated with Charger-Manager. The parameter "type" -is the same as irq's type (enum cm_event_types). The event message "msg" is -optional and is effective only if the event type is "UNDESCRIBED" or "OTHERS". - -6. Other Considerations +5. Other Considerations ======================= At the charger/battery-related events such as battery-pulled-out, diff --git a/trunk/Documentation/power/power_supply_class.txt b/trunk/Documentation/power/power_supply_class.txt index 211831d4095f..9f16c5178b66 100644 --- a/trunk/Documentation/power/power_supply_class.txt +++ b/trunk/Documentation/power/power_supply_class.txt @@ -84,8 +84,6 @@ are already charged or discharging, 'n/a' can be displayed (or HEALTH - represents health of the battery, values corresponds to POWER_SUPPLY_HEALTH_*, defined in battery.h. -VOLTAGE_OCV - open circuit voltage of the battery. - VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and minimal power supply voltages. Maximal/minimal means values of voltages when battery considered "full"/"empty" at normal conditions. Yes, there is diff --git a/trunk/Documentation/sysctl/fs.txt b/trunk/Documentation/sysctl/fs.txt index 13d6166d7a27..88fd7f5c8dcd 100644 --- a/trunk/Documentation/sysctl/fs.txt +++ b/trunk/Documentation/sysctl/fs.txt @@ -225,13 +225,6 @@ a queue must be less or equal then msg_max. maximum message size value (it is every message queue's attribute set during its creation). -/proc/sys/fs/mqueue/msg_default is a read/write file for setting/getting the -default number of messages in a queue value if attr parameter of mq_open(2) is -NULL. If it exceed msg_max, the default value is initialized msg_max. - -/proc/sys/fs/mqueue/msgsize_default is a read/write file for setting/getting -the default message size value if attr parameter of mq_open(2) is NULL. If it -exceed msgsize_max, the default value is initialized msgsize_max. 4. /proc/sys/fs/epoll - Configuration options for the epoll interface -------------------------------------------------------- diff --git a/trunk/Documentation/vm/frontswap.txt b/trunk/Documentation/vm/frontswap.txt deleted file mode 100644 index 37067cf455f4..000000000000 --- a/trunk/Documentation/vm/frontswap.txt +++ /dev/null @@ -1,278 +0,0 @@ -Frontswap provides a "transcendent memory" interface for swap pages. -In some environments, dramatic performance savings may be obtained because -swapped pages are saved in RAM (or a RAM-like device) instead of a swap disk. - -(Note, frontswap -- and cleancache (merged at 3.0) -- are the "frontends" -and the only necessary changes to the core kernel for transcendent memory; -all other supporting code -- the "backends" -- is implemented as drivers. -See the LWN.net article "Transcendent memory in a nutshell" for a detailed -overview of frontswap and related kernel parts: -https://lwn.net/Articles/454795/ ) - -Frontswap is so named because it can be thought of as the opposite of -a "backing" store for a swap device. The storage is assumed to be -a synchronous concurrency-safe page-oriented "pseudo-RAM device" conforming -to the requirements of transcendent memory (such as Xen's "tmem", or -in-kernel compressed memory, aka "zcache", or future RAM-like devices); -this pseudo-RAM device is not directly accessible or addressable by the -kernel and is of unknown and possibly time-varying size. The driver -links itself to frontswap by calling frontswap_register_ops to set the -frontswap_ops funcs appropriately and the functions it provides must -conform to certain policies as follows: - -An "init" prepares the device to receive frontswap pages associated -with the specified swap device number (aka "type"). A "store" will -copy the page to transcendent memory and associate it with the type and -offset associated with the page. A "load" will copy the page, if found, -from transcendent memory into kernel memory, but will NOT remove the page -from from transcendent memory. An "invalidate_page" will remove the page -from transcendent memory and an "invalidate_area" will remove ALL pages -associated with the swap type (e.g., like swapoff) and notify the "device" -to refuse further stores with that swap type. - -Once a page is successfully stored, a matching load on the page will normally -succeed. So when the kernel finds itself in a situation where it needs -to swap out a page, it first attempts to use frontswap. If the store returns -success, the data has been successfully saved to transcendent memory and -a disk write and, if the data is later read back, a disk read are avoided. -If a store returns failure, transcendent memory has rejected the data, and the -page can be written to swap as usual. - -If a backend chooses, frontswap can be configured as a "writethrough -cache" by calling frontswap_writethrough(). In this mode, the reduction -in swap device writes is lost (and also a non-trivial performance advantage) -in order to allow the backend to arbitrarily "reclaim" space used to -store frontswap pages to more completely manage its memory usage. - -Note that if a page is stored and the page already exists in transcendent memory -(a "duplicate" store), either the store succeeds and the data is overwritten, -or the store fails AND the page is invalidated. This ensures stale data may -never be obtained from frontswap. - -If properly configured, monitoring of frontswap is done via debugfs in -the /sys/kernel/debug/frontswap directory. The effectiveness of -frontswap can be measured (across all swap devices) with: - -failed_stores - how many store attempts have failed -loads - how many loads were attempted (all should succeed) -succ_stores - how many store attempts have succeeded -invalidates - how many invalidates were attempted - -A backend implementation may provide additional metrics. - -FAQ - -1) Where's the value? - -When a workload starts swapping, performance falls through the floor. -Frontswap significantly increases performance in many such workloads by -providing a clean, dynamic interface to read and write swap pages to -"transcendent memory" that is otherwise not directly addressable to the kernel. -This interface is ideal when data is transformed to a different form -and size (such as with compression) or secretly moved (as might be -useful for write-balancing for some RAM-like devices). Swap pages (and -evicted page-cache pages) are a great use for this kind of slower-than-RAM- -but-much-faster-than-disk "pseudo-RAM device" and the frontswap (and -cleancache) interface to transcendent memory provides a nice way to read -and write -- and indirectly "name" -- the pages. - -Frontswap -- and cleancache -- with a fairly small impact on the kernel, -provides a huge amount of flexibility for more dynamic, flexible RAM -utilization in various system configurations: - -In the single kernel case, aka "zcache", pages are compressed and -stored in local memory, thus increasing the total anonymous pages -that can be safely kept in RAM. Zcache essentially trades off CPU -cycles used in compression/decompression for better memory utilization. -Benchmarks have shown little or no impact when memory pressure is -low while providing a significant performance improvement (25%+) -on some workloads under high memory pressure. - -"RAMster" builds on zcache by adding "peer-to-peer" transcendent memory -support for clustered systems. Frontswap pages are locally compressed -as in zcache, but then "remotified" to another system's RAM. This -allows RAM to be dynamically load-balanced back-and-forth as needed, -i.e. when system A is overcommitted, it can swap to system B, and -vice versa. RAMster can also be configured as a memory server so -many servers in a cluster can swap, dynamically as needed, to a single -server configured with a large amount of RAM... without pre-configuring -how much of the RAM is available for each of the clients! - -In the virtual case, the whole point of virtualization is to statistically -multiplex physical resources acrosst the varying demands of multiple -virtual machines. This is really hard to do with RAM and efforts to do -it well with no kernel changes have essentially failed (except in some -well-publicized special-case workloads). -Specifically, the Xen Transcendent Memory backend allows otherwise -"fallow" hypervisor-owned RAM to not only be "time-shared" between multiple -virtual machines, but the pages can be compressed and deduplicated to -optimize RAM utilization. And when guest OS's are induced to surrender -underutilized RAM (e.g. with "selfballooning"), sudden unexpected -memory pressure may result in swapping; frontswap allows those pages -to be swapped to and from hypervisor RAM (if overall host system memory -conditions allow), thus mitigating the potentially awful performance impact -of unplanned swapping. - -A KVM implementation is underway and has been RFC'ed to lkml. And, -using frontswap, investigation is also underway on the use of NVM as -a memory extension technology. - -2) Sure there may be performance advantages in some situations, but - what's the space/time overhead of frontswap? - -If CONFIG_FRONTSWAP is disabled, every frontswap hook compiles into -nothingness and the only overhead is a few extra bytes per swapon'ed -swap device. If CONFIG_FRONTSWAP is enabled but no frontswap "backend" -registers, there is one extra global variable compared to zero for -every swap page read or written. If CONFIG_FRONTSWAP is enabled -AND a frontswap backend registers AND the backend fails every "store" -request (i.e. provides no memory despite claiming it might), -CPU overhead is still negligible -- and since every frontswap fail -precedes a swap page write-to-disk, the system is highly likely -to be I/O bound and using a small fraction of a percent of a CPU -will be irrelevant anyway. - -As for space, if CONFIG_FRONTSWAP is enabled AND a frontswap backend -registers, one bit is allocated for every swap page for every swap -device that is swapon'd. This is added to the EIGHT bits (which -was sixteen until about 2.6.34) that the kernel already allocates -for every swap page for every swap device that is swapon'd. (Hugh -Dickins has observed that frontswap could probably steal one of -the existing eight bits, but let's worry about that minor optimization -later.) For very large swap disks (which are rare) on a standard -4K pagesize, this is 1MB per 32GB swap. - -When swap pages are stored in transcendent memory instead of written -out to disk, there is a side effect that this may create more memory -pressure that can potentially outweigh the other advantages. A -backend, such as zcache, must implement policies to carefully (but -dynamically) manage memory limits to ensure this doesn't happen. - -3) OK, how about a quick overview of what this frontswap patch does - in terms that a kernel hacker can grok? - -Let's assume that a frontswap "backend" has registered during -kernel initialization; this registration indicates that this -frontswap backend has access to some "memory" that is not directly -accessible by the kernel. Exactly how much memory it provides is -entirely dynamic and random. - -Whenever a swap-device is swapon'd frontswap_init() is called, -passing the swap device number (aka "type") as a parameter. -This notifies frontswap to expect attempts to "store" swap pages -associated with that number. - -Whenever the swap subsystem is readying a page to write to a swap -device (c.f swap_writepage()), frontswap_store is called. Frontswap -consults with the frontswap backend and if the backend says it does NOT -have room, frontswap_store returns -1 and the kernel swaps the page -to the swap device as normal. Note that the response from the frontswap -backend is unpredictable to the kernel; it may choose to never accept a -page, it could accept every ninth page, or it might accept every -page. But if the backend does accept a page, the data from the page -has already been copied and associated with the type and offset, -and the backend guarantees the persistence of the data. In this case, -frontswap sets a bit in the "frontswap_map" for the swap device -corresponding to the page offset on the swap device to which it would -otherwise have written the data. - -When the swap subsystem needs to swap-in a page (swap_readpage()), -it first calls frontswap_load() which checks the frontswap_map to -see if the page was earlier accepted by the frontswap backend. If -it was, the page of data is filled from the frontswap backend and -the swap-in is complete. If not, the normal swap-in code is -executed to obtain the page of data from the real swap device. - -So every time the frontswap backend accepts a page, a swap device read -and (potentially) a swap device write are replaced by a "frontswap backend -store" and (possibly) a "frontswap backend loads", which are presumably much -faster. - -4) Can't frontswap be configured as a "special" swap device that is - just higher priority than any real swap device (e.g. like zswap, - or maybe swap-over-nbd/NFS)? - -No. First, the existing swap subsystem doesn't allow for any kind of -swap hierarchy. Perhaps it could be rewritten to accomodate a hierarchy, -but this would require fairly drastic changes. Even if it were -rewritten, the existing swap subsystem uses the block I/O layer which -assumes a swap device is fixed size and any page in it is linearly -addressable. Frontswap barely touches the existing swap subsystem, -and works around the constraints of the block I/O subsystem to provide -a great deal of flexibility and dynamicity. - -For example, the acceptance of any swap page by the frontswap backend is -entirely unpredictable. This is critical to the definition of frontswap -backends because it grants completely dynamic discretion to the -backend. In zcache, one cannot know a priori how compressible a page is. -"Poorly" compressible pages can be rejected, and "poorly" can itself be -defined dynamically depending on current memory constraints. - -Further, frontswap is entirely synchronous whereas a real swap -device is, by definition, asynchronous and uses block I/O. The -block I/O layer is not only unnecessary, but may perform "optimizations" -that are inappropriate for a RAM-oriented device including delaying -the write of some pages for a significant amount of time. Synchrony is -required to ensure the dynamicity of the backend and to avoid thorny race -conditions that would unnecessarily and greatly complicate frontswap -and/or the block I/O subsystem. That said, only the initial "store" -and "load" operations need be synchronous. A separate asynchronous thread -is free to manipulate the pages stored by frontswap. For example, -the "remotification" thread in RAMster uses standard asynchronous -kernel sockets to move compressed frontswap pages to a remote machine. -Similarly, a KVM guest-side implementation could do in-guest compression -and use "batched" hypercalls. - -In a virtualized environment, the dynamicity allows the hypervisor -(or host OS) to do "intelligent overcommit". For example, it can -choose to accept pages only until host-swapping might be imminent, -then force guests to do their own swapping. - -There is a downside to the transcendent memory specifications for -frontswap: Since any "store" might fail, there must always be a real -slot on a real swap device to swap the page. Thus frontswap must be -implemented as a "shadow" to every swapon'd device with the potential -capability of holding every page that the swap device might have held -and the possibility that it might hold no pages at all. This means -that frontswap cannot contain more pages than the total of swapon'd -swap devices. For example, if NO swap device is configured on some -installation, frontswap is useless. Swapless portable devices -can still use frontswap but a backend for such devices must configure -some kind of "ghost" swap device and ensure that it is never used. - -5) Why this weird definition about "duplicate stores"? If a page - has been previously successfully stored, can't it always be - successfully overwritten? - -Nearly always it can, but no, sometimes it cannot. Consider an example -where data is compressed and the original 4K page has been compressed -to 1K. Now an attempt is made to overwrite the page with data that -is non-compressible and so would take the entire 4K. But the backend -has no more space. In this case, the store must be rejected. Whenever -frontswap rejects a store that would overwrite, it also must invalidate -the old data and ensure that it is no longer accessible. Since the -swap subsystem then writes the new data to the read swap device, -this is the correct course of action to ensure coherency. - -6) What is frontswap_shrink for? - -When the (non-frontswap) swap subsystem swaps out a page to a real -swap device, that page is only taking up low-value pre-allocated disk -space. But if frontswap has placed a page in transcendent memory, that -page may be taking up valuable real estate. The frontswap_shrink -routine allows code outside of the swap subsystem to force pages out -of the memory managed by frontswap and back into kernel-addressable memory. -For example, in RAMster, a "suction driver" thread will attempt -to "repatriate" pages sent to a remote machine back to the local machine; -this is driven using the frontswap_shrink mechanism when memory pressure -subsides. - -7) Why does the frontswap patch create the new include file swapfile.h? - -The frontswap code depends on some swap-subsystem-internal data -structures that have, over the years, moved back and forth between -static and global. This seemed a reasonable compromise: Define -them as global but declare them in a new include file that isn't -included by the large number of source files that include swap.h. - -Dan Magenheimer, last updated April 9, 2012 diff --git a/trunk/Documentation/vm/pagemap.txt b/trunk/Documentation/vm/pagemap.txt index 7587493c67f1..4600cbe3d6be 100644 --- a/trunk/Documentation/vm/pagemap.txt +++ b/trunk/Documentation/vm/pagemap.txt @@ -16,7 +16,7 @@ There are three components to pagemap: * Bits 0-4 swap type if swapped * Bits 5-54 swap offset if swapped * Bits 55-60 page shift (page size = 1< bzImage.efi console=ttyS0 root=/dev/sda4 - - -**** The "initrd=" option - -Like most boot loaders, the EFI stub allows the user to specify -multiple initrd files using the "initrd=" option. This is the only EFI -stub-specific command line parameter, everything else is passed to the -kernel when it boots. - -The path to the initrd file must be an absolute path from the -beginning of the ESP, relative path names do not work. Also, the path -is an EFI-style path and directory elements must be separated with -backslashes (\). For example, given the following directory layout, - -fs0:> - Kernels\ - bzImage.efi - initrd-large.img - - Ramdisks\ - initrd-small.img - initrd-medium.img - -to boot with the initrd-large.img file if the current working -directory is fs0:\Kernels, the following command must be used, - - fs0:\Kernels> bzImage.efi initrd=\Kernels\initrd-large.img - -Notice how bzImage.efi can be specified with a relative path. That's -because the image we're executing is interpreted by the EFI shell, -which understands relative paths, whereas the rest of the command line -is passed to bzImage.efi. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 3e30a3afe2a4..8cad55b9db99 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1077,7 +1077,7 @@ F: drivers/media/video/s5p-fimc/ ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT M: Kyungmin Park M: Kamil Debski -M: Jeongtae Park +M: Jeongtae Park L: linux-arm-kernel@lists.infradead.org L: linux-media@vger.kernel.org S: Maintained @@ -1646,11 +1646,11 @@ S: Maintained F: drivers/gpio/gpio-bt8xx.c BTRFS FILE SYSTEM -M: Chris Mason +M: Chris Mason L: linux-btrfs@vger.kernel.org W: http://btrfs.wiki.kernel.org/ Q: http://patchwork.kernel.org/project/linux-btrfs/list/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git S: Maintained F: Documentation/filesystems/btrfs.txt F: fs/btrfs/ @@ -1743,10 +1743,10 @@ F: include/linux/can/platform/ CAPABILITIES M: Serge Hallyn L: linux-security-module@vger.kernel.org -S: Supported +S: Supported F: include/linux/capability.h F: security/capability.c -F: security/commoncap.c +F: security/commoncap.c F: kernel/capability.c CELL BROADBAND ENGINE ARCHITECTURE @@ -1800,9 +1800,6 @@ F: include/linux/cfag12864b.h CFG80211 and NL80211 M: Johannes Berg L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git S: Maintained F: include/linux/nl80211.h F: include/net/cfg80211.h @@ -2149,11 +2146,11 @@ S: Orphan F: drivers/net/wan/pc300* CYTTSP TOUCHSCREEN DRIVER -M: Javier Martinez Canillas -L: linux-input@vger.kernel.org -S: Maintained -F: drivers/input/touchscreen/cyttsp* -F: include/linux/input/cyttsp.h +M: Javier Martinez Canillas +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/input/touchscreen/cyttsp* +F: include/linux/input/cyttsp.h DAMA SLAVE for AX.25 M: Joerg Reuter @@ -2273,7 +2270,7 @@ F: include/linux/device-mapper.h F: include/linux/dm-*.h DIOLAN U2C-12 I2C DRIVER -M: Guenter Roeck +M: Guenter Roeck L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/busses/i2c-diolan-u2c.c @@ -2933,13 +2930,6 @@ F: Documentation/power/freezing-of-tasks.txt F: include/linux/freezer.h F: kernel/freezer.c -FRONTSWAP API -M: Konrad Rzeszutek Wilk -L: linux-kernel@vger.kernel.org -S: Maintained -F: mm/frontswap.c -F: include/linux/frontswap.h - FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS M: David Howells L: linux-cachefs@redhat.com @@ -3148,7 +3138,7 @@ F: drivers/tty/hvc/ HARDWARE MONITORING M: Jean Delvare -M: Guenter Roeck +M: Guenter Roeck L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.org/ T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/ @@ -4106,8 +4096,6 @@ F: drivers/scsi/53c700* LED SUBSYSTEM M: Bryan Wu M: Richard Purdie -L: linux-leds@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git S: Maintained F: drivers/leds/ F: include/linux/leds.h @@ -4352,8 +4340,7 @@ MAC80211 M: Johannes Berg L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git S: Maintained F: Documentation/networking/mac80211-injection.txt F: include/net/mac80211.h @@ -4364,8 +4351,7 @@ M: Stefano Brivio M: Mattias Nissler L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git S: Maintained F: net/mac80211/rc80211_pid* @@ -4425,13 +4411,6 @@ S: Orphan F: drivers/video/matrox/matroxfb_* F: include/linux/matroxfb.h -MAX16065 HARDWARE MONITOR DRIVER -M: Guenter Roeck -L: lm-sensors@lm-sensors.org -S: Maintained -F: Documentation/hwmon/max16065 -F: drivers/hwmon/max16065.c - MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER M: "Hans J. Koch" L: lm-sensors@lm-sensors.org @@ -5170,7 +5149,7 @@ F: drivers/leds/leds-pca9532.c F: include/linux/leds-pca9532.h PCA9541 I2C BUS MASTER SELECTOR DRIVER -M: Guenter Roeck +M: Guenter Roeck L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/muxes/i2c-mux-pca9541.c @@ -5190,7 +5169,7 @@ S: Maintained F: drivers/firmware/pcdp.* PCI ERROR RECOVERY -M: Linas Vepstas +M: Linas Vepstas L: linux-pci@vger.kernel.org S: Supported F: Documentation/PCI/pci-error-recovery.txt @@ -5320,7 +5299,7 @@ F: drivers/video/fb-puv3.c F: drivers/rtc/rtc-puv3.c PMBUS HARDWARE MONITORING DRIVERS -M: Guenter Roeck +M: Guenter Roeck L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.org/ W: http://www.roeck-us.net/linux/drivers/ @@ -5358,7 +5337,7 @@ M: David Woodhouse T: git git://git.infradead.org/battery-2.6.git S: Maintained F: include/linux/power_supply.h -F: drivers/power/ +F: drivers/power/power_supply* PNP SUPPORT M: Adam Belay @@ -5716,9 +5695,6 @@ F: include/linux/remoteproc.h RFKILL M: Johannes Berg L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git S: Maintained F: Documentation/rfkill.txt F: net/rfkill/ @@ -7315,11 +7291,11 @@ F: Documentation/DocBook/uio-howto.tmpl F: drivers/uio/ F: include/linux/uio*.h -UTIL-LINUX PACKAGE +UTIL-LINUX-NG PACKAGE M: Karel Zak -L: util-linux@vger.kernel.org -W: http://en.wikipedia.org/wiki/Util-linux -T: git git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git +L: util-linux-ng@vger.kernel.org +W: http://kernel.org/~kzak/util-linux-ng/ +T: git git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git S: Maintained UVESAFB DRIVER diff --git a/trunk/Makefile b/trunk/Makefile index d845c2a1aa68..dda21c3efc7b 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 3 -PATCHLEVEL = 5 +PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = NAME = Saber-toothed Squirrel # *DOCUMENTATION* diff --git a/trunk/arch/alpha/include/asm/posix_types.h b/trunk/arch/alpha/include/asm/posix_types.h index 5a8a48320efe..24779fc95994 100644 --- a/trunk/arch/alpha/include/asm/posix_types.h +++ b/trunk/arch/alpha/include/asm/posix_types.h @@ -10,6 +10,9 @@ typedef unsigned int __kernel_ino_t; #define __kernel_ino_t __kernel_ino_t +typedef unsigned int __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ #include diff --git a/trunk/arch/alpha/kernel/signal.c b/trunk/arch/alpha/kernel/signal.c index a8c97d42ec8e..10ab2d74ecbb 100644 --- a/trunk/arch/alpha/kernel/signal.c +++ b/trunk/arch/alpha/kernel/signal.c @@ -226,6 +226,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, if (__get_user(set.sig[0], &sc->sc_mask)) goto give_sigsegv; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(sc, regs, sw)) @@ -260,6 +261,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto give_sigsegv; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) @@ -466,9 +468,12 @@ static inline void handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, struct pt_regs * regs, struct switch_stack *sw) { - sigset_t *oldset = sigmask_to_save(); + sigset_t *oldset = ¤t->blocked; int ret; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + if (ka->sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); else @@ -478,7 +483,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, force_sigsegv(sig, current); return; } - signal_delivered(sig, info, ka, regs, 0); + block_sigmask(ka, sig); + /* A signal was successfully delivered, and the + saved sigmask was stored on the signal frame, + and will be restored by sigreturn. So we can + simply clear the restore sigmask flag. */ + clear_thread_flag(TIF_RESTORE_SIGMASK); } static inline void @@ -562,7 +572,9 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, } /* If there's no signal to deliver, we just restore the saved mask. */ - restore_saved_sigmask(); + if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) + set_current_blocked(¤t->saved_sigmask); + if (single_stepping) ptrace_set_bpt(current); /* re-set breakpoint */ } @@ -578,5 +590,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index 84449dd8f031..b649c5904a4f 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -7,6 +7,7 @@ config ARM select HAVE_IDE if PCI || ISA || PCMCIA select HAVE_DMA_ATTRS select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7) + select CMA if (CPU_V6 || CPU_V6K || CPU_V7) select HAVE_MEMBLOCK select RTC_LIB select SYS_SUPPORTS_APM_EMULATION diff --git a/trunk/arch/arm/boot/dts/db8500.dtsi b/trunk/arch/arm/boot/dts/db8500.dtsi index 4ad5160018cb..881bc3987844 100644 --- a/trunk/arch/arm/boot/dts/db8500.dtsi +++ b/trunk/arch/arm/boot/dts/db8500.dtsi @@ -58,8 +58,6 @@ "st,nomadik-gpio"; reg = <0x8012e000 0x80>; interrupts = <0 119 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -71,8 +69,6 @@ "st,nomadik-gpio"; reg = <0x8012e080 0x80>; interrupts = <0 120 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -84,8 +80,6 @@ "st,nomadik-gpio"; reg = <0x8000e000 0x80>; interrupts = <0 121 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -97,8 +91,6 @@ "st,nomadik-gpio"; reg = <0x8000e080 0x80>; interrupts = <0 122 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -110,8 +102,6 @@ "st,nomadik-gpio"; reg = <0x8000e100 0x80>; interrupts = <0 123 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -123,8 +113,6 @@ "st,nomadik-gpio"; reg = <0x8000e180 0x80>; interrupts = <0 124 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -136,8 +124,6 @@ "st,nomadik-gpio"; reg = <0x8011e000 0x80>; interrupts = <0 125 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -149,8 +135,6 @@ "st,nomadik-gpio"; reg = <0x8011e080 0x80>; interrupts = <0 126 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; @@ -162,18 +146,12 @@ "st,nomadik-gpio"; reg = <0xa03fe000 0x80>; interrupts = <0 127 0x4>; - interrupt-controller; - #interrupt-cells = <2>; supports-sleepmode; gpio-controller; #gpio-cells = <2>; gpio-bank = <8>; }; - pinctrl { - compatible = "stericsson,nmk_pinctrl"; - }; - usb@a03e0000 { compatible = "stericsson,db8500-musb", "mentor,musb"; @@ -191,195 +169,20 @@ prcmu@80157000 { compatible = "stericsson,db8500-prcmu"; reg = <0x80157000 0x1000>; - interrupts = <0 47 0x4>; + interrupts = <46 47>; #address-cells = <1>; #size-cells = <1>; ranges; - prcmu-timer-4@80157450 { + prcmu-timer-4@80157450 { compatible = "stericsson,db8500-prcmu-timer-4"; reg = <0x80157450 0xC>; }; - db8500-prcmu-regulators { - compatible = "stericsson,db8500-prcmu-regulator"; - - // DB8500_REGULATOR_VAPE - db8500_vape_reg: db8500_vape { - regulator-name = "db8500-vape"; - regulator-always-on; - }; - - // DB8500_REGULATOR_VARM - db8500_varm_reg: db8500_varm { - regulator-name = "db8500-varm"; - }; - - // DB8500_REGULATOR_VMODEM - db8500_vmodem_reg: db8500_vmodem { - regulator-name = "db8500-vmodem"; - }; - - // DB8500_REGULATOR_VPLL - db8500_vpll_reg: db8500_vpll { - regulator-name = "db8500-vpll"; - }; - - // DB8500_REGULATOR_VSMPS1 - db8500_vsmps1_reg: db8500_vsmps1 { - regulator-name = "db8500-vsmps1"; - }; - - // DB8500_REGULATOR_VSMPS2 - db8500_vsmps2_reg: db8500_vsmps2 { - regulator-name = "db8500-vsmps2"; - }; - - // DB8500_REGULATOR_VSMPS3 - db8500_vsmps3_reg: db8500_vsmps3 { - regulator-name = "db8500-vsmps3"; - }; - - // DB8500_REGULATOR_VRF1 - db8500_vrf1_reg: db8500_vrf1 { - regulator-name = "db8500-vrf1"; - }; - - // DB8500_REGULATOR_SWITCH_SVAMMDSP - db8500_sva_mmdsp_reg: db8500_sva_mmdsp { - regulator-name = "db8500-sva-mmdsp"; - }; - - // DB8500_REGULATOR_SWITCH_SVAMMDSPRET - db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret { - regulator-name = "db8500-sva-mmdsp-ret"; - }; - - // DB8500_REGULATOR_SWITCH_SVAPIPE - db8500_sva_pipe_reg: db8500_sva_pipe { - regulator-name = "db8500_sva_pipe"; - }; - - // DB8500_REGULATOR_SWITCH_SIAMMDSP - db8500_sia_mmdsp_reg: db8500_sia_mmdsp { - regulator-name = "db8500_sia_mmdsp"; - }; - - // DB8500_REGULATOR_SWITCH_SIAMMDSPRET - db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret { - regulator-name = "db8500-sia-mmdsp-ret"; - }; - - // DB8500_REGULATOR_SWITCH_SIAPIPE - db8500_sia_pipe_reg: db8500_sia_pipe { - regulator-name = "db8500-sia-pipe"; - }; - - // DB8500_REGULATOR_SWITCH_SGA - db8500_sga_reg: db8500_sga { - regulator-name = "db8500-sga"; - vin-supply = <&db8500_vape_reg>; - }; - - // DB8500_REGULATOR_SWITCH_B2R2_MCDE - db8500_b2r2_mcde_reg: db8500_b2r2_mcde { - regulator-name = "db8500-b2r2-mcde"; - vin-supply = <&db8500_vape_reg>; - }; - - // DB8500_REGULATOR_SWITCH_ESRAM12 - db8500_esram12_reg: db8500_esram12 { - regulator-name = "db8500-esram12"; - }; - - // DB8500_REGULATOR_SWITCH_ESRAM12RET - db8500_esram12_ret_reg: db8500_esram12_ret { - regulator-name = "db8500-esram12-ret"; - }; - - // DB8500_REGULATOR_SWITCH_ESRAM34 - db8500_esram34_reg: db8500_esram34 { - regulator-name = "db8500-esram34"; - }; - - // DB8500_REGULATOR_SWITCH_ESRAM34RET - db8500_esram34_ret_reg: db8500_esram34_ret { - regulator-name = "db8500-esram34-ret"; - }; - }; - ab8500@5 { compatible = "stericsson,ab8500"; reg = <5>; /* mailbox 5 is i2c */ interrupts = <0 40 0x4>; - - ab8500-regulators { - compatible = "stericsson,ab8500-regulator"; - - // supplies to the display/camera - ab8500_ldo_aux1_reg: ab8500_ldo_aux1 { - regulator-name = "V-DISPLAY"; - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2900000>; - regulator-boot-on; - /* BUG: If turned off MMC will be affected. */ - regulator-always-on; - }; - - // supplies to the on-board eMMC - ab8500_ldo_aux2_reg: ab8500_ldo_aux2 { - regulator-name = "V-eMMC1"; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <3300000>; - }; - - // supply for VAUX3; SDcard slots - ab8500_ldo_aux3_reg: ab8500_ldo_aux3 { - regulator-name = "V-MMC-SD"; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <3300000>; - }; - - // supply for v-intcore12; VINTCORE12 LDO - ab8500_ldo_initcore_reg: ab8500_ldo_initcore { - regulator-name = "V-INTCORE"; - }; - - // supply for tvout; gpadc; TVOUT LDO - ab8500_ldo_tvout_reg: ab8500_ldo_tvout { - regulator-name = "V-TVOUT"; - }; - - // supply for ab8500-usb; USB LDO - ab8500_ldo_usb_reg: ab8500_ldo_usb { - regulator-name = "dummy"; - }; - - // supply for ab8500-vaudio; VAUDIO LDO - ab8500_ldo_audio_reg: ab8500_ldo_audio { - regulator-name = "V-AUD"; - }; - - // supply for v-anamic1 VAMic1-LDO - ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 { - regulator-name = "V-AMIC1"; - }; - - // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1 - ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 { - regulator-name = "V-AMIC2"; - }; - - // supply for v-dmic; VDMIC LDO - ab8500_ldo_dmic_reg: ab8500_ldo_dmic { - regulator-name = "V-DMIC"; - }; - - // supply for U8500 CSI/DSI; VANA LDO - ab8500_ldo_ana_reg: ab8500_ldo_ana { - regulator-name = "V-CSI/DSI"; - }; - }; }; }; @@ -432,8 +235,7 @@ status = "disabled"; // Add one of these for each child device - cs-gpios = <&gpio0 31 0x4 &gpio4 14 0x4 &gpio4 16 0x4 - &gpio6 22 0x4 &gpio7 0 0x4>; + cs-gpios = <&gpio0 31 &gpio4 14 &gpio4 16 &gpio6 22 &gpio7 0>; }; diff --git a/trunk/arch/arm/boot/dts/imx27.dtsi b/trunk/arch/arm/boot/dts/imx27.dtsi index 386c769c38d1..2b1a166d41f9 100644 --- a/trunk/arch/arm/boot/dts/imx27.dtsi +++ b/trunk/arch/arm/boot/dts/imx27.dtsi @@ -213,14 +213,5 @@ status = "disabled"; }; }; - nand@d8000000 { - #address-cells = <1>; - #size-cells = <1>; - - compatible = "fsl,imx27-nand"; - reg = <0xd8000000 0x1000>; - interrupts = <29>; - status = "disabled"; - }; }; }; diff --git a/trunk/arch/arm/boot/dts/snowball.dts b/trunk/arch/arm/boot/dts/snowball.dts index ec3c33975110..d99dc04f0d91 100644 --- a/trunk/arch/arm/boot/dts/snowball.dts +++ b/trunk/arch/arm/boot/dts/snowball.dts @@ -20,16 +20,6 @@ reg = <0x00000000 0x20000000>; }; - en_3v3_reg: en_3v3 { - compatible = "regulator-fixed"; - regulator-name = "en-3v3-fixed-supply"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpios = <&gpio0 26 0x4>; // 26 - startup-delay-us = <5000>; - enable-active-high; - }; - gpio_keys { compatible = "gpio-keys"; #address-cells = <1>; @@ -40,35 +30,35 @@ wakeup = <1>; linux,code = <2>; label = "userpb"; - gpios = <&gpio1 0 0x4>; + gpios = <&gpio1 0 0>; }; button@2 { debounce_interval = <50>; wakeup = <1>; linux,code = <3>; label = "extkb1"; - gpios = <&gpio4 23 0x4>; + gpios = <&gpio4 23 0>; }; button@3 { debounce_interval = <50>; wakeup = <1>; linux,code = <4>; label = "extkb2"; - gpios = <&gpio4 24 0x4>; + gpios = <&gpio4 24 0>; }; button@4 { debounce_interval = <50>; wakeup = <1>; linux,code = <5>; label = "extkb3"; - gpios = <&gpio5 1 0x4>; + gpios = <&gpio5 1 0>; }; button@5 { debounce_interval = <50>; wakeup = <1>; linux,code = <6>; label = "extkb4"; - gpios = <&gpio5 2 0x4>; + gpios = <&gpio5 2 0>; }; }; @@ -76,11 +66,12 @@ compatible = "gpio-leds"; used-led { label = "user_led"; - gpios = <&gpio4 14 0x4>; + gpios = <&gpio4 14>; }; }; soc-u9500 { + external-bus@50000000 { status = "okay"; @@ -89,9 +80,6 @@ reg = <0 0x10000>; interrupts = <12 0x1>; interrupt-parent = <&gpio4>; - vdd33a-supply = <&en_3v3_reg>; - vddvario-supply = <&db8500_vape_reg>; - reg-shift = <1>; reg-io-width = <2>; @@ -103,13 +91,11 @@ sdi@80126000 { status = "enabled"; - vmmc-supply = <&ab8500_ldo_aux3_reg>; - cd-gpios = <&gpio6 26 0x4>; // 218 + cd-gpios = <&gpio6 26>; }; sdi@80114000 { status = "enabled"; - vmmc-supply = <&ab8500_ldo_aux2_reg>; }; uart@80120000 { @@ -128,7 +114,7 @@ tc3589x@42 { //compatible = "tc3589x"; reg = <0x42>; - gpios = <&gpio6 25 0x4>; + interrupts = <25>; interrupt-parent = <&gpio6>; }; tps61052@33 { diff --git a/trunk/arch/arm/common/dmabounce.c b/trunk/arch/arm/common/dmabounce.c index aa07f5938f05..9d7eb530f95f 100644 --- a/trunk/arch/arm/common/dmabounce.c +++ b/trunk/arch/arm/common/dmabounce.c @@ -366,8 +366,8 @@ static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, struct safe_buffer *buf; unsigned long off; - dev_dbg(dev, "%s(dma=%#x,sz=%zx,dir=%x)\n", - __func__, addr, sz, dir); + dev_dbg(dev, "%s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n", + __func__, addr, off, sz, dir); buf = find_safe_buffer_dev(dev, addr, __func__); if (!buf) @@ -377,8 +377,8 @@ static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, BUG_ON(buf->direction != dir); - dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x off=%#lx) mapped to %p (dma=%#x)\n", - __func__, buf->ptr, virt_to_dma(dev, buf->ptr), off, + dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n", + __func__, buf->ptr, virt_to_dma(dev, buf->ptr), buf->safe, buf->safe_dma_addr); DO_STATS(dev->archdata.dmabounce->bounce_count++); @@ -406,8 +406,8 @@ static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr, struct safe_buffer *buf; unsigned long off; - dev_dbg(dev, "%s(dma=%#x,sz=%zx,dir=%x)\n", - __func__, addr, sz, dir); + dev_dbg(dev, "%s(dma=%#x,off=%#lx,sz=%zx,dir=%x)\n", + __func__, addr, off, sz, dir); buf = find_safe_buffer_dev(dev, addr, __func__); if (!buf) @@ -417,8 +417,8 @@ static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr, BUG_ON(buf->direction != dir); - dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x off=%#lx) mapped to %p (dma=%#x)\n", - __func__, buf->ptr, virt_to_dma(dev, buf->ptr), off, + dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n", + __func__, buf->ptr, virt_to_dma(dev, buf->ptr), buf->safe, buf->safe_dma_addr); DO_STATS(dev->archdata.dmabounce->bounce_count++); diff --git a/trunk/arch/arm/configs/u8500_defconfig b/trunk/arch/arm/configs/u8500_defconfig index 2d4f661d1cf6..7e84f453e8a6 100644 --- a/trunk/arch/arm/configs/u8500_defconfig +++ b/trunk/arch/arm/configs/u8500_defconfig @@ -75,7 +75,6 @@ CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y CONFIG_REGULATOR=y CONFIG_REGULATOR_AB8500=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y # CONFIG_HID_SUPPORT is not set CONFIG_USB_GADGET=y CONFIG_AB8500_USB=y diff --git a/trunk/arch/arm/include/asm/posix_types.h b/trunk/arch/arm/include/asm/posix_types.h index d2de9cbbcd9b..efdf99045d87 100644 --- a/trunk/arch/arm/include/asm/posix_types.h +++ b/trunk/arch/arm/include/asm/posix_types.h @@ -22,6 +22,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/arm/kernel/signal.c b/trunk/arch/arm/kernel/signal.c index fd2392a17ac1..17fc36c41cff 100644 --- a/trunk/arch/arm/kernel/signal.c +++ b/trunk/arch/arm/kernel/signal.c @@ -22,6 +22,8 @@ #include "signal.h" +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* * For ARM syscalls, we encode the syscall number into the instruction. */ @@ -208,8 +210,10 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) int err; err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); - if (err == 0) + if (err == 0) { + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); + } __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); @@ -524,13 +528,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, /* * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, struct pt_regs *regs) + siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs) { struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; - sigset_t *oldset = sigmask_to_save(); int usig = sig; int ret; @@ -555,9 +559,17 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, if (ret != 0) { force_sigsegv(sig, tsk); - return; + return ret; } - signal_delivered(sig, info, ka, regs, 0); + + /* + * Block the signal if we were successful. + */ + block_sigmask(ka, sig); + + tracehook_signal_handler(sig, info, ka, regs, 0); + + return 0; } /* @@ -605,6 +617,8 @@ static void do_signal(struct pt_regs *regs, int syscall) */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { + sigset_t *oldset; + /* * Depending on the signal settings we may need to revert the * decision to restart the system call. But skip this if a @@ -621,7 +635,20 @@ static void do_signal(struct pt_regs *regs, int syscall) clear_thread_flag(TIF_SYSCALL_RESTARTSYS); } - handle_signal(signr, &ka, &info, regs); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } return; } @@ -636,7 +663,11 @@ static void do_signal(struct pt_regs *regs, int syscall) set_thread_flag(TIF_SYSCALL_RESTARTSYS); } - restore_saved_sigmask(); + /* If there's no signal to deliver, we just put the saved sigmask + * back. + */ + if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) + set_current_blocked(¤t->saved_sigmask); } asmlinkage void @@ -648,5 +679,7 @@ do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) if (thread_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/arm/kernel/smp.c b/trunk/arch/arm/kernel/smp.c index 2c7217d971db..b735521a4a54 100644 --- a/trunk/arch/arm/kernel/smp.c +++ b/trunk/arch/arm/kernel/smp.c @@ -109,6 +109,7 @@ static void percpu_timer_stop(void); int __cpu_disable(void) { unsigned int cpu = smp_processor_id(); + struct task_struct *p; int ret; ret = platform_cpu_disable(cpu); @@ -138,7 +139,12 @@ int __cpu_disable(void) flush_cache_all(); local_flush_tlb_all(); - clear_tasks_mm_cpumask(cpu); + read_lock(&tasklist_lock); + for_each_process(p) { + if (p->mm) + cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); + } + read_unlock(&tasklist_lock); return 0; } diff --git a/trunk/arch/arm/mach-ep93xx/snappercl15.c b/trunk/arch/arm/mach-ep93xx/snappercl15.c index 01abd3516a77..eb282378fa78 100644 --- a/trunk/arch/arm/mach-ep93xx/snappercl15.c +++ b/trunk/arch/arm/mach-ep93xx/snappercl15.c @@ -82,6 +82,8 @@ static int snappercl15_nand_dev_ready(struct mtd_info *mtd) return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY); } +static const char *snappercl15_nand_part_probes[] = {"cmdlinepart", NULL}; + static struct mtd_partition snappercl15_nand_parts[] = { { .name = "Kernel", @@ -98,8 +100,10 @@ static struct mtd_partition snappercl15_nand_parts[] = { static struct platform_nand_data snappercl15_nand_data = { .chip = { .nr_chips = 1, + .part_probe_types = snappercl15_nand_part_probes, .partitions = snappercl15_nand_parts, .nr_partitions = ARRAY_SIZE(snappercl15_nand_parts), + .options = NAND_NO_AUTOINCR, .chip_delay = 25, }, .ctrl = { diff --git a/trunk/arch/arm/mach-ep93xx/ts72xx.c b/trunk/arch/arm/mach-ep93xx/ts72xx.c index 75cab2d7ec73..d4ef339d961e 100644 --- a/trunk/arch/arm/mach-ep93xx/ts72xx.c +++ b/trunk/arch/arm/mach-ep93xx/ts72xx.c @@ -105,6 +105,8 @@ static int ts72xx_nand_device_ready(struct mtd_info *mtd) return !!(__raw_readb(addr) & 0x20); } +static const char *ts72xx_nand_part_probes[] = { "cmdlinepart", NULL }; + #define TS72XX_BOOTROM_PART_SIZE (SZ_16K) #define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M) @@ -132,6 +134,7 @@ static struct platform_nand_data ts72xx_nand_data = { .nr_chips = 1, .chip_offset = 0, .chip_delay = 15, + .part_probe_types = ts72xx_nand_part_probes, .partitions = ts72xx_nand_parts, .nr_partitions = ARRAY_SIZE(ts72xx_nand_parts), }, diff --git a/trunk/arch/arm/mach-exynos/mach-nuri.c b/trunk/arch/arm/mach-exynos/mach-nuri.c index 656f8fc9addd..972983e392bc 100644 --- a/trunk/arch/arm/mach-exynos/mach-nuri.c +++ b/trunk/arch/arm/mach-exynos/mach-nuri.c @@ -237,29 +237,25 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { #else /* Frame Buffer */ static struct s3c_fb_pd_win nuri_fb_win0 = { + .win_mode = { + .left_margin = 64, + .right_margin = 16, + .upper_margin = 64, + .lower_margin = 1, + .hsync_len = 48, + .vsync_len = 3, + .xres = 1024, + .yres = 600, + .refresh = 60, + }, .max_bpp = 24, .default_bpp = 16, - .xres = 1024, - .yres = 600, .virtual_x = 1024, .virtual_y = 2 * 600, }; -static struct fb_videomode nuri_lcd_timing = { - .left_margin = 64, - .right_margin = 16, - .upper_margin = 64, - .lower_margin = 1, - .hsync_len = 48, - .vsync_len = 3, - .xres = 1024, - .yres = 600, - .refresh = 60, -}; - static struct s3c_fb_platdata nuri_fb_pdata __initdata = { .win[0] = &nuri_fb_win0, - .vtiming = &nuri_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-exynos/mach-origen.c b/trunk/arch/arm/mach-exynos/mach-origen.c index f5572be9d7bf..a7f7fd567dde 100644 --- a/trunk/arch/arm/mach-exynos/mach-origen.c +++ b/trunk/arch/arm/mach-exynos/mach-origen.c @@ -604,28 +604,24 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { }; #else static struct s3c_fb_pd_win origen_fb_win0 = { - .xres = 1024, - .yres = 600, + .win_mode = { + .left_margin = 64, + .right_margin = 16, + .upper_margin = 64, + .lower_margin = 16, + .hsync_len = 48, + .vsync_len = 3, + .xres = 1024, + .yres = 600, + }, .max_bpp = 32, .default_bpp = 24, .virtual_x = 1024, .virtual_y = 2 * 600, }; -static struct fb_videomode origen_lcd_timing = { - .left_margin = 64, - .right_margin = 16, - .upper_margin = 64, - .lower_margin = 16, - .hsync_len = 48, - .vsync_len = 3, - .xres = 1024, - .yres = 600, -}; - static struct s3c_fb_platdata origen_lcd_pdata __initdata = { .win[0] = &origen_fb_win0, - .vtiming = &origen_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | VIDCON1_INV_VCLK, diff --git a/trunk/arch/arm/mach-exynos/mach-smdkv310.c b/trunk/arch/arm/mach-exynos/mach-smdkv310.c index 262e9e446a96..70df1a0c2118 100644 --- a/trunk/arch/arm/mach-exynos/mach-smdkv310.c +++ b/trunk/arch/arm/mach-exynos/mach-smdkv310.c @@ -178,26 +178,22 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { }; #else static struct s3c_fb_pd_win smdkv310_fb_win0 = { - .max_bpp = 32, - .default_bpp = 24, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdkv310_lcd_timing = { - .left_margin = 13, - .right_margin = 8, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, + .win_mode = { + .left_margin = 13, + .right_margin = 8, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 24, }; static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = { .win[0] = &smdkv310_fb_win0, - .vtiming = &smdkv310_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = exynos4_fimd0_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-exynos/mach-universal_c210.c b/trunk/arch/arm/mach-exynos/mach-universal_c210.c index cd92fa86ba41..083b44de9c10 100644 --- a/trunk/arch/arm/mach-exynos/mach-universal_c210.c +++ b/trunk/arch/arm/mach-exynos/mach-universal_c210.c @@ -843,29 +843,25 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = { #else /* Frame Buffer */ static struct s3c_fb_pd_win universal_fb_win0 = { + .win_mode = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 2, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 1, + .xres = 480, + .yres = 800, + .refresh = 55, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 480, - .yres = 800, .virtual_x = 480, .virtual_y = 2 * 800, }; -static struct fb_videomode universal_lcd_timing = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 2, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 1, - .xres = 480, - .yres = 800, - .refresh = 55, -}; - static struct s3c_fb_platdata universal_lcd_pdata __initdata = { .win[0] = &universal_fb_win0, - .vtiming = &universal_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN diff --git a/trunk/arch/arm/mach-imx/imx27-dt.c b/trunk/arch/arm/mach-imx/imx27-dt.c index eee0cc8d92a4..ed38d03c61f2 100644 --- a/trunk/arch/arm/mach-imx/imx27-dt.c +++ b/trunk/arch/arm/mach-imx/imx27-dt.c @@ -29,7 +29,6 @@ static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI2_BASE_ADDR, "imx27-cspi.1", NULL), OF_DEV_AUXDATA("fsl,imx27-cspi", MX27_CSPI3_BASE_ADDR, "imx27-cspi.2", NULL), OF_DEV_AUXDATA("fsl,imx27-wdt", MX27_WDOG_BASE_ADDR, "imx2-wdt.0", NULL), - OF_DEV_AUXDATA("fsl,imx27-nand", MX27_NFC_BASE_ADDR, "mxc_nand.0", NULL), { /* sentinel */ } }; diff --git a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c index 108a9d3f382d..3d742aee1773 100644 --- a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -60,6 +60,8 @@ static struct platform_device ixdp425_flash = { #if defined(CONFIG_MTD_NAND_PLATFORM) || \ defined(CONFIG_MTD_NAND_PLATFORM_MODULE) +const char *part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition ixdp425_partitions[] = { { .name = "ixp400 NAND FS 0", @@ -98,6 +100,8 @@ static struct platform_nand_data ixdp425_flash_nand_data = { .chip = { .nr_chips = 1, .chip_delay = 30, + .options = NAND_NO_AUTOINCR, + .part_probe_types = part_probes, .partitions = ixdp425_partitions, .nr_partitions = ARRAY_SIZE(ixdp425_partitions), }, diff --git a/trunk/arch/arm/mach-nomadik/board-nhk8815.c b/trunk/arch/arm/mach-nomadik/board-nhk8815.c index 2e8d3e176bc7..58cacafcf662 100644 --- a/trunk/arch/arm/mach-nomadik/board-nhk8815.c +++ b/trunk/arch/arm/mach-nomadik/board-nhk8815.c @@ -111,7 +111,7 @@ static struct nomadik_nand_platform_data nhk8815_nand_data = { .parts = nhk8815_partitions, .nparts = ARRAY_SIZE(nhk8815_partitions), .options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING \ - | NAND_NO_READRDY, + | NAND_NO_READRDY | NAND_NO_AUTOINCR, .init = nhk8815_nand_init, }; diff --git a/trunk/arch/arm/mach-omap1/board-fsample.c b/trunk/arch/arm/mach-omap1/board-fsample.c index 6872f3fd400f..c7364fdbda05 100644 --- a/trunk/arch/arm/mach-omap1/board-fsample.c +++ b/trunk/arch/arm/mach-omap1/board-fsample.c @@ -192,11 +192,14 @@ static int nand_dev_ready(struct mtd_info *mtd) return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN); } +static const char *part_probes[] = { "cmdlinepart", NULL }; + static struct platform_nand_data nand_data = { .chip = { .nr_chips = 1, .chip_offset = 0, .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, }, .ctrl = { .cmd_ctrl = omap1_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-omap1/board-h2.c b/trunk/arch/arm/mach-omap1/board-h2.c index a28e989a63f4..7e503686f7af 100644 --- a/trunk/arch/arm/mach-omap1/board-h2.c +++ b/trunk/arch/arm/mach-omap1/board-h2.c @@ -186,6 +186,8 @@ static int h2_nand_dev_ready(struct mtd_info *mtd) return gpio_get_value(H2_NAND_RB_GPIO_PIN); } +static const char *h2_part_probes[] = { "cmdlinepart", NULL }; + static struct platform_nand_data h2_nand_platdata = { .chip = { .nr_chips = 1, @@ -193,6 +195,7 @@ static struct platform_nand_data h2_nand_platdata = { .nr_partitions = ARRAY_SIZE(h2_nand_partitions), .partitions = h2_nand_partitions, .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = h2_part_probes, }, .ctrl = { .cmd_ctrl = omap1_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-omap1/board-h3.c b/trunk/arch/arm/mach-omap1/board-h3.c index 108a8640fc6f..9fb03f189d93 100644 --- a/trunk/arch/arm/mach-omap1/board-h3.c +++ b/trunk/arch/arm/mach-omap1/board-h3.c @@ -188,6 +188,8 @@ static int nand_dev_ready(struct mtd_info *mtd) return gpio_get_value(H3_NAND_RB_GPIO_PIN); } +static const char *part_probes[] = { "cmdlinepart", NULL }; + static struct platform_nand_data nand_platdata = { .chip = { .nr_chips = 1, @@ -195,6 +197,7 @@ static struct platform_nand_data nand_platdata = { .nr_partitions = ARRAY_SIZE(nand_partitions), .partitions = nand_partitions, .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, }, .ctrl = { .cmd_ctrl = omap1_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-omap1/board-perseus2.c b/trunk/arch/arm/mach-omap1/board-perseus2.c index 703d55ecffe2..f2cb24387c22 100644 --- a/trunk/arch/arm/mach-omap1/board-perseus2.c +++ b/trunk/arch/arm/mach-omap1/board-perseus2.c @@ -150,11 +150,14 @@ static int nand_dev_ready(struct mtd_info *mtd) return gpio_get_value(P2_NAND_RB_GPIO_PIN); } +static const char *part_probes[] = { "cmdlinepart", NULL }; + static struct platform_nand_data nand_data = { .chip = { .nr_chips = 1, .chip_offset = 0, .options = NAND_SAMSUNG_LP_OPTIONS, + .part_probe_types = part_probes, }, .ctrl = { .cmd_ctrl = omap1_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-omap2/display.c b/trunk/arch/arm/mach-omap2/display.c index 5fb47a14f4ba..db5a88a36c63 100644 --- a/trunk/arch/arm/mach-omap2/display.c +++ b/trunk/arch/arm/mach-omap2/display.c @@ -180,133 +180,16 @@ static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask) omap4_dsi_mux_pads(dsi_id, 0); } -static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput) -{ - return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, tput); -} - -static struct platform_device *create_dss_pdev(const char *pdev_name, - int pdev_id, const char *oh_name, void *pdata, int pdata_len, - struct platform_device *parent) -{ - struct platform_device *pdev; - struct omap_device *od; - struct omap_hwmod *ohs[1]; - struct omap_hwmod *oh; - int r; - - oh = omap_hwmod_lookup(oh_name); - if (!oh) { - pr_err("Could not look up %s\n", oh_name); - r = -ENODEV; - goto err; - } - - pdev = platform_device_alloc(pdev_name, pdev_id); - if (!pdev) { - pr_err("Could not create pdev for %s\n", pdev_name); - r = -ENOMEM; - goto err; - } - - if (parent != NULL) - pdev->dev.parent = &parent->dev; - - if (pdev->id != -1) - dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); - else - dev_set_name(&pdev->dev, "%s", pdev->name); - - ohs[0] = oh; - od = omap_device_alloc(pdev, ohs, 1, NULL, 0); - if (!od) { - pr_err("Could not alloc omap_device for %s\n", pdev_name); - r = -ENOMEM; - goto err; - } - - r = platform_device_add_data(pdev, pdata, pdata_len); - if (r) { - pr_err("Could not set pdata for %s\n", pdev_name); - goto err; - } - - r = omap_device_register(pdev); - if (r) { - pr_err("Could not register omap_device for %s\n", pdev_name); - goto err; - } - - return pdev; - -err: - return ERR_PTR(r); -} - -static struct platform_device *create_simple_dss_pdev(const char *pdev_name, - int pdev_id, void *pdata, int pdata_len, - struct platform_device *parent) -{ - struct platform_device *pdev; - int r; - - pdev = platform_device_alloc(pdev_name, pdev_id); - if (!pdev) { - pr_err("Could not create pdev for %s\n", pdev_name); - r = -ENOMEM; - goto err; - } - - if (parent != NULL) - pdev->dev.parent = &parent->dev; - - if (pdev->id != -1) - dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); - else - dev_set_name(&pdev->dev, "%s", pdev->name); - - r = platform_device_add_data(pdev, pdata, pdata_len); - if (r) { - pr_err("Could not set pdata for %s\n", pdev_name); - goto err; - } - - r = platform_device_add(pdev); - if (r) { - pr_err("Could not register platform_device for %s\n", pdev_name); - goto err; - } - - return pdev; - -err: - return ERR_PTR(r); -} - int __init omap_display_init(struct omap_dss_board_info *board_data) { int r = 0; + struct omap_hwmod *oh; struct platform_device *pdev; int i, oh_count; + struct omap_display_platform_data pdata; const struct omap_dss_hwmod_data *curr_dss_hwmod; - struct platform_device *dss_pdev; - - /* create omapdss device */ - - board_data->dsi_enable_pads = omap_dsi_enable_pads; - board_data->dsi_disable_pads = omap_dsi_disable_pads; - board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; - board_data->set_min_bus_tput = omap_dss_set_min_bus_tput; - - omap_display_device.dev.platform_data = board_data; - - r = platform_device_register(&omap_display_device); - if (r < 0) { - pr_err("Unable to register omapdss device\n"); - return r; - } - /* create devices for dss hwmods */ + memset(&pdata, 0, sizeof(pdata)); if (cpu_is_omap24xx()) { curr_dss_hwmod = omap2_dss_hwmod_data; @@ -319,58 +202,39 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); } - /* - * First create the pdev for dss_core, which is used as a parent device - * by the other dss pdevs. Note: dss_core has to be the first item in - * the hwmod list. - */ - dss_pdev = create_dss_pdev(curr_dss_hwmod[0].dev_name, - curr_dss_hwmod[0].id, - curr_dss_hwmod[0].oh_name, - board_data, sizeof(*board_data), - NULL); - - if (IS_ERR(dss_pdev)) { - pr_err("Could not build omap_device for %s\n", - curr_dss_hwmod[0].oh_name); - - return PTR_ERR(dss_pdev); - } - - for (i = 1; i < oh_count; i++) { - pdev = create_dss_pdev(curr_dss_hwmod[i].dev_name, - curr_dss_hwmod[i].id, - curr_dss_hwmod[i].oh_name, - board_data, sizeof(*board_data), - dss_pdev); - - if (IS_ERR(pdev)) { - pr_err("Could not build omap_device for %s\n", - curr_dss_hwmod[i].oh_name); - - return PTR_ERR(pdev); + if (board_data->dsi_enable_pads == NULL) + board_data->dsi_enable_pads = omap_dsi_enable_pads; + if (board_data->dsi_disable_pads == NULL) + board_data->dsi_disable_pads = omap_dsi_disable_pads; + + pdata.board_data = board_data; + pdata.board_data->get_context_loss_count = + omap_pm_get_dev_context_loss_count; + + for (i = 0; i < oh_count; i++) { + oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name); + if (!oh) { + pr_err("Could not look up %s\n", + curr_dss_hwmod[i].oh_name); + return -ENODEV; } - } - /* Create devices for DPI and SDI */ + pdev = omap_device_build(curr_dss_hwmod[i].dev_name, + curr_dss_hwmod[i].id, oh, &pdata, + sizeof(struct omap_display_platform_data), + NULL, 0, 0); - pdev = create_simple_dss_pdev("omapdss_dpi", -1, - board_data, sizeof(*board_data), dss_pdev); - if (IS_ERR(pdev)) { - pr_err("Could not build platform_device for omapdss_dpi\n"); - return PTR_ERR(pdev); + if (WARN((IS_ERR(pdev)), "Could not build omap_device for %s\n", + curr_dss_hwmod[i].oh_name)) + return -ENODEV; } + omap_display_device.dev.platform_data = board_data; - if (cpu_is_omap34xx()) { - pdev = create_simple_dss_pdev("omapdss_sdi", -1, - board_data, sizeof(*board_data), dss_pdev); - if (IS_ERR(pdev)) { - pr_err("Could not build platform_device for omapdss_sdi\n"); - return PTR_ERR(pdev); - } - } + r = platform_device_register(&omap_display_device); + if (r < 0) + printk(KERN_ERR "Unable to register OMAP-Display device\n"); - return 0; + return r; } static void dispc_disable_outputs(void) diff --git a/trunk/arch/arm/mach-omap2/gpmc.c b/trunk/arch/arm/mach-omap2/gpmc.c index 2286410671e7..46b09dae770e 100644 --- a/trunk/arch/arm/mach-omap2/gpmc.c +++ b/trunk/arch/arm/mach-omap2/gpmc.c @@ -49,7 +49,6 @@ #define GPMC_ECC_CONTROL 0x1f8 #define GPMC_ECC_SIZE_CONFIG 0x1fc #define GPMC_ECC1_RESULT 0x200 -#define GPMC_ECC_BCH_RESULT_0 0x240 /* not available on OMAP2 */ /* GPMC ECC control settings */ #define GPMC_ECC_CTRL_ECCCLEAR 0x100 @@ -936,186 +935,3 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) return 0; } EXPORT_SYMBOL_GPL(gpmc_calculate_ecc); - -#ifdef CONFIG_ARCH_OMAP3 - -/** - * gpmc_init_hwecc_bch - initialize hardware BCH ecc functionality - * @cs: chip select number - * @nsectors: how many 512-byte sectors to process - * @nerrors: how many errors to correct per sector (4 or 8) - * - * This function must be executed before any call to gpmc_enable_hwecc_bch. - */ -int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors) -{ - /* check if ecc module is in use */ - if (gpmc_ecc_used != -EINVAL) - return -EINVAL; - - /* support only OMAP3 class */ - if (!cpu_is_omap34xx()) { - printk(KERN_ERR "BCH ecc is not supported on this CPU\n"); - return -EINVAL; - } - - /* - * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1. - * Other chips may be added if confirmed to work. - */ - if ((nerrors == 4) && - (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) { - printk(KERN_ERR "BCH 4-bit mode is not supported on this CPU\n"); - return -EINVAL; - } - - /* sanity check */ - if (nsectors > 8) { - printk(KERN_ERR "BCH cannot process %d sectors (max is 8)\n", - nsectors); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_init_hwecc_bch); - -/** - * gpmc_enable_hwecc_bch - enable hardware BCH ecc functionality - * @cs: chip select number - * @mode: read/write mode - * @dev_width: device bus width(1 for x16, 0 for x8) - * @nsectors: how many 512-byte sectors to process - * @nerrors: how many errors to correct per sector (4 or 8) - */ -int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors, - int nerrors) -{ - unsigned int val; - - /* check if ecc module is in use */ - if (gpmc_ecc_used != -EINVAL) - return -EINVAL; - - gpmc_ecc_used = cs; - - /* clear ecc and enable bits */ - gpmc_write_reg(GPMC_ECC_CONTROL, 0x1); - - /* - * When using BCH, sector size is hardcoded to 512 bytes. - * Here we are using wrapping mode 6 both for reading and writing, with: - * size0 = 0 (no additional protected byte in spare area) - * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) - */ - gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (32 << 22) | (0 << 12)); - - /* BCH configuration */ - val = ((1 << 16) | /* enable BCH */ - (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ - (0x06 << 8) | /* wrap mode = 6 */ - (dev_width << 7) | /* bus width */ - (((nsectors-1) & 0x7) << 4) | /* number of sectors */ - (cs << 1) | /* ECC CS */ - (0x1)); /* enable ECC */ - - gpmc_write_reg(GPMC_ECC_CONFIG, val); - gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_enable_hwecc_bch); - -/** - * gpmc_calculate_ecc_bch4 - Generate 7 ecc bytes per sector of 512 data bytes - * @cs: chip select number - * @dat: The pointer to data on which ecc is computed - * @ecc: The ecc output buffer - */ -int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc) -{ - int i; - unsigned long nsectors, reg, val1, val2; - - if (gpmc_ecc_used != cs) - return -EINVAL; - - nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; - - for (i = 0; i < nsectors; i++) { - - reg = GPMC_ECC_BCH_RESULT_0 + 16*i; - - /* Read hw-computed remainder */ - val1 = gpmc_read_reg(reg + 0); - val2 = gpmc_read_reg(reg + 4); - - /* - * Add constant polynomial to remainder, in order to get an ecc - * sequence of 0xFFs for a buffer filled with 0xFFs; and - * left-justify the resulting polynomial. - */ - *ecc++ = 0x28 ^ ((val2 >> 12) & 0xFF); - *ecc++ = 0x13 ^ ((val2 >> 4) & 0xFF); - *ecc++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); - *ecc++ = 0x39 ^ ((val1 >> 20) & 0xFF); - *ecc++ = 0x96 ^ ((val1 >> 12) & 0xFF); - *ecc++ = 0xac ^ ((val1 >> 4) & 0xFF); - *ecc++ = 0x7f ^ ((val1 & 0xF) << 4); - } - - gpmc_ecc_used = -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch4); - -/** - * gpmc_calculate_ecc_bch8 - Generate 13 ecc bytes per block of 512 data bytes - * @cs: chip select number - * @dat: The pointer to data on which ecc is computed - * @ecc: The ecc output buffer - */ -int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc) -{ - int i; - unsigned long nsectors, reg, val1, val2, val3, val4; - - if (gpmc_ecc_used != cs) - return -EINVAL; - - nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1; - - for (i = 0; i < nsectors; i++) { - - reg = GPMC_ECC_BCH_RESULT_0 + 16*i; - - /* Read hw-computed remainder */ - val1 = gpmc_read_reg(reg + 0); - val2 = gpmc_read_reg(reg + 4); - val3 = gpmc_read_reg(reg + 8); - val4 = gpmc_read_reg(reg + 12); - - /* - * Add constant polynomial to remainder, in order to get an ecc - * sequence of 0xFFs for a buffer filled with 0xFFs. - */ - *ecc++ = 0xef ^ (val4 & 0xFF); - *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF); - *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF); - *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF); - *ecc++ = 0xed ^ (val3 & 0xFF); - *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF); - *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF); - *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF); - *ecc++ = 0x97 ^ (val2 & 0xFF); - *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF); - *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF); - *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF); - *ecc++ = 0xb5 ^ (val1 & 0xFF); - } - - gpmc_ecc_used = -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch8); - -#endif /* CONFIG_ARCH_OMAP3 */ diff --git a/trunk/arch/arm/mach-orion5x/ts78xx-setup.c b/trunk/arch/arm/mach-orion5x/ts78xx-setup.c index b4203277f3cd..a74f3cf54cc5 100644 --- a/trunk/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/trunk/arch/arm/mach-orion5x/ts78xx-setup.c @@ -251,6 +251,8 @@ static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd, readsb(io_base, buf, len); } +const char *ts_nand_part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition ts78xx_ts_nand_parts[] = { { .name = "mbr", @@ -275,6 +277,7 @@ static struct mtd_partition ts78xx_ts_nand_parts[] = { static struct platform_nand_data ts78xx_ts_nand_data = { .chip = { .nr_chips = 1, + .part_probe_types = ts_nand_part_probes, .partitions = ts78xx_ts_nand_parts, .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), .chip_delay = 15, diff --git a/trunk/arch/arm/mach-pxa/balloon3.c b/trunk/arch/arm/mach-pxa/balloon3.c index 9244493dbcb7..56e8cebeb7d5 100644 --- a/trunk/arch/arm/mach-pxa/balloon3.c +++ b/trunk/arch/arm/mach-pxa/balloon3.c @@ -679,6 +679,8 @@ static struct mtd_partition balloon3_partition_info[] = { }, }; +static const char *balloon3_part_probes[] = { "cmdlinepart", NULL }; + struct platform_nand_data balloon3_nand_pdata = { .chip = { .nr_chips = 4, @@ -686,6 +688,7 @@ struct platform_nand_data balloon3_nand_pdata = { .nr_partitions = ARRAY_SIZE(balloon3_partition_info), .partitions = balloon3_partition_info, .chip_delay = 50, + .part_probe_types = balloon3_part_probes, }, .ctrl = { .hwcontrol = 0, diff --git a/trunk/arch/arm/mach-pxa/em-x270.c b/trunk/arch/arm/mach-pxa/em-x270.c index 97f82ad341bf..a3a4a38d4972 100644 --- a/trunk/arch/arm/mach-pxa/em-x270.c +++ b/trunk/arch/arm/mach-pxa/em-x270.c @@ -338,6 +338,8 @@ static struct mtd_partition em_x270_partition_info[] = { }, }; +static const char *em_x270_part_probes[] = { "cmdlinepart", NULL }; + struct platform_nand_data em_x270_nand_platdata = { .chip = { .nr_chips = 1, @@ -345,6 +347,7 @@ struct platform_nand_data em_x270_nand_platdata = { .nr_partitions = ARRAY_SIZE(em_x270_partition_info), .partitions = em_x270_partition_info, .chip_delay = 20, + .part_probe_types = em_x270_part_probes, }, .ctrl = { .hwcontrol = 0, diff --git a/trunk/arch/arm/mach-pxa/palmtx.c b/trunk/arch/arm/mach-pxa/palmtx.c index 0da35dccfd89..9507605ed547 100644 --- a/trunk/arch/arm/mach-pxa/palmtx.c +++ b/trunk/arch/arm/mach-pxa/palmtx.c @@ -268,6 +268,8 @@ static struct mtd_partition palmtx_partition_info[] = { }, }; +static const char *palmtx_part_probes[] = { "cmdlinepart", NULL }; + struct platform_nand_data palmtx_nand_platdata = { .chip = { .nr_chips = 1, @@ -275,6 +277,7 @@ struct platform_nand_data palmtx_nand_platdata = { .nr_partitions = ARRAY_SIZE(palmtx_partition_info), .partitions = palmtx_partition_info, .chip_delay = 20, + .part_probe_types = palmtx_part_probes, }, .ctrl = { .cmd_ctrl = palmtx_nand_cmd_ctl, diff --git a/trunk/arch/arm/mach-s3c24xx/mach-smdk2416.c b/trunk/arch/arm/mach-s3c24xx/mach-smdk2416.c index c3100a044fbe..30a44f806e01 100644 --- a/trunk/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/trunk/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -148,25 +148,23 @@ static struct s3c24xx_hsudc_platdata smdk2416_hsudc_platdata = { static struct s3c_fb_pd_win smdk2416_fb_win[] = { [0] = { + /* think this is the same as the smdk6410 */ + .win_mode = { + .pixclock = 41094, + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .default_bpp = 16, .max_bpp = 32, - .xres = 800, - .yres = 480, }, }; -static struct fb_videomode smdk2416_lcd_timing = { - .pixclock = 41094, - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, -}; - static void s3c2416_fb_gpio_setup_24bpp(void) { unsigned int gpio; @@ -189,7 +187,6 @@ static void s3c2416_fb_gpio_setup_24bpp(void) static struct s3c_fb_platdata smdk2416_fb_platdata = { .win[0] = &smdk2416_fb_win[0], - .vtiming = &smdk2416_lcd_timing, .setup_gpio = s3c2416_fb_gpio_setup_24bpp, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s3c64xx/mach-anw6410.c b/trunk/arch/arm/mach-s3c64xx/mach-anw6410.c index ffa29ddfdfce..314df0518afd 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-anw6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-anw6410.c @@ -134,27 +134,24 @@ static struct platform_device anw6410_lcd_powerdev = { }; static struct s3c_fb_pd_win anw6410_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode anw6410_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &anw6410_lcd_timing, .win[0] = &anw6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s3c64xx/mach-crag6410.c b/trunk/arch/arm/mach-s3c64xx/mach-crag6410.c index d0c352d861f8..6b20a71d7dbf 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -151,29 +151,26 @@ static struct platform_device crag6410_lcd_powerdev = { /* 640x480 URT */ static struct s3c_fb_pd_win crag6410_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .left_margin = 150, + .right_margin = 80, + .upper_margin = 40, + .lower_margin = 5, + .hsync_len = 40, + .vsync_len = 5, + .xres = 640, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 640, - .yres = 480, .virtual_y = 480 * 2, .virtual_x = 640, }; -static struct fb_videomode crag6410_lcd_timing = { - .left_margin = 150, - .right_margin = 80, - .upper_margin = 40, - .lower_margin = 5, - .hsync_len = 40, - .vsync_len = 5, - .xres = 640, - .yres = 480, -}; - /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &crag6410_lcd_timing, .win[0] = &crag6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s3c64xx/mach-hmt.c b/trunk/arch/arm/mach-s3c64xx/mach-hmt.c index 689088162f77..1bf6b9da20fc 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-hmt.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-hmt.c @@ -129,27 +129,23 @@ static struct platform_device hmt_backlight_device = { }; static struct s3c_fb_pd_win hmt_fb_win0 = { + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode hmt_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata hmt_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &hmt_lcd_timing, .win[0] = &hmt_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s3c64xx/mach-mini6410.c b/trunk/arch/arm/mach-s3c64xx/mach-mini6410.c index 5539a255a704..f8ea61ea3b33 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-mini6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-mini6410.c @@ -140,59 +140,41 @@ static struct s3c2410_platform_nand mini6410_nand_info = { .sets = mini6410_nand_sets, }; -static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = { - .max_bpp = 32, - .default_bpp = 16, - .xres = 480, - .yres = 272, -}; - -static struct fb_videomode mini6410_lcd_type0_timing = { - /* 4.3" 480x272 */ - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 40, - .vsync_len = 1, - .xres = 480, - .yres = 272, -}; - -static struct s3c_fb_pd_win mini6410_lcd_type1_fb_win = { - .max_bpp = 32, - .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode mini6410_lcd_type1_timing = { - /* 7.0" 800x480 */ - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, -}; - -static struct s3c_fb_platdata mini6410_lcd_pdata[] __initdata = { +static struct s3c_fb_pd_win mini6410_fb_win[] = { { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &mini6410_lcd_type0_timing, - .win[0] = &mini6410_lcd_type0_fb_win, - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .win_mode = { /* 4.3" 480x272 */ + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 40, + .vsync_len = 1, + .xres = 480, + .yres = 272, + }, + .max_bpp = 32, + .default_bpp = 16, }, { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &mini6410_lcd_type1_timing, - .win[0] = &mini6410_lcd_type1_fb_win, - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .win_mode = { /* 7.0" 800x480 */ + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 16, }, - { }, +}; + +static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &mini6410_fb_win[0], + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, }; static void mini6410_lcd_power_set(struct plat_lcd_data *pd, @@ -290,7 +272,7 @@ static void mini6410_parse_features( "screen type already set\n", f); } else { int li = f - '0'; - if (li >= ARRAY_SIZE(mini6410_lcd_pdata)) + if (li >= ARRAY_SIZE(mini6410_fb_win)) printk(KERN_INFO "MINI6410: '%c' out " "of range LCD mode\n", f); else { @@ -314,12 +296,14 @@ static void __init mini6410_machine_init(void) /* Parse the feature string */ mini6410_parse_features(&features, mini6410_features_str); + mini6410_lcd_pdata.win[0] = &mini6410_fb_win[features.lcd_index]; + printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n", - mini6410_lcd_pdata[features.lcd_index].win[0]->xres, - mini6410_lcd_pdata[features.lcd_index].win[0]->yres); + mini6410_lcd_pdata.win[0]->win_mode.xres, + mini6410_lcd_pdata.win[0]->win_mode.yres); s3c_nand_set_platdata(&mini6410_nand_info); - s3c_fb_set_platdata(&mini6410_lcd_pdata[features.lcd_index]); + s3c_fb_set_platdata(&mini6410_lcd_pdata); s3c24xx_ts_set_platdata(NULL); /* configure nCS1 width to 16 bits */ diff --git a/trunk/arch/arm/mach-s3c64xx/mach-real6410.c b/trunk/arch/arm/mach-s3c64xx/mach-real6410.c index 326b21604bc3..b92d8e17d502 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-real6410.c @@ -106,57 +106,41 @@ static struct platform_device real6410_device_eth = { }, }; -static struct s3c_fb_pd_win real6410_lcd_type0_fb_win = { - .max_bpp = 32, - .default_bpp = 16, - .xres = 480, - .yres = 272, -}; - -static struct fb_videomode real6410_lcd_type0_timing = { - /* 4.3" 480x272 */ - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 40, - .vsync_len = 1, -}; - -static struct s3c_fb_pd_win real6410_lcd_type1_fb_win = { - .max_bpp = 32, - .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode real6410_lcd_type1_timing = { - /* 7.0" 800x480 */ - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, -}; - -static struct s3c_fb_platdata real6410_lcd_pdata[] __initdata = { +static struct s3c_fb_pd_win real6410_fb_win[] = { { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &real6410_lcd_type0_timing, - .win[0] = &real6410_lcd_type0_fb_win, - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .win_mode = { /* 4.3" 480x272 */ + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 40, + .vsync_len = 1, + .xres = 480, + .yres = 272, + }, + .max_bpp = 32, + .default_bpp = 16, }, { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &real6410_lcd_type1_timing, - .win[0] = &real6410_lcd_type1_fb_win, - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + .win_mode = { /* 7.0" 800x480 */ + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 16, }, - { }, +}; + +static struct s3c_fb_platdata real6410_lcd_pdata __initdata = { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &real6410_fb_win[0], + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, }; static struct mtd_partition real6410_nand_part[] = { @@ -269,7 +253,7 @@ static void real6410_parse_features( "screen type already set\n", f); } else { int li = f - '0'; - if (li >= ARRAY_SIZE(real6410_lcd_pdata)) + if (li >= ARRAY_SIZE(real6410_fb_win)) printk(KERN_INFO "REAL6410: '%c' out " "of range LCD mode\n", f); else { @@ -293,11 +277,13 @@ static void __init real6410_machine_init(void) /* Parse the feature string */ real6410_parse_features(&features, real6410_features_str); + real6410_lcd_pdata.win[0] = &real6410_fb_win[features.lcd_index]; + printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n", - real6410_lcd_pdata[features.lcd_index].win[0]->xres, - real6410_lcd_pdata[features.lcd_index].win[0]->yres); + real6410_lcd_pdata.win[0]->win_mode.xres, + real6410_lcd_pdata.win[0]->win_mode.yres); - s3c_fb_set_platdata(&real6410_lcd_pdata[features.lcd_index]); + s3c_fb_set_platdata(&real6410_lcd_pdata); s3c_nand_set_platdata(&real6410_nand_info); s3c24xx_ts_set_platdata(NULL); diff --git a/trunk/arch/arm/mach-s3c64xx/mach-smartq5.c b/trunk/arch/arm/mach-s3c64xx/mach-smartq5.c index d6266d8b43c9..c5021d0335c6 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-smartq5.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-smartq5.c @@ -108,27 +108,23 @@ static struct platform_device smartq5_buttons_device = { }; static struct s3c_fb_pd_win smartq5_fb_win0 = { + .win_mode = { + .left_margin = 216, + .right_margin = 40, + .upper_margin = 35, + .lower_margin = 10, + .hsync_len = 1, + .vsync_len = 1, + .xres = 800, + .yres = 480, + .refresh = 80, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smartq5_lcd_timing = { - .left_margin = 216, - .right_margin = 40, - .upper_margin = 35, - .lower_margin = 10, - .hsync_len = 1, - .vsync_len = 1, - .xres = 800, - .yres = 480, - .refresh = 80, }; static struct s3c_fb_platdata smartq5_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &smartq5_lcd_timing, .win[0] = &smartq5_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | diff --git a/trunk/arch/arm/mach-s3c64xx/mach-smartq7.c b/trunk/arch/arm/mach-s3c64xx/mach-smartq7.c index 0957d2a980e1..aa9072a4cbef 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-smartq7.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-smartq7.c @@ -124,27 +124,23 @@ static struct platform_device smartq7_buttons_device = { }; static struct s3c_fb_pd_win smartq7_fb_win0 = { + .win_mode = { + .left_margin = 3, + .right_margin = 5, + .upper_margin = 1, + .lower_margin = 20, + .hsync_len = 10, + .vsync_len = 3, + .xres = 800, + .yres = 480, + .refresh = 80, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smartq7_lcd_timing = { - .left_margin = 3, - .right_margin = 5, - .upper_margin = 1, - .lower_margin = 20, - .hsync_len = 10, - .vsync_len = 3, - .xres = 800, - .yres = 480, - .refresh = 80, }; static struct s3c_fb_platdata smartq7_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &smartq7_lcd_timing, .win[0] = &smartq7_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | diff --git a/trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c b/trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c index df3103d450e2..d44319b09412 100644 --- a/trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/trunk/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -146,29 +146,26 @@ static struct platform_device smdk6410_lcd_powerdev = { }; static struct s3c_fb_pd_win smdk6410_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, .virtual_y = 480 * 2, .virtual_x = 800, }; -static struct fb_videomode smdk6410_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, -}; - /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .vtiming = &smdk6410_lcd_timing, .win[0] = &smdk6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c b/trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c index 92fefad505cc..a40e325d62c8 100644 --- a/trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/trunk/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -103,26 +103,22 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win smdk6440_fb_win0 = { + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 24, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdk6440_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = { .win[0] = &smdk6440_fb_win0, - .vtiming = &smdk6440_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c b/trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c index e2335ecf6eae..efb69e2f2afe 100644 --- a/trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/trunk/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -121,26 +121,22 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win smdk6450_fb_win0 = { + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 24, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdk6450_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = { .win[0] = &smdk6450_fb_win0, - .vtiming = &smdk6450_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-s5pc100/mach-smdkc100.c b/trunk/arch/arm/mach-s5pc100/mach-smdkc100.c index 0c3ae38d27ca..674d22992f3c 100644 --- a/trunk/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/trunk/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -136,27 +136,24 @@ static struct platform_device smdkc100_lcd_powerdev = { /* Frame Buffer */ static struct s3c_fb_pd_win smdkc100_fb_win0 = { + /* this is to ensure we use win0 */ + .win_mode = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + .refresh = 80, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdkc100_lcd_timing = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - .refresh = 80, }; static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = { .win[0] = &smdkc100_fb_win0, - .vtiming = &smdkc100_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5pc100_fb_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-s5pv210/mach-aquila.c b/trunk/arch/arm/mach-s5pv210/mach-aquila.c index af528f9e97f9..48d018f2332b 100644 --- a/trunk/arch/arm/mach-s5pv210/mach-aquila.c +++ b/trunk/arch/arm/mach-s5pv210/mach-aquila.c @@ -96,34 +96,38 @@ static struct s3c2410_uartcfg aquila_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win aquila_fb_win0 = { + .win_mode = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 3, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 2, + .xres = 480, + .yres = 800, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 480, - .yres = 800, }; static struct s3c_fb_pd_win aquila_fb_win1 = { + .win_mode = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 3, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 2, + .xres = 480, + .yres = 800, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 480, - .yres = 800, -}; - -static struct fb_videomode aquila_lcd_timing = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 3, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 2, - .xres = 480, - .yres = 800, }; static struct s3c_fb_platdata aquila_lcd_pdata __initdata = { .win[0] = &aquila_fb_win0, .win[1] = &aquila_fb_win1, - .vtiming = &aquila_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | VIDCON1_INV_VCLK | VIDCON1_INV_VDEN, diff --git a/trunk/arch/arm/mach-s5pv210/mach-goni.c b/trunk/arch/arm/mach-s5pv210/mach-goni.c index bf5087c2b7fe..f20a97c8e411 100644 --- a/trunk/arch/arm/mach-s5pv210/mach-goni.c +++ b/trunk/arch/arm/mach-s5pv210/mach-goni.c @@ -107,29 +107,25 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win goni_fb_win0 = { + .win_mode = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 2, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 1, + .xres = 480, + .yres = 800, + .refresh = 55, + }, .max_bpp = 32, .default_bpp = 16, - .xres = 480, - .yres = 800, .virtual_x = 480, .virtual_y = 2 * 800, }; -static struct fb_videomode goni_lcd_timing = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 2, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 1, - .xres = 480, - .yres = 800, - .refresh = 55, -}; - static struct s3c_fb_platdata goni_lcd_pdata __initdata = { .win[0] = &goni_fb_win0, - .vtiming = &goni_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN diff --git a/trunk/arch/arm/mach-s5pv210/mach-smdkv210.c b/trunk/arch/arm/mach-s5pv210/mach-smdkv210.c index 0d7ddec88eb7..fa1b61209fd9 100644 --- a/trunk/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/trunk/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -178,26 +178,22 @@ static struct platform_device smdkv210_lcd_lte480wv = { }; static struct s3c_fb_pd_win smdkv210_fb_win0 = { + .win_mode = { + .left_margin = 13, + .right_margin = 8, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, .max_bpp = 32, .default_bpp = 24, - .xres = 800, - .yres = 480, -}; - -static struct fb_videomode smdkv210_lcd_timing = { - .left_margin = 13, - .right_margin = 8, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, }; static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = { .win[0] = &smdkv210_fb_win0, - .vtiming = &smdkv210_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5pv210_fb_gpio_setup_24bpp, diff --git a/trunk/arch/arm/mach-shmobile/Kconfig b/trunk/arch/arm/mach-shmobile/Kconfig index df33909205e2..f31383c32f9c 100644 --- a/trunk/arch/arm/mach-shmobile/Kconfig +++ b/trunk/arch/arm/mach-shmobile/Kconfig @@ -186,12 +186,6 @@ config SH_TIMER_TMU help This enables build of the TMU timer driver. -config EM_TIMER_STI - bool "STI timer driver" - default y - help - This enables build of the STI timer driver. - endmenu config SH_CLK_CPG diff --git a/trunk/arch/arm/mach-ux500/board-mop500-uib.c b/trunk/arch/arm/mach-ux500/board-mop500-uib.c index 1f47d962e3a1..b29a788f498c 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500-uib.c +++ b/trunk/arch/arm/mach-ux500/board-mop500-uib.c @@ -96,7 +96,7 @@ static void __init __mop500_uib_init(struct uib *uib, const char *why) /* * Detect the UIB attached based on the presence or absence of i2c devices. */ -int __init mop500_uib_init(void) +static int __init mop500_uib_init(void) { struct uib *uib = mop500_uib; struct i2c_adapter *i2c0; @@ -131,3 +131,5 @@ int __init mop500_uib_init(void) return 0; } + +module_init(mop500_uib_init); diff --git a/trunk/arch/arm/mach-ux500/board-mop500.c b/trunk/arch/arm/mach-ux500/board-mop500.c index 9c74ac545849..fba8adea421e 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500.c +++ b/trunk/arch/arm/mach-ux500/board-mop500.c @@ -673,15 +673,9 @@ static void __init u8500_cryp1_hash1_init(struct device *parent) static struct platform_device *snowball_platform_devs[] __initdata = { &snowball_led_dev, &snowball_key_dev, - &snowball_sbnet_dev, &ab8500_device, }; -static struct platform_device *snowball_of_platform_devs[] __initdata = { - &snowball_led_dev, - &snowball_key_dev, -}; - static void __init mop500_init_machine(void) { struct device *parent = NULL; @@ -716,8 +710,6 @@ static void __init mop500_init_machine(void) /* This board has full regulator constraints */ regulator_has_full_constraints(); - - mop500_uib_init(); } static void __init snowball_init_machine(void) @@ -782,8 +774,6 @@ static void __init hrefv60_init_machine(void) /* This board has full regulator constraints */ regulator_has_full_constraints(); - - mop500_uib_init(); } MACHINE_START(U8500, "ST-Ericsson MOP500 platform") @@ -844,10 +834,6 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { static const struct of_device_id u8500_local_bus_nodes[] = { /* only create devices below soc node */ { .compatible = "stericsson,db8500", }, - { .compatible = "stericsson,db8500-prcmu", }, - { .compatible = "stericsson,db8500-prcmu-regulator", }, - { .compatible = "stericsson,ab8500", }, - { .compatible = "stericsson,ab8500-regulator", }, { .compatible = "simple-bus"}, { }, }; @@ -866,7 +852,7 @@ static void __init u8500_init_machine(void) else if (of_machine_is_compatible("st-ericsson,hrefv60+")) hrefv60_pinmaps_init(); - parent = u8500_of_init_devices(); + parent = u8500_init_devices(); for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) mop500_platform_devs[i]->dev.parent = parent; @@ -883,23 +869,15 @@ static void __init u8500_init_machine(void) ARRAY_SIZE(mop500_platform_devs)); mop500_sdi_init(parent); + i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); i2c_register_board_info(2, mop500_i2c2_devices, ARRAY_SIZE(mop500_i2c2_devices)); - mop500_uib_init(); - } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) { - /* - * Devices to be DT:ed: - * snowball_led_dev = todo - * snowball_key_dev = todo - * snowball_sbnet_dev = done - * ab8500_device = done - */ - platform_add_devices(snowball_of_platform_devs, - ARRAY_SIZE(snowball_of_platform_devs)); + platform_add_devices(snowball_platform_devs, + ARRAY_SIZE(snowball_platform_devs)); snowball_sdi_init(parent); } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) { @@ -920,8 +898,6 @@ static void __init u8500_init_machine(void) i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); i2c_register_board_info(2, mop500_i2c2_devices, ARRAY_SIZE(mop500_i2c2_devices)); - - mop500_uib_init(); } mop500_i2c_init(parent); diff --git a/trunk/arch/arm/mach-ux500/board-mop500.h b/trunk/arch/arm/mach-ux500/board-mop500.h index 2f87b25a908a..bc44c07c71a9 100644 --- a/trunk/arch/arm/mach-ux500/board-mop500.h +++ b/trunk/arch/arm/mach-ux500/board-mop500.h @@ -89,11 +89,7 @@ void __init mop500_pinmaps_init(void); void __init snowball_pinmaps_init(void); void __init hrefv60_pinmaps_init(void); -int __init mop500_uib_init(void); void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, unsigned n); -/* TODO: Once all pieces are DT:ed, remove completely. */ -struct device * __init u8500_of_init_devices(void); - #endif diff --git a/trunk/arch/arm/mach-ux500/cpu-db8500.c b/trunk/arch/arm/mach-ux500/cpu-db8500.c index 33275eb4c689..16169c4bf6ca 100644 --- a/trunk/arch/arm/mach-ux500/cpu-db8500.c +++ b/trunk/arch/arm/mach-ux500/cpu-db8500.c @@ -140,6 +140,7 @@ static struct platform_device *platform_devs[] __initdata = { static struct platform_device *of_platform_devs[] __initdata = { &u8500_dma40_device, &db8500_pmu_device, + &db8500_prcmu_device, }; static resource_size_t __initdata db8500_gpio_base[] = { @@ -218,28 +219,6 @@ struct device * __init u8500_init_devices(void) db8500_add_gpios(parent); db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); - platform_device_register_data(parent, - "cpufreq-u8500", -1, NULL, 0); - - for (i = 0; i < ARRAY_SIZE(platform_devs); i++) - platform_devs[i]->dev.parent = parent; - - platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); - - return parent; -} - -/* TODO: Once all pieces are DT:ed, remove completely. */ -struct device * __init u8500_of_init_devices(void) -{ - struct device *parent; - int i; - - parent = db8500_soc_device_init(); - - db8500_add_rtc(parent); - db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); - platform_device_register_data(parent, "cpufreq-u8500", -1, NULL, 0); @@ -250,7 +229,7 @@ struct device * __init u8500_of_init_devices(void) * Devices to be DT:ed: * u8500_dma40_device = todo * db8500_pmu_device = todo - * db8500_prcmu_device = done + * db8500_prcmu_device = todo */ platform_add_devices(of_platform_devs, ARRAY_SIZE(of_platform_devs)); diff --git a/trunk/arch/arm/mm/dma-mapping.c b/trunk/arch/arm/mm/dma-mapping.c index d766e4256b74..ea6b43154090 100644 --- a/trunk/arch/arm/mm/dma-mapping.c +++ b/trunk/arch/arm/mm/dma-mapping.c @@ -228,7 +228,7 @@ static pte_t **consistent_pte; #define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M -static unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE; +unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE; void __init init_consistent_dma_size(unsigned long size) { @@ -268,8 +268,10 @@ static int __init consistent_init(void) unsigned long base = consistent_base; unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT; - if (IS_ENABLED(CONFIG_CMA) && !IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) +#ifndef CONFIG_ARM_DMA_USE_IOMMU + if (cpu_architecture() >= CPU_ARCH_ARMv6) return 0; +#endif consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL); if (!consistent_pte) { @@ -321,7 +323,7 @@ static struct arm_vmregion_head coherent_head = { .vm_list = LIST_HEAD_INIT(coherent_head.vm_list), }; -static size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8; +size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8; static int __init early_coherent_pool(char *p) { @@ -340,7 +342,7 @@ static int __init coherent_init(void) struct page *page; void *ptr; - if (!IS_ENABLED(CONFIG_CMA)) + if (cpu_architecture() < CPU_ARCH_ARMv6) return 0; ptr = __alloc_from_contiguous(NULL, size, prot, &page); @@ -702,7 +704,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, if (arch_is_coherent() || nommu()) addr = __alloc_simple_buffer(dev, size, gfp, &page); - else if (!IS_ENABLED(CONFIG_CMA)) + else if (cpu_architecture() < CPU_ARCH_ARMv6) addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller); else if (gfp & GFP_ATOMIC) addr = __alloc_from_pool(dev, size, &page, caller); @@ -771,7 +773,7 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr, if (arch_is_coherent() || nommu()) { __dma_free_buffer(page, size); - } else if (!IS_ENABLED(CONFIG_CMA)) { + } else if (cpu_architecture() < CPU_ARCH_ARMv6) { __dma_free_remap(cpu_addr, size); __dma_free_buffer(page, size); } else { diff --git a/trunk/arch/arm/mm/init.c b/trunk/arch/arm/mm/init.c index f54d59219764..c21d06c7dd7e 100644 --- a/trunk/arch/arm/mm/init.c +++ b/trunk/arch/arm/mm/init.c @@ -212,7 +212,7 @@ EXPORT_SYMBOL(arm_dma_zone_size); * allocations. This must be the smallest DMA mask in the system, * so a successful GFP_DMA allocation will always satisfy this. */ -phys_addr_t arm_dma_limit; +u32 arm_dma_limit; static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole, unsigned long dma_size) diff --git a/trunk/arch/arm/mm/mm.h b/trunk/arch/arm/mm/mm.h index c471436c7952..93dc0c17cdcb 100644 --- a/trunk/arch/arm/mm/mm.h +++ b/trunk/arch/arm/mm/mm.h @@ -62,7 +62,7 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page #endif #ifdef CONFIG_ZONE_DMA -extern phys_addr_t arm_dma_limit; +extern u32 arm_dma_limit; #else #define arm_dma_limit ((u32)~0) #endif diff --git a/trunk/arch/arm/plat-omap/include/plat/gpmc.h b/trunk/arch/arm/plat-omap/include/plat/gpmc.h index f37764a36072..1527929b445a 100644 --- a/trunk/arch/arm/plat-omap/include/plat/gpmc.h +++ b/trunk/arch/arm/plat-omap/include/plat/gpmc.h @@ -92,8 +92,6 @@ enum omap_ecc { OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ /* 1-bit ecc: stored at beginning of spare area as romcode */ OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ - OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */ - OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */ }; /* @@ -159,13 +157,4 @@ extern int gpmc_nand_write(int cs, int cmd, int wval); int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size); int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); - -#ifdef CONFIG_ARCH_OMAP3 -int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors); -int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors, - int nerrors); -int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc); -int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc); -#endif /* CONFIG_ARCH_OMAP3 */ - #endif diff --git a/trunk/arch/arm/plat-samsung/include/plat/fb.h b/trunk/arch/arm/plat-samsung/include/plat/fb.h index 536002ff2ab8..0fedf47fa502 100644 --- a/trunk/arch/arm/plat-samsung/include/plat/fb.h +++ b/trunk/arch/arm/plat-samsung/include/plat/fb.h @@ -24,16 +24,15 @@ /** * struct s3c_fb_pd_win - per window setup data - * @xres : The window X size. - * @yres : The window Y size. + * @win_mode: The display parameters to initialise (not for window 0) * @virtual_x: The virtual X size. * @virtual_y: The virtual Y size. */ struct s3c_fb_pd_win { + struct fb_videomode win_mode; + unsigned short default_bpp; unsigned short max_bpp; - unsigned short xres; - unsigned short yres; unsigned short virtual_x; unsigned short virtual_y; }; @@ -46,7 +45,6 @@ struct s3c_fb_pd_win { * @default_win: default window layer number to be used for UI layer. * @vidcon0: The base vidcon0 values to control the panel data format. * @vidcon1: The base vidcon1 values to control the panel data output. - * @vtiming: Video timing when connected to a RGB type panel. * @win: The setup data for each hardware window, or NULL for unused. * @display_mode: The LCD output display mode. * @@ -60,7 +58,8 @@ struct s3c_fb_platdata { void (*setup_gpio)(void); struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; - struct fb_videomode *vtiming; + + u32 default_win; u32 vidcon0; u32 vidcon1; diff --git a/trunk/arch/avr32/include/asm/posix_types.h b/trunk/arch/avr32/include/asm/posix_types.h index 9ba9e749b3f3..74667bfc88cc 100644 --- a/trunk/arch/avr32/include/asm/posix_types.h +++ b/trunk/arch/avr32/include/asm/posix_types.h @@ -17,6 +17,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/avr32/kernel/entry-avr32b.S b/trunk/arch/avr32/kernel/entry-avr32b.S index df2884181313..169268c40ae2 100644 --- a/trunk/arch/avr32/kernel/entry-avr32b.S +++ b/trunk/arch/avr32/kernel/entry-avr32b.S @@ -281,7 +281,7 @@ syscall_exit_work: ld.w r1, r0[TI_flags] rjmp 1b -2: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME +2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME tst r1, r2 breq 3f unmask_interrupts @@ -587,7 +587,7 @@ fault_exit_work: ld.w r1, r0[TI_flags] rjmp fault_exit_work -1: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME +1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK tst r1, r2 breq 2f unmask_interrupts diff --git a/trunk/arch/avr32/kernel/signal.c b/trunk/arch/avr32/kernel/signal.c index d552a854dacc..ae386c304bee 100644 --- a/trunk/arch/avr32/kernel/signal.c +++ b/trunk/arch/avr32/kernel/signal.c @@ -22,6 +22,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) { @@ -87,6 +89,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) @@ -221,27 +224,30 @@ static inline void setup_syscall_restart(struct pt_regs *regs) static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, - struct pt_regs *regs, int syscall) + sigset_t *oldset, struct pt_regs *regs, int syscall) { int ret; /* * Set up the stack frame */ - ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); + ret = setup_rt_frame(sig, ka, info, oldset, regs); /* * Check that the resulting registers are sane */ ret |= !valid_user_regs(regs); + if (ret != 0) { + force_sigsegv(sig, current); + return; + } + /* * Block the signal if we were successful. */ - if (ret != 0) - force_sigsegv(sig, current); - else - signal_delivered(sig, info, ka, regs, 0); + block_sigmask(ka, sig); + clear_thread_flag(TIF_RESTORE_SIGMASK); } /* @@ -249,7 +255,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, * doesn't want to handle. Thus you cannot kill init even with a * SIGKILL even by mistake. */ -static void do_signal(struct pt_regs *regs, int syscall) +int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) { siginfo_t info; int signr; @@ -261,7 +267,12 @@ static void do_signal(struct pt_regs *regs, int syscall) * without doing anything if so. */ if (!user_mode(regs)) - return; + return 0; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) + oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (syscall) { @@ -286,11 +297,15 @@ static void do_signal(struct pt_regs *regs, int syscall) if (signr == 0) { /* No signal to deliver -- put the saved sigmask back */ - restore_saved_sigmask(); - return; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + return 0; } - handle_signal(signr, &ka, &info, regs, syscall); + handle_signal(signr, &ka, &info, oldset, regs, syscall); + return 1; } asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) @@ -300,11 +315,13 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR) syscall = 1; - if (ti->flags & _TIF_SIGPENDING) - do_signal(regs, syscall); + if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + do_signal(regs, ¤t->blocked, syscall); if (ti->flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/blackfin/include/asm/posix_types.h b/trunk/arch/blackfin/include/asm/posix_types.h index 1bd3436db6a7..41bc1875c4d7 100644 --- a/trunk/arch/blackfin/include/asm/posix_types.h +++ b/trunk/arch/blackfin/include/asm/posix_types.h @@ -10,6 +10,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned int __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/blackfin/include/asm/thread_info.h b/trunk/arch/blackfin/include/asm/thread_info.h index 53ad10005ae3..02560fd8a121 100644 --- a/trunk/arch/blackfin/include/asm/thread_info.h +++ b/trunk/arch/blackfin/include/asm/thread_info.h @@ -100,6 +100,7 @@ static inline struct thread_info *current_thread_info(void) TIF_NEED_RESCHED */ #define TIF_MEMDIE 4 /* is terminating due to OOM killer */ #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ +#define TIF_FREEZE 6 /* is freezing for suspend */ #define TIF_IRQ_SYNC 7 /* sync pipeline stage */ #define TIF_NOTIFY_RESUME 8 /* callback before returning to user */ #define TIF_SINGLESTEP 9 @@ -110,6 +111,7 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_NEED_RESCHED (1<nr_cpus_allowed == num_possible_cpus()) + if (current->rt.nr_cpus_allowed == num_possible_cpus()) set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id())); #endif diff --git a/trunk/arch/blackfin/kernel/signal.c b/trunk/arch/blackfin/kernel/signal.c index 6682b73a8523..e5bbc1a5edc2 100644 --- a/trunk/arch/blackfin/kernel/signal.c +++ b/trunk/arch/blackfin/kernel/signal.c @@ -19,6 +19,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* Location of the trace bit in SYSCFG. */ #define TRACE_BITS 0x0001 @@ -96,6 +98,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) @@ -187,22 +190,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) - return -EFAULT; + goto give_sigsegv; /* Set up registers for signal handler */ + wrusp((unsigned long)frame); if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor *) ka->sa.sa_handler; - u32 pc, p3; - err |= __get_user(pc, &funcptr->text); - err |= __get_user(p3, &funcptr->GOT); - if (err) - return -EFAULT; - regs->pc = pc; - regs->p3 = p3; + __get_user(regs->pc, &funcptr->text); + __get_user(regs->p3, &funcptr->GOT); } else regs->pc = (unsigned long)ka->sa.sa_handler; - wrusp((unsigned long)frame); regs->rets = SIGRETURN_STUB; regs->r0 = frame->sig; @@ -210,6 +208,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, regs->r2 = (unsigned long)(&frame->uc); return 0; + + give_sigsegv: + force_sigsegv(sig, current); + return -EFAULT; } static inline void @@ -245,21 +247,24 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) /* * OK, we're invoking a handler */ -static void +static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs *regs) + sigset_t *oldset, struct pt_regs *regs) { + int ret; + /* are we from a system call? to see pt_regs->orig_p0 */ if (regs->orig_p0 >= 0) /* If so, check system call restarting.. */ handle_restart(regs, ka, 1); /* set up the stack frame */ - if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) - force_sigsegv(sig, current); - else - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLESTEP)); + ret = setup_rt_frame(sig, ka, info, oldset, regs); + + if (ret == 0) + block_sigmask(ka, sig); + + return ret; } /* @@ -276,16 +281,37 @@ asmlinkage void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; current->thread.esp0 = (unsigned long)regs; + if (try_to_freeze()) + goto no_signal; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, regs); + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + } + return; } + no_signal: /* Did we come from a system call? */ if (regs->orig_p0 >= 0) /* Restart the system call - no handlers present */ @@ -293,7 +319,10 @@ asmlinkage void do_signal(struct pt_regs *regs) /* if there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* @@ -301,12 +330,14 @@ asmlinkage void do_signal(struct pt_regs *regs) */ asmlinkage void do_notify_resume(struct pt_regs *regs) { - if (test_thread_flag(TIF_SIGPENDING)) + if (test_thread_flag(TIF_SIGPENDING) || test_thread_flag(TIF_RESTORE_SIGMASK)) do_signal(regs); if (test_thread_flag(TIF_NOTIFY_RESUME)) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/blackfin/kernel/trace.c b/trunk/arch/blackfin/kernel/trace.c index f7f7a18abca9..44bbf2f564cb 100644 --- a/trunk/arch/blackfin/kernel/trace.c +++ b/trunk/arch/blackfin/kernel/trace.c @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include #include #include @@ -29,7 +27,8 @@ void decode_address(char *buf, unsigned long address) { struct task_struct *p; struct mm_struct *mm; - unsigned long offset; + unsigned long flags, offset; + unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); struct rb_node *n; #ifdef CONFIG_KALLSYMS @@ -113,17 +112,17 @@ void decode_address(char *buf, unsigned long address) * mappings of all our processes and see if we can't be a whee * bit more specific */ - read_lock(&tasklist_lock); + write_lock_irqsave(&tasklist_lock, flags); for_each_process(p) { - struct task_struct *t; - - t = find_lock_task_mm(p); - if (!t) + mm = (in_atomic ? p->mm : get_task_mm(p)); + if (!mm) continue; - mm = t->mm; - if (!down_read_trylock(&mm->mmap_sem)) - goto __continue; + if (!down_read_trylock(&mm->mmap_sem)) { + if (!in_atomic) + mmput(mm); + continue; + } for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) { struct vm_area_struct *vma; @@ -132,7 +131,7 @@ void decode_address(char *buf, unsigned long address) if (address >= vma->vm_start && address < vma->vm_end) { char _tmpbuf[256]; - char *name = t->comm; + char *name = p->comm; struct file *file = vma->vm_file; if (file) { @@ -165,7 +164,8 @@ void decode_address(char *buf, unsigned long address) name, vma->vm_start, vma->vm_end); up_read(&mm->mmap_sem); - task_unlock(t); + if (!in_atomic) + mmput(mm); if (buf[0] == '\0') sprintf(buf, "[ %s ] dynamic memory", name); @@ -175,8 +175,8 @@ void decode_address(char *buf, unsigned long address) } up_read(&mm->mmap_sem); -__continue: - task_unlock(t); + if (!in_atomic) + mmput(mm); } /* @@ -186,7 +186,7 @@ void decode_address(char *buf, unsigned long address) sprintf(buf, "/* kernel dynamic memory */"); done: - read_unlock(&tasklist_lock); + write_unlock_irqrestore(&tasklist_lock, flags); } #define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1) diff --git a/trunk/arch/blackfin/mach-bf561/boards/acvilon.c b/trunk/arch/blackfin/mach-bf561/boards/acvilon.c index 0b74218fdd3a..f6ffd6f054c3 100644 --- a/trunk/arch/blackfin/mach-bf561/boards/acvilon.c +++ b/trunk/arch/blackfin/mach-bf561/boards/acvilon.c @@ -248,6 +248,8 @@ static struct platform_device bfin_uart0_device = { #if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) +const char *part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition bfin_plat_nand_partitions[] = { { .name = "params(nand)", @@ -287,6 +289,7 @@ static struct platform_nand_data bfin_plat_nand_data = { .chip = { .nr_chips = 1, .chip_delay = 30, + .part_probe_types = part_probes, .partitions = bfin_plat_nand_partitions, .nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions), }, diff --git a/trunk/arch/blackfin/mach-common/entry.S b/trunk/arch/blackfin/mach-common/entry.S index 04c2fbe41a7f..80aa2535e2c9 100644 --- a/trunk/arch/blackfin/mach-common/entry.S +++ b/trunk/arch/blackfin/mach-common/entry.S @@ -711,6 +711,8 @@ ENTRY(_system_call) jump .Lresume_userspace_1; .Lsyscall_sigpending: + cc = BITTST(r7, TIF_RESTORE_SIGMASK); + if cc jump .Lsyscall_do_signals; cc = BITTST(r7, TIF_SIGPENDING); if cc jump .Lsyscall_do_signals; cc = BITTST(r7, TIF_NOTIFY_RESUME); diff --git a/trunk/arch/c6x/kernel/signal.c b/trunk/arch/c6x/kernel/signal.c index 3d8f3c22a94f..cf37478c1169 100644 --- a/trunk/arch/c6x/kernel/signal.c +++ b/trunk/arch/c6x/kernel/signal.c @@ -20,6 +20,8 @@ #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* * Do a signal return, undo the signal stack. */ @@ -85,6 +87,7 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) @@ -245,9 +248,10 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) /* * handle the actual delivery of a signal to userspace */ -static void handle_signal(int sig, +static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs *regs, int syscall) + sigset_t *oldset, struct pt_regs *regs, + int syscall) { int ret; @@ -274,9 +278,11 @@ static void handle_signal(int sig, } /* Set up the stack frame */ - if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) - return; - signal_delivered(sig, info, ka, regs, 0); + ret = setup_rt_frame(sig, ka, info, oldset, regs); + if (ret == 0) + block_sigmask(ka, sig); + + return ret; } /* @@ -286,6 +292,7 @@ static void do_signal(struct pt_regs *regs, int syscall) { struct k_sigaction ka; siginfo_t info; + sigset_t *oldset; int signr; /* we want the common case to go fast, which is why we may in certain @@ -293,9 +300,25 @@ static void do_signal(struct pt_regs *regs, int syscall) if (!user_mode(regs)) return; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &info, &ka, regs, syscall); + if (handle_signal(signr, &info, &ka, oldset, + regs, syscall) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + tracehook_signal_handler(signr, &info, &ka, regs, 0); + } + return; } @@ -320,7 +343,10 @@ static void do_signal(struct pt_regs *regs, int syscall) /* if there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* @@ -331,11 +357,14 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags, int syscall) { /* deal with pending signal delivery */ - if (thread_info_flags & (1 << TIF_SIGPENDING)) + if (thread_info_flags & ((1 << TIF_SIGPENDING) | + (1 << TIF_RESTORE_SIGMASK))) do_signal(regs, syscall); if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/cris/arch-v10/kernel/signal.c b/trunk/arch/cris/arch-v10/kernel/signal.c index 0bb477c13a4e..e16f8f297f61 100644 --- a/trunk/arch/cris/arch-v10/kernel/signal.c +++ b/trunk/arch/cris/arch-v10/kernel/signal.c @@ -31,6 +31,8 @@ #define DEBUG_SIG 0 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */ /* manipulate regs so that upon return, it will be re-executed */ @@ -174,6 +176,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, sizeof(frame->extramask)))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc)) @@ -209,6 +212,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) @@ -411,11 +415,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * OK, we're invoking a handler */ -static inline void handle_signal(int canrestart, unsigned long sig, +static inline int handle_signal(int canrestart, unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs *regs) + sigset_t *oldset, struct pt_regs *regs) { - sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ @@ -453,7 +456,9 @@ static inline void handle_signal(int canrestart, unsigned long sig, ret = setup_frame(sig, ka, oldset, regs); if (ret == 0) - signal_delivered(sig, info, ka, regs, 0); + block_sigmask(ka, sig); + + return ret; } /* @@ -473,6 +478,7 @@ void do_signal(int canrestart, struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -483,10 +489,23 @@ void do_signal(int canrestart, struct pt_regs *regs) if (!user_mode(regs)) return; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(canrestart, signr, &info, &ka, regs); + if (handle_signal(canrestart, signr, &info, &ka, + oldset, regs)) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } return; } @@ -506,5 +525,8 @@ void do_signal(int canrestart, struct pt_regs *regs) /* if there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } diff --git a/trunk/arch/cris/arch-v32/kernel/signal.c b/trunk/arch/cris/arch-v32/kernel/signal.c index b60d1b65a426..b338d8fc0c12 100644 --- a/trunk/arch/cris/arch-v32/kernel/signal.c +++ b/trunk/arch/cris/arch-v32/kernel/signal.c @@ -24,6 +24,9 @@ extern unsigned long cris_signal_return_page; +/* Flag to check if a signal is blockable. */ +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* * A syscall in CRIS is really a "break 13" instruction, which is 2 * bytes. The registers is manipulated so upon return the instruction @@ -164,6 +167,7 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, sizeof(frame->extramask)))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc)) @@ -204,6 +208,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) @@ -429,12 +434,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } /* Invoke a signal handler to, well, handle the signal. */ -static inline void +static inline int handle_signal(int canrestart, unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs * regs) + sigset_t *oldset, struct pt_regs * regs) { - sigset_t *oldset = sigmask_to_save(); int ret; /* Check if this got called from a system call. */ @@ -485,7 +489,9 @@ handle_signal(int canrestart, unsigned long sig, ret = setup_frame(sig, ka, oldset, regs); if (ret == 0) - signal_delivered(sig, info, ka, regs, 0); + block_sigmask(ka, sig); + + return ret; } /* @@ -505,6 +511,7 @@ do_signal(int canrestart, struct pt_regs *regs) int signr; siginfo_t info; struct k_sigaction ka; + sigset_t *oldset; /* * The common case should go fast, which is why this point is @@ -514,11 +521,25 @@ do_signal(int canrestart, struct pt_regs *regs) if (!user_mode(regs)) return; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(canrestart, signr, &info, &ka, regs); + if (handle_signal(canrestart, signr, &info, &ka, + oldset, regs)) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + return; } @@ -539,7 +560,10 @@ do_signal(int canrestart, struct pt_regs *regs) /* if there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } asmlinkage void diff --git a/trunk/arch/cris/include/asm/posix_types.h b/trunk/arch/cris/include/asm/posix_types.h index ce4e51793151..234891c74e2b 100644 --- a/trunk/arch/cris/include/asm/posix_types.h +++ b/trunk/arch/cris/include/asm/posix_types.h @@ -15,6 +15,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/cris/kernel/ptrace.c b/trunk/arch/cris/kernel/ptrace.c index 58d44ee1a71f..d114ad3da9b1 100644 --- a/trunk/arch/cris/kernel/ptrace.c +++ b/trunk/arch/cris/kernel/ptrace.c @@ -40,5 +40,7 @@ void do_notify_resume(int canrestart, struct pt_regs *regs, if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/frv/include/asm/posix_types.h b/trunk/arch/frv/include/asm/posix_types.h index fe512af74a5a..3f34cb45fbb3 100644 --- a/trunk/arch/frv/include/asm/posix_types.h +++ b/trunk/arch/frv/include/asm/posix_types.h @@ -10,6 +10,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/frv/include/asm/thread_info.h b/trunk/arch/frv/include/asm/thread_info.h index 0ff03a33c81e..54ab13a0de41 100644 --- a/trunk/arch/frv/include/asm/thread_info.h +++ b/trunk/arch/frv/include/asm/thread_info.h @@ -94,8 +94,8 @@ register struct thread_info *__current_thread_info asm("gr15"); #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ -#define TIF_POLLING_NRFLAG 6 /* true if poll_idle() is polling TIF_NEED_RESCHED */ -#define TIF_MEMDIE 7 /* is terminating due to OOM killer */ +#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_MEMDIE 17 /* is terminating due to OOM killer */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) @@ -105,16 +105,8 @@ register struct thread_info *__current_thread_info asm("gr15"); #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) -/* work to do on interrupt/exception return */ -#define _TIF_WORK_MASK \ - (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP) - -/* work to do on any return to u-space */ -#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE) - -#if _TIF_ALLWORK_MASK >= 0x2000 -#error "_TIF_ALLWORK_MASK won't fit in an ANDI now (see entry.S)" -#endif +#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ +#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ /* * Thread-synchronous status. diff --git a/trunk/arch/frv/kernel/entry.S b/trunk/arch/frv/kernel/entry.S index 7d5e000fd32e..5ba23f715ea5 100644 --- a/trunk/arch/frv/kernel/entry.S +++ b/trunk/arch/frv/kernel/entry.S @@ -905,19 +905,18 @@ __syscall_call: __syscall_exit: LEDS 0x6300 - # keep current PSR in GR23 - movsg psr,gr23 - - ldi @(gr28,#REG_PSR),gr22 - - sti.p gr8,@(gr28,#REG_GR(8)) ; save return value + sti gr8,@(gr28,#REG_GR(8)) ; save return value # rebuild saved psr - execve will change it for init/main.c + ldi @(gr28,#REG_PSR),gr22 srli gr22,#1,gr5 andi.p gr22,#~PSR_PS,gr22 andi gr5,#PSR_PS,gr5 or gr5,gr22,gr22 - ori.p gr22,#PSR_S,gr22 + ori gr22,#PSR_S,gr22 + + # keep current PSR in GR23 + movsg psr,gr23 # make sure we don't miss an interrupt setting need_resched or sigpending between # sampling and the RETT @@ -925,7 +924,9 @@ __syscall_exit: movgs gr23,psr ldi @(gr15,#TI_FLAGS),gr4 - andicc gr4,#_TIF_ALLWORK_MASK,gr0,icc0 + sethi.p %hi(_TIF_ALLWORK_MASK),gr5 + setlo %lo(_TIF_ALLWORK_MASK),gr5 + andcc gr4,gr5,gr0,icc0 bne icc0,#0,__syscall_exit_work # restore all registers and return @@ -1110,7 +1111,9 @@ __entry_resume_userspace: __entry_return_from_user_interrupt: LEDS 0x6402 ldi @(gr15,#TI_FLAGS),gr4 - andicc gr4,#_TIF_WORK_MASK,gr0,icc0 + sethi.p %hi(_TIF_WORK_MASK),gr5 + setlo %lo(_TIF_WORK_MASK),gr5 + andcc gr4,gr5,gr0,icc0 beq icc0,#1,__entry_return_direct __entry_work_pending: @@ -1130,7 +1133,9 @@ __entry_work_resched: LEDS 0x6401 ldi @(gr15,#TI_FLAGS),gr4 - andicc gr4,#_TIF_WORK_MASK,gr0,icc0 + sethi.p %hi(_TIF_WORK_MASK),gr5 + setlo %lo(_TIF_WORK_MASK),gr5 + andcc gr4,gr5,gr0,icc0 beq icc0,#1,__entry_return_direct andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 bne icc0,#1,__entry_work_resched @@ -1158,9 +1163,7 @@ __syscall_trace_entry: # perform syscall exit tracing __syscall_exit_work: LEDS 0x6340 - andicc gr22,#PSR_PS,gr0,icc1 ; don't handle on return to kernel mode - andicc.p gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 - bne icc1,#0,__entry_return_direct + andicc gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 beq icc0,#1,__entry_work_pending movsg psr,gr23 diff --git a/trunk/arch/frv/kernel/signal.c b/trunk/arch/frv/kernel/signal.c index 864c2f0d497b..8cf5dca01758 100644 --- a/trunk/arch/frv/kernel/signal.c +++ b/trunk/arch/frv/kernel/signal.c @@ -28,6 +28,8 @@ #define DEBUG_SIG 0 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + struct fdpic_func_descriptor { unsigned long text; unsigned long GOT; @@ -147,6 +149,7 @@ asmlinkage int sys_sigreturn(void) __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(&frame->sc, &gr8)) @@ -169,6 +172,7 @@ asmlinkage int sys_rt_sigreturn(void) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) @@ -422,10 +426,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka) +static int handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka, sigset_t *oldset) { - sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ @@ -457,11 +460,11 @@ static void handle_signal(unsigned long sig, siginfo_t *info, else ret = setup_frame(sig, ka, oldset); - if (ret) - return; + if (ret == 0) + block_sigmask(ka, sig); + + return ret; - signal_delivered(sig, info, ka, __frame, - test_thread_flag(TIF_SINGLESTEP)); } /* end handle_signal() */ /*****************************************************************************/ @@ -474,14 +477,44 @@ static void do_signal(void) { struct k_sigaction ka; siginfo_t info; + sigset_t *oldset; int signr; + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(__frame)) + return; + + if (try_to_freeze()) + goto no_signal; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, __frame, NULL); if (signr > 0) { - handle_signal(signr, &info, &ka); + if (handle_signal(signr, &info, &ka, oldset) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + tracehook_signal_handler(signr, &info, &ka, __frame, + test_thread_flag(TIF_SINGLESTEP)); + } + return; } +no_signal: /* Did we come from a system call? */ if (__frame->syscallno != -1) { /* Restart the system call - no handlers present */ @@ -503,7 +536,11 @@ static void do_signal(void) /* if there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + } /* end do_signal() */ /*****************************************************************************/ @@ -518,13 +555,15 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) clear_thread_flag(TIF_SINGLESTEP); /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) do_signal(); /* deal with notification on about to resume userspace execution */ if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(__frame); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } /* end do_notify_resume() */ diff --git a/trunk/arch/h8300/include/asm/posix_types.h b/trunk/arch/h8300/include/asm/posix_types.h index 91e62ba4c7b0..bc4c34efb1ad 100644 --- a/trunk/arch/h8300/include/asm/posix_types.h +++ b/trunk/arch/h8300/include/asm/posix_types.h @@ -10,6 +10,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/h8300/kernel/signal.c b/trunk/arch/h8300/kernel/signal.c index fca10378701b..d4b0555d2904 100644 --- a/trunk/arch/h8300/kernel/signal.c +++ b/trunk/arch/h8300/kernel/signal.c @@ -47,6 +47,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* * Atomically swap in the new signal mask, and wait for a signal. */ @@ -184,6 +186,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...) sizeof(frame->extramask)))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc, &er0)) @@ -208,6 +211,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) @@ -408,9 +412,8 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, */ static void handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs * regs) + sigset_t *oldset, struct pt_regs * regs) { - sigset_t *oldset = sigmask_to_save(); int ret; /* are we from a system call? */ if (regs->orig_er0 >= 0) { @@ -438,8 +441,10 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, else ret = setup_frame(sig, ka, oldset, regs); - if (!ret) - signal_delivered(sig, info, ka, regs, 0); + if (!ret) { + block_sigmask(ka, sig); + clear_thread_flag(TIF_RESTORE_SIGMASK); + } } /* @@ -452,6 +457,7 @@ statis void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -462,14 +468,23 @@ statis void do_signal(struct pt_regs *regs) if ((regs->ccr & 0x10)) return; + if (try_to_freeze()) + goto no_signal; + current->thread.esp0 = (unsigned long) regs; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, regs); + handle_signal(signr, &info, &ka, oldset, regs); return; } + no_signal: /* Did we come from a system call? */ if (regs->orig_er0 >= 0) { /* Restart the system call - no handlers present */ @@ -486,7 +501,8 @@ statis void do_signal(struct pt_regs *regs) } /* If there's no signal to deliver, we just restore the saved mask. */ - restore_saved_sigmask(); + if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) + set_current_blocked(¤t->saved_sigmask); } asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) @@ -497,5 +513,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/hexagon/kernel/signal.c b/trunk/arch/hexagon/kernel/signal.c index 304b0808d072..434866eb0f1c 100644 --- a/trunk/arch/hexagon/kernel/signal.c +++ b/trunk/arch/hexagon/kernel/signal.c @@ -31,6 +31,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + struct rt_sigframe { unsigned long tramp[2]; struct siginfo info; @@ -147,9 +149,11 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, /* * Setup invocation of signal handler */ -static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs *regs) +static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs *regs) { + int rc; + /* * If we're handling a signal that aborted a system call, * set up the error return value before adding the signal @@ -182,12 +186,15 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, * Set up the stack frame; not doing the SA_SIGINFO thing. We * only set up the rt_frame flavor. */ + rc = setup_rt_frame(sig, ka, info, oldset, regs); + /* If there was an error on setup, no signal was delivered. */ - if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) - return; + if (rc) + return rc; + + block_sigmask(ka, sig); - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLESTEP)); + return 0; } /* @@ -202,13 +209,34 @@ static void do_signal(struct pt_regs *regs) if (!user_mode(regs)) return; + if (try_to_freeze()) + goto no_signal; + signo = get_signal_to_deliver(&info, &sigact, regs, NULL); if (signo > 0) { - handle_signal(signo, &info, &sigact, regs); + sigset_t *oldset; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + + if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) { + /* + * Successful delivery case. The saved sigmask is + * stored in the signal frame, and will be restored + * by sigreturn. We can clear the TIF flag. + */ + clear_thread_flag(TIF_RESTORE_SIGMASK); + + tracehook_signal_handler(signo, &info, &sigact, regs, + test_thread_flag(TIF_SINGLESTEP)); + } return; } +no_signal: /* * If we came from a system call, handle the restart. */ @@ -231,7 +259,10 @@ static void do_signal(struct pt_regs *regs) no_restart: /* If there's no signal to deliver, put the saved sigmask back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) @@ -242,6 +273,8 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } @@ -270,6 +303,7 @@ asmlinkage int sys_rt_sigreturn(void) if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked))) goto badframe; + sigdelsetmask(&blocked, ~_BLOCKABLE); set_current_blocked(&blocked); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) diff --git a/trunk/arch/ia64/include/asm/posix_types.h b/trunk/arch/ia64/include/asm/posix_types.h index 99ee1d6510cf..7323ab9467eb 100644 --- a/trunk/arch/ia64/include/asm/posix_types.h +++ b/trunk/arch/ia64/include/asm/posix_types.h @@ -1,6 +1,9 @@ #ifndef _ASM_IA64_POSIX_TYPES_H #define _ASM_IA64_POSIX_TYPES_H +typedef unsigned int __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ #include diff --git a/trunk/arch/ia64/include/asm/thread_info.h b/trunk/arch/ia64/include/asm/thread_info.h index f7ee85378311..310d9734f02d 100644 --- a/trunk/arch/ia64/include/asm/thread_info.h +++ b/trunk/arch/ia64/include/asm/thread_info.h @@ -141,23 +141,7 @@ static inline void set_restore_sigmask(void) { struct thread_info *ti = current_thread_info(); ti->status |= TS_RESTORE_SIGMASK; - WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags)); -} -static inline void clear_restore_sigmask(void) -{ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -} -static inline bool test_restore_sigmask(void) -{ - return current_thread_info()->status & TS_RESTORE_SIGMASK; -} -static inline bool test_and_clear_restore_sigmask(void) -{ - struct thread_info *ti = current_thread_info(); - if (!(ti->status & TS_RESTORE_SIGMASK)) - return false; - ti->status &= ~TS_RESTORE_SIGMASK; - return true; + set_bit(TIF_SIGPENDING, &ti->flags); } #endif /* !__ASSEMBLY__ */ diff --git a/trunk/arch/ia64/kernel/perfmon.c b/trunk/arch/ia64/kernel/perfmon.c index d7f558c1e711..f00ba025375d 100644 --- a/trunk/arch/ia64/kernel/perfmon.c +++ b/trunk/arch/ia64/kernel/perfmon.c @@ -604,6 +604,12 @@ pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) spin_unlock(&(x)->ctx_lock); } +static inline unsigned long +pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, unsigned long exec) +{ + return get_unmapped_area(file, addr, len, pgoff, flags); +} + /* forward declaration */ static const struct dentry_operations pfmfs_dentry_operations; @@ -2327,8 +2333,8 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t down_write(&task->mm->mmap_sem); /* find some free area in address space, must have mmap sem held */ - vma->vm_start = get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS); - if (IS_ERR_VALUE(vma->vm_start)) { + vma->vm_start = pfm_get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS, 0); + if (vma->vm_start == 0UL) { DPRINT(("Cannot find unmapped area for size %ld\n", size)); up_write(&task->mm->mmap_sem); goto error; diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c index dd6fc1449741..5e0e86ddb12f 100644 --- a/trunk/arch/ia64/kernel/process.c +++ b/trunk/arch/ia64/kernel/process.c @@ -199,6 +199,8 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) if (test_thread_flag(TIF_NOTIFY_RESUME)) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(&scr->pt); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } /* copy user rbs to kernel rbs */ diff --git a/trunk/arch/ia64/kernel/signal.c b/trunk/arch/ia64/kernel/signal.c index a199be1fe619..7523501d3bc0 100644 --- a/trunk/arch/ia64/kernel/signal.c +++ b/trunk/arch/ia64/kernel/signal.c @@ -30,6 +30,7 @@ #define DEBUG_SIG 0 #define STACK_ALIGN 16 /* minimal alignment for stack pointer */ +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #if _NSIG_WORDS > 1 # define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t)) @@ -199,6 +200,7 @@ ia64_rt_sigreturn (struct sigscratch *scr) if (GET_SIGSET(&set, &sc->sc_mask)) goto give_sigsegv; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(sc, scr)) @@ -413,13 +415,18 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, } static long -handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, +handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct sigscratch *scr) { - if (!setup_frame(sig, ka, info, sigmask_to_save(), scr)) + if (!setup_frame(sig, ka, info, oldset, scr)) return 0; - signal_delivered(sig, info, ka, &scr->pt, + block_sigmask(ka, sig); + + /* + * Let tracing know that we've done the handler setup. + */ + tracehook_signal_handler(sig, info, ka, &scr->pt, test_thread_flag(TIF_SINGLESTEP)); return 1; @@ -433,6 +440,7 @@ void ia64_do_signal (struct sigscratch *scr, long in_syscall) { struct k_sigaction ka; + sigset_t *oldset; siginfo_t info; long restart = in_syscall; long errno = scr->pt.r8; @@ -445,6 +453,11 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) if (!user_mode(&scr->pt)) return; + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + /* * This only loops in the rare cases of handle_signal() failing, in which case we * need to push through a forced SIGSEGV. @@ -494,8 +507,16 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) * Whee! Actually deliver the signal. If the delivery failed, we need to * continue to iterate in this loop so we can deliver the SIGSEGV... */ - if (handle_signal(signr, &ka, &info, scr)) + if (handle_signal(signr, &ka, &info, oldset, scr)) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; return; + } } /* Did we come from a system call? */ @@ -517,5 +538,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) /* if there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } diff --git a/trunk/arch/ia64/kernel/sys_ia64.c b/trunk/arch/ia64/kernel/sys_ia64.c index d9439ef2f661..609d50056a6c 100644 --- a/trunk/arch/ia64/kernel/sys_ia64.c +++ b/trunk/arch/ia64/kernel/sys_ia64.c @@ -171,9 +171,22 @@ asmlinkage unsigned long ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) { - addr = sys_mremap(addr, old_len, new_len, flags, new_addr); - if (!IS_ERR((void *) addr)) - force_successful_syscall_return(); + extern unsigned long do_mremap (unsigned long addr, + unsigned long old_len, + unsigned long new_len, + unsigned long flags, + unsigned long new_addr); + + down_write(¤t->mm->mmap_sem); + { + addr = do_mremap(addr, old_len, new_len, flags, new_addr); + } + up_write(¤t->mm->mmap_sem); + + if (IS_ERR((void *) addr)) + return addr; + + force_successful_syscall_return(); return addr; } diff --git a/trunk/arch/m32r/include/asm/posix_types.h b/trunk/arch/m32r/include/asm/posix_types.h index 236de26a409b..0195850e1f88 100644 --- a/trunk/arch/m32r/include/asm/posix_types.h +++ b/trunk/arch/m32r/include/asm/posix_types.h @@ -10,6 +10,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/m32r/kernel/signal.c b/trunk/arch/m32r/kernel/signal.c index f3fb2c029cfc..f54d96993ea1 100644 --- a/trunk/arch/m32r/kernel/signal.c +++ b/trunk/arch/m32r/kernel/signal.c @@ -28,6 +28,8 @@ #define DEBUG_SIG 0 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r2, unsigned long r3, unsigned long r4, @@ -109,6 +111,7 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result)) @@ -264,9 +267,9 @@ static int prev_insn(struct pt_regs *regs) * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, - struct pt_regs *regs) + sigset_t *oldset, struct pt_regs *regs) { /* Are we from a system call? */ if (regs->syscall_nr >= 0) { @@ -291,10 +294,11 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, } /* Set up the stack frame */ - if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs)) - return; + if (setup_rt_frame(sig, ka, info, oldset, regs)) + return -EFAULT; - signal_delivered(sig, info, ka, regs, 0); + block_sigmask(ka, sig); + return 0; } /* @@ -307,6 +311,7 @@ static void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -317,6 +322,14 @@ static void do_signal(struct pt_regs *regs) if (!user_mode(regs)) return; + if (try_to_freeze()) + goto no_signal; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Re-enable any watchpoints before delivering the @@ -326,11 +339,13 @@ static void do_signal(struct pt_regs *regs) */ /* Whee! Actually deliver the signal. */ - handle_signal(signr, &ka, &info, regs); + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) + clear_thread_flag(TIF_RESTORE_SIGMASK); return; } + no_signal: /* Did we come from a system call? */ if (regs->syscall_nr >= 0) { /* Restart the system call - no handlers present */ @@ -345,7 +360,10 @@ static void do_signal(struct pt_regs *regs) prev_insn(regs); } } - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* @@ -365,6 +383,8 @@ void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags) if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } clear_thread_flag(TIF_IRET); diff --git a/trunk/arch/m68k/Kconfig b/trunk/arch/m68k/Kconfig index 147120128260..cac5b6be572a 100644 --- a/trunk/arch/m68k/Kconfig +++ b/trunk/arch/m68k/Kconfig @@ -7,8 +7,6 @@ config M68K select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS select GENERIC_CPU_DEVICES - select GENERIC_STRNCPY_FROM_USER if MMU - select GENERIC_STRNLEN_USER if MMU select FPU if MMU select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE diff --git a/trunk/arch/m68k/include/asm/Kbuild b/trunk/arch/m68k/include/asm/Kbuild index eafa2539a8ee..1a922fad76f7 100644 --- a/trunk/arch/m68k/include/asm/Kbuild +++ b/trunk/arch/m68k/include/asm/Kbuild @@ -1,4 +1,2 @@ include include/asm-generic/Kbuild.asm header-y += cachectl.h - -generic-y += word-at-a-time.h diff --git a/trunk/arch/m68k/include/asm/m528xsim.h b/trunk/arch/m68k/include/asm/m528xsim.h index 497c31c803ff..d63b99ff7ff7 100644 --- a/trunk/arch/m68k/include/asm/m528xsim.h +++ b/trunk/arch/m68k/include/asm/m528xsim.h @@ -86,7 +86,7 @@ /* * QSPI module. */ -#define MCFQSPI_BASE (MCF_IPSBAR + 0x340) +#define MCFQSPI_IOBASE (MCF_IPSBAR + 0x340) #define MCFQSPI_SIZE 0x40 #define MCFQSPI_CS0 147 diff --git a/trunk/arch/m68k/include/asm/posix_types.h b/trunk/arch/m68k/include/asm/posix_types.h index cf4dbf70fdc7..6373093be72b 100644 --- a/trunk/arch/m68k/include/asm/posix_types.h +++ b/trunk/arch/m68k/include/asm/posix_types.h @@ -10,6 +10,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/m68k/include/asm/uaccess_mm.h b/trunk/arch/m68k/include/asm/uaccess_mm.h index 472c891a4aee..9c80cd515b20 100644 --- a/trunk/arch/m68k/include/asm/uaccess_mm.h +++ b/trunk/arch/m68k/include/asm/uaccess_mm.h @@ -379,15 +379,12 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n) #define copy_from_user(to, from, n) __copy_from_user(to, from, n) #define copy_to_user(to, from, n) __copy_to_user(to, from, n) -#define user_addr_max() \ - (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) - -extern long strncpy_from_user(char *dst, const char __user *src, long count); -extern __must_check long strlen_user(const char __user *str); -extern __must_check long strnlen_user(const char __user *str, long n); - +long strncpy_from_user(char *dst, const char __user *src, long count); +long strnlen_user(const char __user *src, long n); unsigned long __clear_user(void __user *to, unsigned long n); #define clear_user __clear_user +#define strlen_user(str) strnlen_user(str, 32767) + #endif /* _M68K_UACCESS_H */ diff --git a/trunk/arch/m68k/kernel/ptrace.c b/trunk/arch/m68k/kernel/ptrace.c index 1bc10e62b9af..8b4a2222e658 100644 --- a/trunk/arch/m68k/kernel/ptrace.c +++ b/trunk/arch/m68k/kernel/ptrace.c @@ -286,7 +286,7 @@ asmlinkage void syscall_trace(void) } } -#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) +#ifdef CONFIG_COLDFIRE asmlinkage int syscall_trace_enter(void) { int ret = 0; diff --git a/trunk/arch/m68k/kernel/signal.c b/trunk/arch/m68k/kernel/signal.c index 710a528b928b..d9f3d1900eed 100644 --- a/trunk/arch/m68k/kernel/signal.c +++ b/trunk/arch/m68k/kernel/signal.c @@ -51,6 +51,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + #ifdef CONFIG_MMU /* @@ -793,6 +795,7 @@ asmlinkage int do_sigreturn(unsigned long __unused) sizeof(frame->extramask)))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc, frame + 1)) @@ -817,6 +820,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (rt_restore_ucontext(regs, sw, &frame->uc)) @@ -1119,9 +1123,8 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) */ static void handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, - struct pt_regs *regs) + sigset_t *oldset, struct pt_regs *regs) { - sigset_t *oldset = sigmask_to_save(); int err; /* are we from a system call? */ if (regs->orig_d0 >= 0) @@ -1137,12 +1140,14 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, if (err) return; - signal_delivered(sig, info, ka, regs, 0); + block_sigmask(ka, sig); if (test_thread_flag(TIF_DELAYED_TRACE)) { regs->sr &= ~0x8000; send_sig(SIGTRAP, current, 1); } + + clear_thread_flag(TIF_RESTORE_SIGMASK); } /* @@ -1155,13 +1160,19 @@ static void do_signal(struct pt_regs *regs) siginfo_t info; struct k_sigaction ka; int signr; + sigset_t *oldset; current->thread.esp0 = (unsigned long) regs; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, &ka, &info, regs); + handle_signal(signr, &ka, &info, oldset, regs); return; } @@ -1171,7 +1182,10 @@ static void do_signal(struct pt_regs *regs) handle_restart(regs, NULL, 0); /* If there's no signal to deliver, we just restore the saved mask. */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } void do_notify_resume(struct pt_regs *regs) @@ -1179,6 +1193,9 @@ void do_notify_resume(struct pt_regs *regs) if (test_thread_flag(TIF_SIGPENDING)) do_signal(regs); - if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) + if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); + } } diff --git a/trunk/arch/m68k/kernel/time.c b/trunk/arch/m68k/kernel/time.c index 707f0573ec6b..d7deb7fc7eb5 100644 --- a/trunk/arch/m68k/kernel/time.c +++ b/trunk/arch/m68k/kernel/time.c @@ -85,7 +85,7 @@ void __init time_init(void) mach_sched_init(timer_interrupt); } -#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET +#ifdef CONFIG_M68KCLASSIC u32 arch_gettimeoffset(void) { @@ -108,4 +108,4 @@ static int __init rtc_init(void) module_init(rtc_init); -#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ +#endif /* CONFIG_M68KCLASSIC */ diff --git a/trunk/arch/m68k/lib/uaccess.c b/trunk/arch/m68k/lib/uaccess.c index 5e97f2ee7c11..5664386338da 100644 --- a/trunk/arch/m68k/lib/uaccess.c +++ b/trunk/arch/m68k/lib/uaccess.c @@ -103,6 +103,80 @@ unsigned long __generic_copy_to_user(void __user *to, const void *from, } EXPORT_SYMBOL(__generic_copy_to_user); +/* + * Copy a null terminated string from userspace. + */ +long strncpy_from_user(char *dst, const char __user *src, long count) +{ + long res; + char c; + + if (count <= 0) + return count; + + asm volatile ("\n" + "1: "MOVES".b (%2)+,%4\n" + " move.b %4,(%1)+\n" + " jeq 2f\n" + " subq.l #1,%3\n" + " jne 1b\n" + "2: sub.l %3,%0\n" + "3:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "10: move.l %5,%0\n" + " jra 3b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,10b\n" + " .previous" + : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c) + : "i" (-EFAULT), "0" (count)); + + return res; +} +EXPORT_SYMBOL(strncpy_from_user); + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 on exception, a value greater than N if too long + */ +long strnlen_user(const char __user *src, long n) +{ + char c; + long res; + + asm volatile ("\n" + "1: subq.l #1,%1\n" + " jmi 3f\n" + "2: "MOVES".b (%0)+,%2\n" + " tst.b %2\n" + " jne 1b\n" + " jra 4f\n" + "\n" + "3: addq.l #1,%0\n" + "4: sub.l %4,%0\n" + "5:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "20: sub.l %0,%0\n" + " jra 5b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 2b,20b\n" + " .previous\n" + : "=&a" (res), "+d" (n), "=&d" (c) + : "0" (src), "r" (src)); + + return res; +} +EXPORT_SYMBOL(strnlen_user); + /* * Zero Userspace */ diff --git a/trunk/arch/m68k/platform/68328/timers.c b/trunk/arch/m68k/platform/68328/timers.c index f4dc9b295609..c801c172b822 100644 --- a/trunk/arch/m68k/platform/68328/timers.c +++ b/trunk/arch/m68k/platform/68328/timers.c @@ -53,7 +53,6 @@ #endif static u32 m68328_tick_cnt; -static irq_handler_t timer_interrupt; /***************************************************************************/ @@ -63,7 +62,7 @@ static irqreturn_t hw_tick(int irq, void *dummy) TSTAT &= 0; m68328_tick_cnt += TICKS_PER_JIFFY; - return timer_interrupt(irq, dummy); + return arch_timer_interrupt(irq, dummy); } /***************************************************************************/ @@ -100,7 +99,7 @@ static struct clocksource m68328_clk = { /***************************************************************************/ -void hw_timer_init(irq_handler_t handler) +void hw_timer_init(void) { /* disable timer 1 */ TCTL = 0; @@ -116,7 +115,6 @@ void hw_timer_init(irq_handler_t handler) /* Enable timer 1 */ TCTL |= TCTL_TEN; clocksource_register_hz(&m68328_clk, TICKS_PER_JIFFY*HZ); - timer_interrupt = handler; } /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/68360/config.c b/trunk/arch/m68k/platform/68360/config.c index 9877cefad1e7..255fc03913e9 100644 --- a/trunk/arch/m68k/platform/68360/config.c +++ b/trunk/arch/m68k/platform/68360/config.c @@ -35,7 +35,6 @@ extern void m360_cpm_reset(void); #define OSCILLATOR (unsigned long int)33000000 #endif -static irq_handler_t timer_interrupt; unsigned long int system_clock; extern QUICC *pquicc; @@ -53,7 +52,7 @@ static irqreturn_t hw_tick(int irq, void *dummy) pquicc->timer_ter1 = 0x0002; /* clear timer event */ - return timer_interrupt(irq, dummy); + return arch_timer_interrupt(irq, dummy); } static struct irqaction m68360_timer_irq = { @@ -62,7 +61,7 @@ static struct irqaction m68360_timer_irq = { .handler = hw_tick, }; -void hw_timer_init(irq_handler_t handler) +void hw_timer_init(void) { unsigned char prescaler; unsigned short tgcr_save; @@ -95,8 +94,6 @@ void hw_timer_init(irq_handler_t handler) pquicc->timer_ter1 = 0x0003; /* clear timer events */ - timer_interrupt = handler; - /* enable timer 1 interrupt in CIMR */ setup_irq(CPMVEC_TIMER1, &m68360_timer_irq); diff --git a/trunk/arch/microblaze/include/asm/thread_info.h b/trunk/arch/microblaze/include/asm/thread_info.h index 6c610234ffab..1a8ab6a5c03f 100644 --- a/trunk/arch/microblaze/include/asm/thread_info.h +++ b/trunk/arch/microblaze/include/asm/thread_info.h @@ -166,23 +166,7 @@ static inline void set_restore_sigmask(void) { struct thread_info *ti = current_thread_info(); ti->status |= TS_RESTORE_SIGMASK; - WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags)); -} -static inline void clear_restore_sigmask(void) -{ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -} -static inline bool test_restore_sigmask(void) -{ - return current_thread_info()->status & TS_RESTORE_SIGMASK; -} -static inline bool test_and_clear_restore_sigmask(void) -{ - struct thread_info *ti = current_thread_info(); - if (!(ti->status & TS_RESTORE_SIGMASK)) - return false; - ti->status &= ~TS_RESTORE_SIGMASK; - return true; + set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); } #endif diff --git a/trunk/arch/microblaze/kernel/signal.c b/trunk/arch/microblaze/kernel/signal.c index 76b9722557db..7f4c7bef1642 100644 --- a/trunk/arch/microblaze/kernel/signal.c +++ b/trunk/arch/microblaze/kernel/signal.c @@ -41,6 +41,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs) @@ -104,6 +106,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) @@ -307,11 +310,10 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, struct pt_regs *regs) + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - sigset_t *oldset = sigmask_to_save(); int ret; /* Set up the stack frame */ @@ -321,9 +323,11 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ret = setup_rt_frame(sig, ka, NULL, oldset, regs); if (ret) - return; + return ret; - signal_delivered(sig, info, ka, regs, 0); + block_sigmask(ka, sig); + + return 0; } /* @@ -340,18 +344,33 @@ static void do_signal(struct pt_regs *regs, int in_syscall) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; #ifdef DEBUG_SIG printk(KERN_INFO "do signal: %p %d\n", regs, in_syscall); printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, regs->r12, current_thread_info()->flags); #endif + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ if (in_syscall) handle_restart(regs, &ka, 1); - handle_signal(signr, &ka, &info, regs); + if (!handle_signal(signr, &ka, &info, oldset, regs)) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= + ~TS_RESTORE_SIGMASK; + } return; } @@ -362,7 +381,10 @@ static void do_signal(struct pt_regs *regs, int in_syscall) * If there's no signal to deliver, we just put the saved sigmask * back. */ - restore_saved_sigmask(); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } void do_notify_resume(struct pt_regs *regs, int in_syscall) @@ -379,6 +401,9 @@ void do_notify_resume(struct pt_regs *regs, int in_syscall) if (test_thread_flag(TIF_SIGPENDING)) do_signal(regs, in_syscall); - if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) + if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); + } } diff --git a/trunk/arch/mips/alchemy/devboards/db1200.c b/trunk/arch/mips/alchemy/devboards/db1200.c index bf2248474fa8..7dde01642d6b 100644 --- a/trunk/arch/mips/alchemy/devboards/db1200.c +++ b/trunk/arch/mips/alchemy/devboards/db1200.c @@ -213,6 +213,8 @@ static int au1200_nand_device_ready(struct mtd_info *mtd) return __raw_readl((void __iomem *)MEM_STSTAT) & 1; } +static const char *db1200_part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition db1200_nand_parts[] = { { .name = "NAND FS 0", @@ -233,6 +235,7 @@ struct platform_nand_data db1200_nand_platdata = { .nr_partitions = ARRAY_SIZE(db1200_nand_parts), .partitions = db1200_nand_parts, .chip_delay = 20, + .part_probe_types = db1200_part_probes, }, .ctrl = { .dev_ready = au1200_nand_device_ready, diff --git a/trunk/arch/mips/alchemy/devboards/db1300.c b/trunk/arch/mips/alchemy/devboards/db1300.c index c56e0246694e..0893f2af0d01 100644 --- a/trunk/arch/mips/alchemy/devboards/db1300.c +++ b/trunk/arch/mips/alchemy/devboards/db1300.c @@ -145,6 +145,8 @@ static int au1300_nand_device_ready(struct mtd_info *mtd) return __raw_readl((void __iomem *)MEM_STSTAT) & 1; } +static const char *db1300_part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition db1300_nand_parts[] = { { .name = "NAND FS 0", @@ -165,6 +167,7 @@ struct platform_nand_data db1300_nand_platdata = { .nr_partitions = ARRAY_SIZE(db1300_nand_parts), .partitions = db1300_nand_parts, .chip_delay = 20, + .part_probe_types = db1300_part_probes, }, .ctrl = { .dev_ready = au1300_nand_device_ready, diff --git a/trunk/arch/mips/alchemy/devboards/db1550.c b/trunk/arch/mips/alchemy/devboards/db1550.c index 9eb79062f46e..6815d0783cd8 100644 --- a/trunk/arch/mips/alchemy/devboards/db1550.c +++ b/trunk/arch/mips/alchemy/devboards/db1550.c @@ -149,6 +149,8 @@ static int au1550_nand_device_ready(struct mtd_info *mtd) return __raw_readl((void __iomem *)MEM_STSTAT) & 1; } +static const char *db1550_part_probes[] = { "cmdlinepart", NULL }; + static struct mtd_partition db1550_nand_parts[] = { { .name = "NAND FS 0", @@ -169,6 +171,7 @@ struct platform_nand_data db1550_nand_platdata = { .nr_partitions = ARRAY_SIZE(db1550_nand_parts), .partitions = db1550_nand_parts, .chip_delay = 20, + .part_probe_types = db1550_part_probes, }, .ctrl = { .dev_ready = au1550_nand_device_ready, diff --git a/trunk/arch/mips/include/asm/posix_types.h b/trunk/arch/mips/include/asm/posix_types.h index fa03ec3fbf89..e0308dcca135 100644 --- a/trunk/arch/mips/include/asm/posix_types.h +++ b/trunk/arch/mips/include/asm/posix_types.h @@ -17,6 +17,11 @@ * assume GCC is being used. */ +#if (_MIPS_SZLONG == 64) +typedef unsigned int __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t +#endif + typedef long __kernel_daddr_t; #define __kernel_daddr_t __kernel_daddr_t diff --git a/trunk/arch/mips/include/asm/stat.h b/trunk/arch/mips/include/asm/stat.h index fe9a4c3ec5a1..6e00f751ab6d 100644 --- a/trunk/arch/mips/include/asm/stat.h +++ b/trunk/arch/mips/include/asm/stat.h @@ -20,7 +20,7 @@ struct stat { long st_pad1[3]; /* Reserved for network id */ ino_t st_ino; mode_t st_mode; - __u32 st_nlink; + nlink_t st_nlink; uid_t st_uid; gid_t st_gid; unsigned st_rdev; @@ -55,7 +55,7 @@ struct stat64 { unsigned long long st_ino; mode_t st_mode; - __u32 st_nlink; + nlink_t st_nlink; uid_t st_uid; gid_t st_gid; @@ -96,7 +96,7 @@ struct stat { unsigned long st_ino; mode_t st_mode; - __u32 st_nlink; + nlink_t st_nlink; uid_t st_uid; gid_t st_gid; diff --git a/trunk/arch/mips/kernel/signal-common.h b/trunk/arch/mips/kernel/signal-common.h index 9c60d09e62a7..10263b405981 100644 --- a/trunk/arch/mips/kernel/signal-common.h +++ b/trunk/arch/mips/kernel/signal-common.h @@ -19,6 +19,8 @@ # define DEBUGP(fmt, args...) #endif +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* * Determine which stack to use.. */ diff --git a/trunk/arch/mips/kernel/signal.c b/trunk/arch/mips/kernel/signal.c index f2c09cfc60ac..17f6ee30ad0d 100644 --- a/trunk/arch/mips/kernel/signal.c +++ b/trunk/arch/mips/kernel/signal.c @@ -339,6 +339,7 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs) if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) goto badframe; + sigdelsetmask(&blocked, ~_BLOCKABLE); set_current_blocked(&blocked); sig = restore_sigcontext(®s, &frame->sf_sc); @@ -374,6 +375,7 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext); @@ -512,10 +514,9 @@ struct mips_abi mips_abi = { .restart = __NR_restart_syscall }; -static void handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka, struct pt_regs *regs) +static int handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { - sigset_t *oldset = sigmask_to_save(); int ret; struct mips_abi *abi = current->thread.abi; void *vdso = current->mm->context.vdso; @@ -549,14 +550,17 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ka, regs, sig, oldset); if (ret) - return; + return ret; + + block_sigmask(ka, sig); - signal_delivered(sig, info, ka, regs, 0); + return ret; } static void do_signal(struct pt_regs *regs) { struct k_sigaction ka; + sigset_t *oldset; siginfo_t info; int signr; @@ -568,10 +572,25 @@ static void do_signal(struct pt_regs *regs) if (!user_mode(regs)) return; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, regs); + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + return; } @@ -595,7 +614,10 @@ static void do_signal(struct pt_regs *regs) * If there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* @@ -608,12 +630,14 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, local_irq_enable(); /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) do_signal(regs); if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/mips/kernel/signal32.c b/trunk/arch/mips/kernel/signal32.c index da1b56a39ac7..b4fe2eacbd5d 100644 --- a/trunk/arch/mips/kernel/signal32.c +++ b/trunk/arch/mips/kernel/signal32.c @@ -465,6 +465,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask)) goto badframe; + sigdelsetmask(&blocked, ~_BLOCKABLE); set_current_blocked(&blocked); sig = restore_sigcontext32(®s, &frame->sf_sc); @@ -502,6 +503,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); diff --git a/trunk/arch/mips/kernel/signal_n32.c b/trunk/arch/mips/kernel/signal_n32.c index 3574c145511b..63ffac9af7c5 100644 --- a/trunk/arch/mips/kernel/signal_n32.c +++ b/trunk/arch/mips/kernel/signal_n32.c @@ -109,6 +109,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext); diff --git a/trunk/arch/mips/pnx833x/common/platform.c b/trunk/arch/mips/pnx833x/common/platform.c index 05a1d922cd60..87167dcc79fa 100644 --- a/trunk/arch/mips/pnx833x/common/platform.c +++ b/trunk/arch/mips/pnx833x/common/platform.c @@ -244,6 +244,11 @@ static struct platform_device pnx833x_sata_device = { .resource = pnx833x_sata_resources, }; +static const char *part_probes[] = { + "cmdlinepart", + NULL +}; + static void pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) { @@ -263,6 +268,7 @@ static struct platform_nand_data pnx833x_flash_nand_data = { .chip = { .nr_chips = 1, .chip_delay = 25, + .part_probe_types = part_probes, }, .ctrl = { .cmd_ctrl = pnx833x_flash_nand_cmd_ctrl diff --git a/trunk/arch/mips/rb532/devices.c b/trunk/arch/mips/rb532/devices.c index 716e9a12f0e7..ea774285e6c5 100644 --- a/trunk/arch/mips/rb532/devices.c +++ b/trunk/arch/mips/rb532/devices.c @@ -293,6 +293,7 @@ static void __init rb532_nand_setup(void) rb532_nand_data.chip.nr_partitions = ARRAY_SIZE(rb532_partition_info); rb532_nand_data.chip.partitions = rb532_partition_info; rb532_nand_data.chip.chip_delay = NAND_CHIP_DELAY; + rb532_nand_data.chip.options = NAND_NO_AUTOINCR; } diff --git a/trunk/arch/mn10300/include/asm/posix_types.h b/trunk/arch/mn10300/include/asm/posix_types.h index d31eeea480cf..ab506181ec31 100644 --- a/trunk/arch/mn10300/include/asm/posix_types.h +++ b/trunk/arch/mn10300/include/asm/posix_types.h @@ -20,6 +20,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/mn10300/kernel/signal.c b/trunk/arch/mn10300/kernel/signal.c index 6ab0bee2a54f..890cf91767cc 100644 --- a/trunk/arch/mn10300/kernel/signal.c +++ b/trunk/arch/mn10300/kernel/signal.c @@ -31,6 +31,8 @@ #define DEBUG_SIG 0 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* * atomically swap in the new signal mask, and wait for a signal. */ @@ -161,6 +163,7 @@ asmlinkage long sys_sigreturn(void) sizeof(frame->extramask))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(current_frame(), &frame->sc, &d0)) @@ -188,6 +191,7 @@ asmlinkage long sys_rt_sigreturn(void) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0)) @@ -426,9 +430,8 @@ static inline void stepback(struct pt_regs *regs) */ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs *regs) + sigset_t *oldset, struct pt_regs *regs) { - sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ @@ -458,11 +461,11 @@ static int handle_signal(int sig, ret = setup_rt_frame(sig, ka, info, oldset, regs); else ret = setup_frame(sig, ka, oldset, regs); - if (ret) - return; - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLESTEP)); + if (ret == 0) + block_sigmask(ka, sig); + + return ret; } /* @@ -472,6 +475,7 @@ static void do_signal(struct pt_regs *regs) { struct k_sigaction ka; siginfo_t info; + sigset_t *oldset; int signr; /* we want the common case to go fast, which is why we may in certain @@ -479,9 +483,23 @@ static void do_signal(struct pt_regs *regs) if (!user_mode(regs)) return; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - if (handle_signal(signr, &info, &ka, regs) == 0) { + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLESTEP)); } return; @@ -507,7 +525,10 @@ static void do_signal(struct pt_regs *regs) /* if there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* @@ -527,11 +548,13 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) } /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) do_signal(regs); if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(current_frame()); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/openrisc/kernel/signal.c b/trunk/arch/openrisc/kernel/signal.c index 30110297f4f9..e970743251ae 100644 --- a/trunk/arch/openrisc/kernel/signal.c +++ b/trunk/arch/openrisc/kernel/signal.c @@ -33,6 +33,8 @@ #define DEBUG_SIG 0 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + asmlinkage long _sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs) { @@ -99,6 +101,7 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) @@ -248,19 +251,20 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return -EFAULT; } -static inline void +static inline int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs *regs) + sigset_t *oldset, struct pt_regs *regs) { int ret; - ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); + ret = setup_rt_frame(sig, ka, info, oldset, regs); if (ret) - return; + return ret; + + block_sigmask(ka, sig); - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLESTEP)); + return 0; } /* @@ -335,10 +339,30 @@ void do_signal(struct pt_regs *regs) if (signr <= 0) { /* no signal to deliver so we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + } else { /* signr > 0 */ + sigset_t *oldset; + + if (current_thread_info()->flags & _TIF_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, regs); + if (!handle_signal(signr, &info, &ka, oldset, regs)) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLESTEP)); } return; @@ -352,5 +376,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs) if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/parisc/Makefile b/trunk/arch/parisc/Makefile index 5707f1a62341..dbc3850b1d0d 100644 --- a/trunk/arch/parisc/Makefile +++ b/trunk/arch/parisc/Makefile @@ -21,7 +21,6 @@ KBUILD_DEFCONFIG := default_defconfig NM = sh $(srctree)/arch/parisc/nm CHECKFLAGS += -D__hppa__=1 -LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) MACHINE := $(shell uname -m) ifeq ($(MACHINE),parisc*) @@ -80,7 +79,7 @@ kernel-y := mm/ kernel/ math-emu/ kernel-$(CONFIG_HPUX) += hpux/ core-y += $(addprefix arch/parisc/, $(kernel-y)) -libs-y += arch/parisc/lib/ $(LIBGCC) +libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name` drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/ diff --git a/trunk/arch/parisc/include/asm/Kbuild b/trunk/arch/parisc/include/asm/Kbuild index 4383707d9801..19a434f55059 100644 --- a/trunk/arch/parisc/include/asm/Kbuild +++ b/trunk/arch/parisc/include/asm/Kbuild @@ -1,4 +1,3 @@ include include/asm-generic/Kbuild.asm header-y += pdc.h -generic-y += word-at-a-time.h diff --git a/trunk/arch/parisc/include/asm/bug.h b/trunk/arch/parisc/include/asm/bug.h index 62a33338549c..72cfdb0cfdd1 100644 --- a/trunk/arch/parisc/include/asm/bug.h +++ b/trunk/arch/parisc/include/asm/bug.h @@ -1,8 +1,6 @@ #ifndef _PARISC_BUG_H #define _PARISC_BUG_H -#include /* for BUGFLAG_TAINT */ - /* * Tell the user there is some problem. * The offending file and line are encoded in the __bug_table section. diff --git a/trunk/arch/parisc/include/asm/posix_types.h b/trunk/arch/parisc/include/asm/posix_types.h index b9344256f76b..5212b0357daf 100644 --- a/trunk/arch/parisc/include/asm/posix_types.h +++ b/trunk/arch/parisc/include/asm/posix_types.h @@ -10,6 +10,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/parisc/include/asm/stat.h b/trunk/arch/parisc/include/asm/stat.h index d76fbda5d62c..9d5fbbc5c31f 100644 --- a/trunk/arch/parisc/include/asm/stat.h +++ b/trunk/arch/parisc/include/asm/stat.h @@ -7,7 +7,7 @@ struct stat { unsigned int st_dev; /* dev_t is 32 bits on parisc */ ino_t st_ino; /* 32 bits */ mode_t st_mode; /* 16 bits */ - unsigned short st_nlink; /* 16 bits */ + nlink_t st_nlink; /* 16 bits */ unsigned short st_reserved1; /* old st_uid */ unsigned short st_reserved2; /* old st_gid */ unsigned int st_rdev; @@ -42,7 +42,7 @@ struct hpux_stat64 { unsigned int st_dev; /* dev_t is 32 bits on parisc */ ino_t st_ino; /* 32 bits */ mode_t st_mode; /* 16 bits */ - unsigned short st_nlink; /* 16 bits */ + nlink_t st_nlink; /* 16 bits */ unsigned short st_reserved1; /* old st_uid */ unsigned short st_reserved2; /* old st_gid */ unsigned int st_rdev; diff --git a/trunk/arch/parisc/include/asm/thread_info.h b/trunk/arch/parisc/include/asm/thread_info.h index 22b4726dee49..83ae7dd4d99e 100644 --- a/trunk/arch/parisc/include/asm/thread_info.h +++ b/trunk/arch/parisc/include/asm/thread_info.h @@ -74,7 +74,7 @@ struct thread_info { #define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \ - _TIF_NEED_RESCHED) + _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK) #endif /* __KERNEL__ */ diff --git a/trunk/arch/parisc/kernel/entry.S b/trunk/arch/parisc/kernel/entry.S index 18670a078849..07ef351edd57 100644 --- a/trunk/arch/parisc/kernel/entry.S +++ b/trunk/arch/parisc/kernel/entry.S @@ -924,7 +924,7 @@ intr_check_sig: /* As above */ mfctl %cr30,%r1 LDREG TI_FLAGS(%r1),%r19 - ldi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r20 + ldi (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NOTIFY_RESUME), %r20 and,COND(<>) %r19, %r20, %r0 b,n intr_restore /* skip past if we've nothing to do */ @@ -2032,7 +2032,7 @@ syscall_check_resched: .import do_signal,code syscall_check_sig: LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 - ldi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r26 + ldi (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r26 and,COND(<>) %r19, %r26, %r0 b,n syscall_restore /* skip past if we've nothing to do */ diff --git a/trunk/arch/parisc/kernel/signal.c b/trunk/arch/parisc/kernel/signal.c index 594459bde14e..4b9cb0d546d1 100644 --- a/trunk/arch/parisc/kernel/signal.c +++ b/trunk/arch/parisc/kernel/signal.c @@ -48,6 +48,9 @@ #define DBG(LEVEL, ...) #endif + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* gcc will complain if a pointer is cast to an integer of different * size. If you really need to do this (and we do for an ELF32 user * application in an ELF64 kernel) then you have to do a cast to an @@ -128,6 +131,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) goto give_sigsegv; } + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); /* Good thing we saved the old gr[30], eh? */ @@ -439,9 +443,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static long handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs *regs, int in_syscall) + sigset_t *oldset, struct pt_regs *regs, int in_syscall) { - sigset_t *oldset = sigmask_to_save(); DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n", sig, ka, info, oldset, regs); @@ -449,13 +452,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) return 0; - signal_delivered(sig, info, ka, regs, + block_sigmask(ka, sig); + + tracehook_signal_handler(sig, info, ka, regs, test_thread_flag(TIF_SINGLESTEP) || test_thread_flag(TIF_BLOCKSTEP)); - DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", - regs->gr[28]); - return 1; } @@ -566,17 +568,28 @@ do_signal(struct pt_regs *regs, long in_syscall) siginfo_t info; struct k_sigaction ka; int signr; + sigset_t *oldset; - DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n", - regs, regs->sr[7], in_syscall); + DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n", + oldset, regs, regs->sr[7], in_syscall); /* Everyone else checks to see if they are in kernel mode at this point and exits if that's the case. I'm not sure why we would be called in that case, but for some reason we are. */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + + DBG(1,"do_signal: oldset %08lx / %08lx\n", + oldset->sig[0], oldset->sig[1]); + + /* May need to force signal if handle_signal failed to deliver */ while (1) { + signr = get_signal_to_deliver(&info, &ka, regs, NULL); DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); @@ -590,8 +603,14 @@ do_signal(struct pt_regs *regs, long in_syscall) /* Whee! Actually deliver the signal. If the delivery failed, we need to continue to iterate in this loop so we can deliver the SIGSEGV... */ - if (handle_signal(signr, &info, &ka, regs, in_syscall)) + if (handle_signal(signr, &info, &ka, oldset, + regs, in_syscall)) { + DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", + regs->gr[28]); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); return; + } } /* end of while(1) looping forever if we can't force a signal */ @@ -602,16 +621,24 @@ do_signal(struct pt_regs *regs, long in_syscall) DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", regs->gr[28]); - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + + return; } void do_notify_resume(struct pt_regs *regs, long in_syscall) { - if (test_thread_flag(TIF_SIGPENDING)) + if (test_thread_flag(TIF_SIGPENDING) || + test_thread_flag(TIF_RESTORE_SIGMASK)) do_signal(regs, in_syscall); if (test_thread_flag(TIF_NOTIFY_RESUME)) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/parisc/kernel/signal32.c b/trunk/arch/parisc/kernel/signal32.c index fd49aeda9eb8..e14132430762 100644 --- a/trunk/arch/parisc/kernel/signal32.c +++ b/trunk/arch/parisc/kernel/signal32.c @@ -47,6 +47,8 @@ #define DBG(LEVEL, ...) #endif +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + inline void sigset_32to64(sigset_t *s64, compat_sigset_t *s32) { diff --git a/trunk/arch/powerpc/include/asm/hw_irq.h b/trunk/arch/powerpc/include/asm/hw_irq.h index 32b394f3b854..c9aac24b02e2 100644 --- a/trunk/arch/powerpc/include/asm/hw_irq.h +++ b/trunk/arch/powerpc/include/asm/hw_irq.h @@ -100,9 +100,6 @@ static inline void hard_irq_disable(void) get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; } -/* include/linux/interrupt.h needs hard_irq_disable to be a macro */ -#define hard_irq_disable hard_irq_disable - /* * This is called by asynchronous interrupts to conditionally * re-enable hard interrupts when soft-disabled after having diff --git a/trunk/arch/powerpc/include/asm/posix_types.h b/trunk/arch/powerpc/include/asm/posix_types.h index 2958c5b97b2d..f1393252bbda 100644 --- a/trunk/arch/powerpc/include/asm/posix_types.h +++ b/trunk/arch/powerpc/include/asm/posix_types.h @@ -16,6 +16,9 @@ typedef int __kernel_ssize_t; typedef long __kernel_ptrdiff_t; #define __kernel_size_t __kernel_size_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t #endif diff --git a/trunk/arch/powerpc/include/asm/stat.h b/trunk/arch/powerpc/include/asm/stat.h index 84880b80cc1c..e4edc510b530 100644 --- a/trunk/arch/powerpc/include/asm/stat.h +++ b/trunk/arch/powerpc/include/asm/stat.h @@ -30,11 +30,11 @@ struct stat { unsigned long st_dev; ino_t st_ino; #ifdef __powerpc64__ - unsigned long st_nlink; + nlink_t st_nlink; mode_t st_mode; #else mode_t st_mode; - unsigned short st_nlink; + nlink_t st_nlink; #endif uid_t st_uid; gid_t st_gid; diff --git a/trunk/arch/powerpc/include/asm/thread_info.h b/trunk/arch/powerpc/include/asm/thread_info.h index 68831e9cf82f..a556ccc16b58 100644 --- a/trunk/arch/powerpc/include/asm/thread_info.h +++ b/trunk/arch/powerpc/include/asm/thread_info.h @@ -140,23 +140,7 @@ static inline void set_restore_sigmask(void) { struct thread_info *ti = current_thread_info(); ti->local_flags |= _TLF_RESTORE_SIGMASK; - WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags)); -} -static inline void clear_restore_sigmask(void) -{ - current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK; -} -static inline bool test_restore_sigmask(void) -{ - return current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK; -} -static inline bool test_and_clear_restore_sigmask(void) -{ - struct thread_info *ti = current_thread_info(); - if (!(ti->local_flags & _TLF_RESTORE_SIGMASK)) - return false; - ti->local_flags &= ~_TLF_RESTORE_SIGMASK; - return true; + set_bit(TIF_SIGPENDING, &ti->flags); } static inline bool test_thread_local_flags(unsigned int flags) diff --git a/trunk/arch/powerpc/kernel/module_32.c b/trunk/arch/powerpc/kernel/module_32.c index 2e3200ca485f..0b6d79617d7b 100644 --- a/trunk/arch/powerpc/kernel/module_32.c +++ b/trunk/arch/powerpc/kernel/module_32.c @@ -176,8 +176,8 @@ int module_frob_arch_sections(Elf32_Ehdr *hdr, static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) { - if (entry->jump[0] == 0x3d800000 + ((val + 0x8000) >> 16) - && entry->jump[1] == 0x398c0000 + (val & 0xffff)) + if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) + && entry->jump[1] == 0x396b0000 + (val & 0xffff)) return 1; return 0; } @@ -204,9 +204,10 @@ static uint32_t do_plt_call(void *location, entry++; } - entry->jump[0] = 0x3d800000+((val+0x8000)>>16); /* lis r12,sym@ha */ - entry->jump[1] = 0x398c0000 + (val&0xffff); /* addi r12,r12,sym@l*/ - entry->jump[2] = 0x7d8903a6; /* mtctr r12 */ + /* Stolen from Paul Mackerras as well... */ + entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ + entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ + entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ entry->jump[3] = 0x4e800420; /* bctr */ DEBUGP("Initialized plt for 0x%x at %p\n", val, entry); diff --git a/trunk/arch/powerpc/kernel/signal.c b/trunk/arch/powerpc/kernel/signal.c index 5c023c9cf16e..651c5963662b 100644 --- a/trunk/arch/powerpc/kernel/signal.c +++ b/trunk/arch/powerpc/kernel/signal.c @@ -51,6 +51,16 @@ void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, return (void __user *)newsp; } + +/* + * Restore the user process's signal mask + */ +void restore_sigmask(sigset_t *set) +{ + sigdelsetmask(set, ~_BLOCKABLE); + set_current_blocked(set); +} + static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) { @@ -104,21 +114,30 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, static int do_signal(struct pt_regs *regs) { - sigset_t *oldset = sigmask_to_save(); + sigset_t *oldset; siginfo_t info; int signr; struct k_sigaction ka; int ret; int is32 = is_32bit_task(); + if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* Is there any syscall restart business here ? */ check_syscall_restart(regs, &ka, signr > 0); if (signr <= 0) { + struct thread_info *ti = current_thread_info(); /* No signal to deliver -- put the saved sigmask back */ - restore_saved_sigmask(); + if (ti->local_flags & _TLF_RESTORE_SIGMASK) { + ti->local_flags &= ~_TLF_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } regs->trap = 0; return 0; /* no signals delivered */ } @@ -148,7 +167,18 @@ static int do_signal(struct pt_regs *regs) regs->trap = 0; if (ret) { - signal_delivered(signr, &info, &ka, regs, + block_sigmask(&ka, signr); + + /* + * A signal was successfully delivered; the saved sigmask is in + * its frame, and we can clear the TLF_RESTORE_SIGMASK flag. + */ + current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK; + + /* + * Let tracing know that we've done the handler setup. + */ + tracehook_signal_handler(signr, &info, &ka, regs, test_thread_flag(TIF_SINGLESTEP)); } @@ -163,6 +193,8 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/powerpc/kernel/signal.h b/trunk/arch/powerpc/kernel/signal.h index e00acb413934..8dde973aaaf5 100644 --- a/trunk/arch/powerpc/kernel/signal.h +++ b/trunk/arch/powerpc/kernel/signal.h @@ -10,10 +10,13 @@ #ifndef _POWERPC_ARCH_SIGNAL_H #define _POWERPC_ARCH_SIGNAL_H +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags); extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, int is_32); +extern void restore_sigmask(sigset_t *set); extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, diff --git a/trunk/arch/powerpc/kernel/signal_32.c b/trunk/arch/powerpc/kernel/signal_32.c index 8b4c049aee20..61f6aff25edc 100644 --- a/trunk/arch/powerpc/kernel/signal_32.c +++ b/trunk/arch/powerpc/kernel/signal_32.c @@ -919,7 +919,7 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp))) return -EFAULT; #endif - set_current_blocked(&set); + restore_sigmask(&set); if (restore_user_regs(regs, mcp, sig)) return -EFAULT; @@ -1273,7 +1273,7 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, set.sig[0] = sigctx.oldmask; set.sig[1] = sigctx._unused[3]; #endif - set_current_blocked(&set); + restore_sigmask(&set); sr = (struct mcontext __user *)from_user_ptr(sigctx.regs); addr = sr; diff --git a/trunk/arch/powerpc/kernel/signal_64.c b/trunk/arch/powerpc/kernel/signal_64.c index d183f8719a50..2692efdb154e 100644 --- a/trunk/arch/powerpc/kernel/signal_64.c +++ b/trunk/arch/powerpc/kernel/signal_64.c @@ -335,7 +335,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx, if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set))) do_exit(SIGSEGV); - set_current_blocked(&set); + restore_sigmask(&set); if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext)) do_exit(SIGSEGV); @@ -364,7 +364,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) goto badframe; - set_current_blocked(&set); + restore_sigmask(&set); if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext)) goto badframe; diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index be171ee73bf8..99a995c2a3f2 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -475,7 +475,6 @@ void timer_interrupt(struct pt_regs * regs) struct pt_regs *old_regs; u64 *next_tb = &__get_cpu_var(decrementers_next_tb); struct clock_event_device *evt = &__get_cpu_var(decrementers); - u64 now; /* Ensure a positive value is written to the decrementer, or else * some CPUs will continue to take decrementer exceptions. @@ -510,16 +509,9 @@ void timer_interrupt(struct pt_regs * regs) irq_work_run(); } - now = get_tb_or_rtc(); - if (now >= *next_tb) { - *next_tb = ~(u64)0; - if (evt->event_handler) - evt->event_handler(evt); - } else { - now = *next_tb - now; - if (now <= DECREMENTER_MAX) - set_dec((int)now); - } + *next_tb = ~(u64)0; + if (evt->event_handler) + evt->event_handler(evt); #ifdef CONFIG_PPC64 /* collect purr register values often, for accurate calculations */ diff --git a/trunk/arch/powerpc/mm/mmu_context_nohash.c b/trunk/arch/powerpc/mm/mmu_context_nohash.c index e779642c25e5..5b63bd3da4a9 100644 --- a/trunk/arch/powerpc/mm/mmu_context_nohash.c +++ b/trunk/arch/powerpc/mm/mmu_context_nohash.c @@ -333,7 +333,9 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)(long)hcpu; - +#ifdef CONFIG_HOTPLUG_CPU + struct task_struct *p; +#endif /* We don't touch CPU 0 map, it's allocated at aboot and kept * around forever */ @@ -356,7 +358,12 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, stale_map[cpu] = NULL; /* We also clear the cpu_vm_mask bits of CPUs going away */ - clear_tasks_mm_cpumask(cpu); + read_lock(&tasklist_lock); + for_each_process(p) { + if (p->mm) + cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); + } + read_unlock(&tasklist_lock); break; #endif /* CONFIG_HOTPLUG_CPU */ } diff --git a/trunk/arch/s390/include/asm/posix_types.h b/trunk/arch/s390/include/asm/posix_types.h index 7be104c0f192..edf8527ff08d 100644 --- a/trunk/arch/s390/include/asm/posix_types.h +++ b/trunk/arch/s390/include/asm/posix_types.h @@ -24,6 +24,7 @@ typedef unsigned short __kernel_old_dev_t; typedef unsigned long __kernel_ino_t; typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; typedef unsigned short __kernel_ipc_pid_t; typedef unsigned short __kernel_uid_t; typedef unsigned short __kernel_gid_t; @@ -34,6 +35,7 @@ typedef int __kernel_ptrdiff_t; typedef unsigned int __kernel_ino_t; typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; typedef int __kernel_ipc_pid_t; typedef unsigned int __kernel_uid_t; typedef unsigned int __kernel_gid_t; @@ -45,6 +47,7 @@ typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ #define __kernel_ino_t __kernel_ino_t #define __kernel_mode_t __kernel_mode_t +#define __kernel_nlink_t __kernel_nlink_t #define __kernel_ipc_pid_t __kernel_ipc_pid_t #define __kernel_uid_t __kernel_uid_t #define __kernel_gid_t __kernel_gid_t diff --git a/trunk/arch/s390/kernel/compat_signal.c b/trunk/arch/s390/kernel/compat_signal.c index 3c0c19830c37..377c096ca4a7 100644 --- a/trunk/arch/s390/kernel/compat_signal.c +++ b/trunk/arch/s390/kernel/compat_signal.c @@ -32,6 +32,8 @@ #include "compat_ptrace.h" #include "entry.h" +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + typedef struct { __u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; @@ -362,6 +364,7 @@ asmlinkage long sys32_sigreturn(void) goto badframe; if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32)) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigregs32(regs, &frame->sregs)) goto badframe; @@ -387,6 +390,7 @@ asmlinkage long sys32_rt_sigreturn(void) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigregs32(regs, &frame->uc.uc_mcontext)) goto badframe; @@ -568,7 +572,7 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, * OK, we're invoking a handler */ -void handle_signal32(unsigned long sig, struct k_sigaction *ka, +int handle_signal32(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { int ret; @@ -579,8 +583,8 @@ void handle_signal32(unsigned long sig, struct k_sigaction *ka, else ret = setup_frame32(sig, ka, oldset, regs); if (ret) - return; - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLE_STEP)); + return ret; + block_sigmask(ka, sig); + return 0; } diff --git a/trunk/arch/s390/kernel/entry.h b/trunk/arch/s390/kernel/entry.h index f66a229ab0b3..6cdddac93a2e 100644 --- a/trunk/arch/s390/kernel/entry.h +++ b/trunk/arch/s390/kernel/entry.h @@ -31,7 +31,7 @@ void do_per_trap(struct pt_regs *regs); void syscall_trace(struct pt_regs *regs, int entryexit); void kernel_stack_overflow(struct pt_regs * regs); void do_signal(struct pt_regs *regs); -void handle_signal32(unsigned long sig, struct k_sigaction *ka, +int handle_signal32(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); void do_notify_resume(struct pt_regs *regs); diff --git a/trunk/arch/s390/kernel/signal.c b/trunk/arch/s390/kernel/signal.c index ac565b44aabb..f626232e216c 100644 --- a/trunk/arch/s390/kernel/signal.c +++ b/trunk/arch/s390/kernel/signal.c @@ -33,6 +33,9 @@ #include #include "entry.h" +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + + typedef struct { __u8 callee_used_stack[__SIGNAL_FRAMESIZE]; @@ -166,6 +169,7 @@ SYSCALL_DEFINE0(sigreturn) goto badframe; if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE)) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigregs(regs, &frame->sregs)) goto badframe; @@ -185,6 +189,7 @@ SYSCALL_DEFINE0(rt_sigreturn) goto badframe; if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigregs(regs, &frame->uc.uc_mcontext)) goto badframe; @@ -362,7 +367,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return -EFAULT; } -static void handle_signal(unsigned long sig, struct k_sigaction *ka, +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { @@ -374,9 +379,9 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, else ret = setup_frame(sig, ka, oldset, regs); if (ret) - return; - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLE_STEP)); + return ret; + block_sigmask(ka, sig); + return 0; } /* @@ -393,7 +398,12 @@ void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; - sigset_t *oldset = sigmask_to_save(); + sigset_t *oldset; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; /* * Get signal to deliver. When running under ptrace, at this point @@ -431,10 +441,24 @@ void do_signal(struct pt_regs *regs) /* No longer in a system call */ clear_thread_flag(TIF_SYSCALL); - if (is_compat_task()) - handle_signal32(signr, &ka, &info, oldset, regs); - else - handle_signal(signr, &ka, &info, oldset, regs); + if ((is_compat_task() ? + handle_signal32(signr, &ka, &info, oldset, regs) : + handle_signal(signr, &ka, &info, oldset, regs)) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + /* + * Let tracing know that we've done the handler setup. + */ + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLE_STEP)); + } return; } @@ -460,11 +484,16 @@ void do_signal(struct pt_regs *regs) /* * If there's no signal to deliver, we just put the saved sigmask back. */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } void do_notify_resume(struct pt_regs *regs) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } diff --git a/trunk/arch/score/kernel/signal.c b/trunk/arch/score/kernel/signal.c index e382c52ca0d9..d4a49011c48a 100644 --- a/trunk/arch/score/kernel/signal.c +++ b/trunk/arch/score/kernel/signal.c @@ -34,6 +34,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + struct rt_sigframe { u32 rs_ass[4]; /* argument save space */ u32 rs_code[2]; /* signal trampoline */ @@ -160,6 +162,7 @@ score_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext); @@ -238,9 +241,11 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, return -EFAULT; } -static void handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka, struct pt_regs *regs) +static int handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { + int ret; + if (regs->is_syscall) { switch (regs->regs[4]) { case ERESTART_RESTARTBLOCK: @@ -264,15 +269,18 @@ static void handle_signal(unsigned long sig, siginfo_t *info, /* * Set up the stack frame */ - if (setup_rt_frame(ka, regs, sig, sigmask_to_save(), info) < 0) - return; + ret = setup_rt_frame(ka, regs, sig, oldset, info); + + if (ret == 0) + block_sigmask(ka, sig); - signal_delivered(sig, info, ka, regs, 0); + return ret; } static void do_signal(struct pt_regs *regs) { struct k_sigaction ka; + sigset_t *oldset; siginfo_t info; int signr; @@ -284,10 +292,25 @@ static void do_signal(struct pt_regs *regs) if (!user_mode(regs)) return; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Actually deliver the signal. */ - handle_signal(signr, &info, &ka, regs); + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + return; } @@ -314,7 +337,10 @@ static void do_signal(struct pt_regs *regs) * If there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* @@ -330,5 +356,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 31d9db7913e4..99bcd0ee838d 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -32,8 +32,6 @@ config SUPERH select GENERIC_SMP_IDLE_THREAD select GENERIC_CLOCKEVENTS select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast diff --git a/trunk/arch/sh/Makefile b/trunk/arch/sh/Makefile index aed701c7b11b..46edf070da1c 100644 --- a/trunk/arch/sh/Makefile +++ b/trunk/arch/sh/Makefile @@ -9,12 +9,6 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -ifneq ($(SUBARCH),$(ARCH)) - ifeq ($(CROSS_COMPILE),) - CROSS_COMPILE := $(call cc-cross-prefix, $(UTS_MACHINE)-linux- $(UTS_MACHINE)-linux-gnu- $(UTS_MACHINE)-unknown-linux-gnu-) - endif -endif - isa-y := any isa-$(CONFIG_SH_DSP) := sh isa-$(CONFIG_CPU_SH2) := sh2 @@ -112,13 +106,19 @@ LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_PAGE_OFFSET) \ KBUILD_DEFCONFIG := cayman_defconfig endif +ifneq ($(SUBARCH),$(ARCH)) + ifeq ($(CROSS_COMPILE),) + CROSS_COMPILE := $(call cc-cross-prefix, $(UTS_MACHINE)-linux- $(UTS_MACHINE)-linux-gnu- $(UTS_MACHINE)-unknown-linux-gnu-) + endif +endif + ifdef CONFIG_CPU_LITTLE_ENDIAN ld-bfd := elf32-$(UTS_MACHINE)-linux -LDFLAGS_vmlinux += --defsym jiffies=jiffies_64 --oformat $(ld-bfd) +LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' --oformat $(ld-bfd) LDFLAGS += -EL else ld-bfd := elf32-$(UTS_MACHINE)big-linux -LDFLAGS_vmlinux += --defsym jiffies=jiffies_64+4 --oformat $(ld-bfd) +LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' --oformat $(ld-bfd) LDFLAGS += -EB endif diff --git a/trunk/arch/sh/boards/mach-migor/setup.c b/trunk/arch/sh/boards/mach-migor/setup.c index a8a1ca741c85..34cd0c5ff2e1 100644 --- a/trunk/arch/sh/boards/mach-migor/setup.c +++ b/trunk/arch/sh/boards/mach-migor/setup.c @@ -188,6 +188,7 @@ static struct platform_nand_data migor_nand_flash_data = { .partitions = migor_nand_flash_partitions, .nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions), .chip_delay = 20, + .part_probe_types = (const char *[]) { "cmdlinepart", NULL }, }, .ctrl = { .dev_ready = migor_nand_flash_ready, diff --git a/trunk/arch/sh/include/asm/Kbuild b/trunk/arch/sh/include/asm/Kbuild index 7b673ddcd555..7beb42322f60 100644 --- a/trunk/arch/sh/include/asm/Kbuild +++ b/trunk/arch/sh/include/asm/Kbuild @@ -1,39 +1,5 @@ include include/asm-generic/Kbuild.asm -generic-y += bitsperlong.h -generic-y += cputime.h -generic-y += current.h -generic-y += delay.h -generic-y += div64.h -generic-y += emergency-restart.h -generic-y += errno.h -generic-y += fcntl.h -generic-y += ioctl.h -generic-y += ipcbuf.h -generic-y += irq_regs.h -generic-y += kvm_para.h -generic-y += local.h -generic-y += local64.h -generic-y += param.h -generic-y += parport.h -generic-y += percpu.h -generic-y += poll.h -generic-y += mman.h -generic-y += msgbuf.h -generic-y += resource.h -generic-y += scatterlist.h -generic-y += sembuf.h -generic-y += serial.h -generic-y += shmbuf.h -generic-y += siginfo.h -generic-y += sizes.h -generic-y += socket.h -generic-y += statfs.h -generic-y += termbits.h -generic-y += termios.h -generic-y += ucontext.h -generic-y += xor.h - header-y += cachectl.h header-y += cpu-features.h header-y += hw_breakpoint.h diff --git a/trunk/arch/sh/include/asm/bitsperlong.h b/trunk/arch/sh/include/asm/bitsperlong.h new file mode 100644 index 000000000000..6dc0bb0c13b2 --- /dev/null +++ b/trunk/arch/sh/include/asm/bitsperlong.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/cputime.h b/trunk/arch/sh/include/asm/cputime.h new file mode 100644 index 000000000000..6ca395d1393e --- /dev/null +++ b/trunk/arch/sh/include/asm/cputime.h @@ -0,0 +1,6 @@ +#ifndef __SH_CPUTIME_H +#define __SH_CPUTIME_H + +#include + +#endif /* __SH_CPUTIME_H */ diff --git a/trunk/arch/sh/include/asm/current.h b/trunk/arch/sh/include/asm/current.h new file mode 100644 index 000000000000..4c51401b5537 --- /dev/null +++ b/trunk/arch/sh/include/asm/current.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/delay.h b/trunk/arch/sh/include/asm/delay.h new file mode 100644 index 000000000000..9670e127b7b2 --- /dev/null +++ b/trunk/arch/sh/include/asm/delay.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/div64.h b/trunk/arch/sh/include/asm/div64.h new file mode 100644 index 000000000000..6cd978cefb28 --- /dev/null +++ b/trunk/arch/sh/include/asm/div64.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/emergency-restart.h b/trunk/arch/sh/include/asm/emergency-restart.h new file mode 100644 index 000000000000..108d8c48e42e --- /dev/null +++ b/trunk/arch/sh/include/asm/emergency-restart.h @@ -0,0 +1,6 @@ +#ifndef _ASM_EMERGENCY_RESTART_H +#define _ASM_EMERGENCY_RESTART_H + +#include + +#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/trunk/arch/sh/include/asm/errno.h b/trunk/arch/sh/include/asm/errno.h new file mode 100644 index 000000000000..51cf6f9cebb8 --- /dev/null +++ b/trunk/arch/sh/include/asm/errno.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_ERRNO_H +#define __ASM_SH_ERRNO_H + +#include + +#endif /* __ASM_SH_ERRNO_H */ diff --git a/trunk/arch/sh/include/asm/fcntl.h b/trunk/arch/sh/include/asm/fcntl.h new file mode 100644 index 000000000000..46ab12db5739 --- /dev/null +++ b/trunk/arch/sh/include/asm/fcntl.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/ioctl.h b/trunk/arch/sh/include/asm/ioctl.h new file mode 100644 index 000000000000..b279fe06dfe5 --- /dev/null +++ b/trunk/arch/sh/include/asm/ioctl.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/ipcbuf.h b/trunk/arch/sh/include/asm/ipcbuf.h new file mode 100644 index 000000000000..84c7e51cb6d0 --- /dev/null +++ b/trunk/arch/sh/include/asm/ipcbuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/irq_regs.h b/trunk/arch/sh/include/asm/irq_regs.h new file mode 100644 index 000000000000..3dd9c0b70270 --- /dev/null +++ b/trunk/arch/sh/include/asm/irq_regs.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/kvm_para.h b/trunk/arch/sh/include/asm/kvm_para.h new file mode 100644 index 000000000000..14fab8f0b957 --- /dev/null +++ b/trunk/arch/sh/include/asm/kvm_para.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/local.h b/trunk/arch/sh/include/asm/local.h new file mode 100644 index 000000000000..9ed9b9cb459a --- /dev/null +++ b/trunk/arch/sh/include/asm/local.h @@ -0,0 +1,7 @@ +#ifndef __ASM_SH_LOCAL_H +#define __ASM_SH_LOCAL_H + +#include + +#endif /* __ASM_SH_LOCAL_H */ + diff --git a/trunk/arch/sh/include/asm/local64.h b/trunk/arch/sh/include/asm/local64.h new file mode 100644 index 000000000000..36c93b5cc239 --- /dev/null +++ b/trunk/arch/sh/include/asm/local64.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/mman.h b/trunk/arch/sh/include/asm/mman.h new file mode 100644 index 000000000000..8eebf89f5ab1 --- /dev/null +++ b/trunk/arch/sh/include/asm/mman.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/msgbuf.h b/trunk/arch/sh/include/asm/msgbuf.h new file mode 100644 index 000000000000..809134c644a6 --- /dev/null +++ b/trunk/arch/sh/include/asm/msgbuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/param.h b/trunk/arch/sh/include/asm/param.h new file mode 100644 index 000000000000..965d45427975 --- /dev/null +++ b/trunk/arch/sh/include/asm/param.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/parport.h b/trunk/arch/sh/include/asm/parport.h new file mode 100644 index 000000000000..cf252af64590 --- /dev/null +++ b/trunk/arch/sh/include/asm/parport.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/percpu.h b/trunk/arch/sh/include/asm/percpu.h new file mode 100644 index 000000000000..4db4b39a4399 --- /dev/null +++ b/trunk/arch/sh/include/asm/percpu.h @@ -0,0 +1,6 @@ +#ifndef __ARCH_SH_PERCPU +#define __ARCH_SH_PERCPU + +#include + +#endif /* __ARCH_SH_PERCPU */ diff --git a/trunk/arch/sh/include/asm/poll.h b/trunk/arch/sh/include/asm/poll.h new file mode 100644 index 000000000000..c98509d3149e --- /dev/null +++ b/trunk/arch/sh/include/asm/poll.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/posix_types_32.h b/trunk/arch/sh/include/asm/posix_types_32.h index ba0bdc423b07..abda58467ece 100644 --- a/trunk/arch/sh/include/asm/posix_types_32.h +++ b/trunk/arch/sh/include/asm/posix_types_32.h @@ -3,6 +3,8 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t typedef unsigned short __kernel_uid_t; diff --git a/trunk/arch/sh/include/asm/posix_types_64.h b/trunk/arch/sh/include/asm/posix_types_64.h index 244f7e950e17..fcda07b4a616 100644 --- a/trunk/arch/sh/include/asm/posix_types_64.h +++ b/trunk/arch/sh/include/asm/posix_types_64.h @@ -3,6 +3,8 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t typedef unsigned short __kernel_uid_t; diff --git a/trunk/arch/sh/include/asm/resource.h b/trunk/arch/sh/include/asm/resource.h new file mode 100644 index 000000000000..9c2499a86ec0 --- /dev/null +++ b/trunk/arch/sh/include/asm/resource.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_RESOURCE_H +#define __ASM_SH_RESOURCE_H + +#include + +#endif /* __ASM_SH_RESOURCE_H */ diff --git a/trunk/arch/sh/include/asm/scatterlist.h b/trunk/arch/sh/include/asm/scatterlist.h new file mode 100644 index 000000000000..98dfc3510f10 --- /dev/null +++ b/trunk/arch/sh/include/asm/scatterlist.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_SCATTERLIST_H +#define __ASM_SH_SCATTERLIST_H + +#include + +#endif /* __ASM_SH_SCATTERLIST_H */ diff --git a/trunk/arch/sh/include/asm/sembuf.h b/trunk/arch/sh/include/asm/sembuf.h new file mode 100644 index 000000000000..7673b83cfef7 --- /dev/null +++ b/trunk/arch/sh/include/asm/sembuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/serial.h b/trunk/arch/sh/include/asm/serial.h new file mode 100644 index 000000000000..a0cb0caff152 --- /dev/null +++ b/trunk/arch/sh/include/asm/serial.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/shmbuf.h b/trunk/arch/sh/include/asm/shmbuf.h new file mode 100644 index 000000000000..83c05fc2de38 --- /dev/null +++ b/trunk/arch/sh/include/asm/shmbuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/siginfo.h b/trunk/arch/sh/include/asm/siginfo.h new file mode 100644 index 000000000000..813040ed68a9 --- /dev/null +++ b/trunk/arch/sh/include/asm/siginfo.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_SIGINFO_H +#define __ASM_SH_SIGINFO_H + +#include + +#endif /* __ASM_SH_SIGINFO_H */ diff --git a/trunk/arch/sh/include/asm/sizes.h b/trunk/arch/sh/include/asm/sizes.h new file mode 100644 index 000000000000..dd248c2e1085 --- /dev/null +++ b/trunk/arch/sh/include/asm/sizes.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/socket.h b/trunk/arch/sh/include/asm/socket.h new file mode 100644 index 000000000000..6b71384b9d8b --- /dev/null +++ b/trunk/arch/sh/include/asm/socket.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/statfs.h b/trunk/arch/sh/include/asm/statfs.h new file mode 100644 index 000000000000..9202a023328f --- /dev/null +++ b/trunk/arch/sh/include/asm/statfs.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_STATFS_H +#define __ASM_SH_STATFS_H + +#include + +#endif /* __ASM_SH_STATFS_H */ diff --git a/trunk/arch/sh/include/asm/termbits.h b/trunk/arch/sh/include/asm/termbits.h new file mode 100644 index 000000000000..3935b106de79 --- /dev/null +++ b/trunk/arch/sh/include/asm/termbits.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/termios.h b/trunk/arch/sh/include/asm/termios.h new file mode 100644 index 000000000000..280d78a9d966 --- /dev/null +++ b/trunk/arch/sh/include/asm/termios.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/thread_info.h b/trunk/arch/sh/include/asm/thread_info.h index bc13b57cdc83..0c04ffc4f12c 100644 --- a/trunk/arch/sh/include/asm/thread_info.h +++ b/trunk/arch/sh/include/asm/thread_info.h @@ -169,7 +169,7 @@ static inline void set_restore_sigmask(void) { struct thread_info *ti = current_thread_info(); ti->status |= TS_RESTORE_SIGMASK; - WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags)); + set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); } #define TI_FLAG_FAULT_CODE_SHIFT 24 @@ -189,23 +189,6 @@ static inline unsigned int get_thread_fault_code(void) struct thread_info *ti = current_thread_info(); return ti->flags >> TI_FLAG_FAULT_CODE_SHIFT; } - -static inline void clear_restore_sigmask(void) -{ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -} -static inline bool test_restore_sigmask(void) -{ - return current_thread_info()->status & TS_RESTORE_SIGMASK; -} -static inline bool test_and_clear_restore_sigmask(void) -{ - struct thread_info *ti = current_thread_info(); - if (!(ti->status & TS_RESTORE_SIGMASK)) - return false; - ti->status &= ~TS_RESTORE_SIGMASK; - return true; -} #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/trunk/arch/sh/include/asm/uaccess.h b/trunk/arch/sh/include/asm/uaccess.h index 8698a80ed00c..050f221fa898 100644 --- a/trunk/arch/sh/include/asm/uaccess.h +++ b/trunk/arch/sh/include/asm/uaccess.h @@ -25,8 +25,6 @@ (__chk_user_ptr(addr), \ __access_ok((unsigned long __force)(addr), (size))) -#define user_addr_max() (current_thread_info()->addr_limit.seg) - /* * Uh, these should become the main single-value transfer routines ... * They automatically use the right size if we just have the right @@ -102,11 +100,6 @@ struct __large_struct { unsigned long buf[100]; }; # include "uaccess_64.h" #endif -extern long strncpy_from_user(char *dest, const char __user *src, long count); - -extern __must_check long strlen_user(const char __user *str); -extern __must_check long strnlen_user(const char __user *str, long n); - /* Generic arbitrary sized copy. */ /* Return the number of bytes NOT copied */ __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); @@ -144,6 +137,37 @@ __kernel_size_t __clear_user(void *addr, __kernel_size_t size); __cl_size; \ }) +/** + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +#define strncpy_from_user(dest,src,count) \ +({ \ + unsigned long __sfu_src = (unsigned long)(src); \ + int __sfu_count = (int)(count); \ + long __sfu_res = -EFAULT; \ + \ + if (__access_ok(__sfu_src, __sfu_count)) \ + __sfu_res = __strncpy_from_user((unsigned long)(dest), \ + __sfu_src, __sfu_count); \ + \ + __sfu_res; \ +}) + static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { @@ -168,6 +192,43 @@ copy_to_user(void __user *to, const void *from, unsigned long n) return __copy_size; } +/** + * strnlen_user: - Get the size of a string in user space. + * @s: The string to measure. + * @n: The maximum valid length + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * If the string is too long, returns a value greater than @n. + */ +static inline long strnlen_user(const char __user *s, long n) +{ + if (!__addr_ok(s)) + return 0; + else + return __strnlen_user(s, n); +} + +/** + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * + * If there is a limit on the length of a valid string, you may wish to + * consider using strnlen_user() instead. + */ +#define strlen_user(str) strnlen_user(str, ~0UL >> 1) + /* * The exception table consists of pairs of addresses: the first is the * address of an instruction that is allowed to fault, and the second is diff --git a/trunk/arch/sh/include/asm/uaccess_32.h b/trunk/arch/sh/include/asm/uaccess_32.h index c0de7ee35ab7..ae0d24f6653f 100644 --- a/trunk/arch/sh/include/asm/uaccess_32.h +++ b/trunk/arch/sh/include/asm/uaccess_32.h @@ -170,4 +170,79 @@ __asm__ __volatile__( \ extern void __put_user_unknown(void); +static inline int +__strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count) +{ + __kernel_size_t res; + unsigned long __dummy, _d, _s, _c; + + __asm__ __volatile__( + "9:\n" + "mov.b @%2+, %1\n\t" + "cmp/eq #0, %1\n\t" + "bt/s 2f\n" + "1:\n" + "mov.b %1, @%3\n\t" + "dt %4\n\t" + "bf/s 9b\n\t" + " add #1, %3\n\t" + "2:\n\t" + "sub %4, %0\n" + "3:\n" + ".section .fixup,\"ax\"\n" + "4:\n\t" + "mov.l 5f, %1\n\t" + "jmp @%1\n\t" + " mov %9, %0\n\t" + ".balign 4\n" + "5: .long 3b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .balign 4\n" + " .long 9b,4b\n" + ".previous" + : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c) + : "0" (__count), "2" (__src), "3" (__dest), "4" (__count), + "i" (-EFAULT) + : "memory", "t"); + + return res; +} + +/* + * Return the size of a string (including the ending 0 even when we have + * exceeded the maximum string length). + */ +static inline long __strnlen_user(const char __user *__s, long __n) +{ + unsigned long res; + unsigned long __dummy; + + __asm__ __volatile__( + "1:\t" + "mov.b @(%0,%3), %1\n\t" + "cmp/eq %4, %0\n\t" + "bt/s 2f\n\t" + " add #1, %0\n\t" + "tst %1, %1\n\t" + "bf 1b\n\t" + "2:\n" + ".section .fixup,\"ax\"\n" + "3:\n\t" + "mov.l 4f, %1\n\t" + "jmp @%1\n\t" + " mov #0, %0\n" + ".balign 4\n" + "4: .long 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .balign 4\n" + " .long 1b,3b\n" + ".previous" + : "=z" (res), "=&r" (__dummy) + : "0" (0), "r" (__s), "r" (__n) + : "t"); + return res; +} + #endif /* __ASM_SH_UACCESS_32_H */ diff --git a/trunk/arch/sh/include/asm/uaccess_64.h b/trunk/arch/sh/include/asm/uaccess_64.h index 2e07e0f40c6a..56fd20b8cdcc 100644 --- a/trunk/arch/sh/include/asm/uaccess_64.h +++ b/trunk/arch/sh/include/asm/uaccess_64.h @@ -84,4 +84,8 @@ extern long __put_user_asm_l(void *, long); extern long __put_user_asm_q(void *, long); extern void __put_user_unknown(void); +extern long __strnlen_user(const char *__s, long __n); +extern int __strncpy_from_user(unsigned long __dest, + unsigned long __user __src, int __count); + #endif /* __ASM_SH_UACCESS_64_H */ diff --git a/trunk/arch/sh/include/asm/ucontext.h b/trunk/arch/sh/include/asm/ucontext.h new file mode 100644 index 000000000000..9bc07b9f30fb --- /dev/null +++ b/trunk/arch/sh/include/asm/ucontext.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/word-at-a-time.h b/trunk/arch/sh/include/asm/word-at-a-time.h deleted file mode 100644 index 6e38953ff7fd..000000000000 --- a/trunk/arch/sh/include/asm/word-at-a-time.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __ASM_SH_WORD_AT_A_TIME_H -#define __ASM_SH_WORD_AT_A_TIME_H - -#ifdef CONFIG_CPU_BIG_ENDIAN -# include -#else -/* - * Little-endian version cribbed from x86. - */ -struct word_at_a_time { - const unsigned long one_bits, high_bits; -}; - -#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } - -/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ -static inline long count_masked_bytes(long mask) -{ - /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ - long a = (0x0ff0001+mask) >> 23; - /* Fix the 1 for 00 case */ - return a & mask; -} - -/* Return nonzero if it has a zero */ -static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) -{ - unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; - *bits = mask; - return mask; -} - -static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) -{ - return bits; -} - -static inline unsigned long create_zero_mask(unsigned long bits) -{ - bits = (bits - 1) & ~bits; - return bits >> 7; -} - -/* The mask we created is directly usable as a bytemask */ -#define zero_bytemask(mask) (mask) - -static inline unsigned long find_zero(unsigned long mask) -{ - return count_masked_bytes(mask); -} -#endif - -#endif diff --git a/trunk/arch/sh/include/asm/xor.h b/trunk/arch/sh/include/asm/xor.h new file mode 100644 index 000000000000..c82eb12a5b18 --- /dev/null +++ b/trunk/arch/sh/include/asm/xor.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/cpu-sh2a/cpu/ubc.h b/trunk/arch/sh/include/cpu-sh2a/cpu/ubc.h new file mode 100644 index 000000000000..1192e1c761a7 --- /dev/null +++ b/trunk/arch/sh/include/cpu-sh2a/cpu/ubc.h @@ -0,0 +1,28 @@ +/* + * SH-2A UBC definitions + * + * Copyright (C) 2008 Kieran Bingham + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#ifndef __ASM_CPU_SH2A_UBC_H +#define __ASM_CPU_SH2A_UBC_H + +#define UBC_BARA 0xfffc0400 +#define UBC_BAMRA 0xfffc0404 +#define UBC_BBRA 0xfffc04a0 /* 16 bit access */ +#define UBC_BDRA 0xfffc0408 +#define UBC_BDMRA 0xfffc040c + +#define UBC_BARB 0xfffc0410 +#define UBC_BAMRB 0xfffc0414 +#define UBC_BBRB 0xfffc04b0 /* 16 bit access */ +#define UBC_BDRB 0xfffc0418 +#define UBC_BDMRB 0xfffc041c + +#define UBC_BRCR 0xfffc04c0 + +#endif /* __ASM_CPU_SH2A_UBC_H */ diff --git a/trunk/arch/sh/kernel/cpu/sh5/entry.S b/trunk/arch/sh/kernel/cpu/sh5/entry.S index b7cf6a547f11..ff1f0e6e9bec 100644 --- a/trunk/arch/sh/kernel/cpu/sh5/entry.S +++ b/trunk/arch/sh/kernel/cpu/sh5/entry.S @@ -1568,6 +1568,86 @@ ___clear_user_exit: #endif /* CONFIG_MMU */ +/* + * int __strncpy_from_user(unsigned long __dest, unsigned long __src, + * int __count) + * + * Inputs: + * (r2) target address + * (r3) source address + * (r4) maximum size in bytes + * + * Ouputs: + * (*r2) copied data + * (r2) -EFAULT (in case of faulting) + * copied data (otherwise) + */ + .global __strncpy_from_user +__strncpy_from_user: + pta ___strncpy_from_user1, tr0 + pta ___strncpy_from_user_done, tr1 + or r4, ZERO, r5 /* r5 = original count */ + beq/u r4, r63, tr1 /* early exit if r4==0 */ + movi -(EFAULT), r6 /* r6 = reply, no real fixup */ + or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ + +___strncpy_from_user1: + ld.b r3, 0, r7 /* Fault address: only in reading */ + st.b r2, 0, r7 + addi r2, 1, r2 + addi r3, 1, r3 + beq/u ZERO, r7, tr1 + addi r4, -1, r4 /* return real number of copied bytes */ + bne/l ZERO, r4, tr0 + +___strncpy_from_user_done: + sub r5, r4, r6 /* If done, return copied */ + +___strncpy_from_user_exit: + or r6, ZERO, r2 + ptabs LINK, tr0 + blink tr0, ZERO + +/* + * extern long __strnlen_user(const char *__s, long __n) + * + * Inputs: + * (r2) source address + * (r3) source size in bytes + * + * Ouputs: + * (r2) -EFAULT (in case of faulting) + * string length (otherwise) + */ + .global __strnlen_user +__strnlen_user: + pta ___strnlen_user_set_reply, tr0 + pta ___strnlen_user1, tr1 + or ZERO, ZERO, r5 /* r5 = counter */ + movi -(EFAULT), r6 /* r6 = reply, no real fixup */ + or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ + beq r3, ZERO, tr0 + +___strnlen_user1: + ldx.b r2, r5, r7 /* Fault address: only in reading */ + addi r3, -1, r3 /* No real fixup */ + addi r5, 1, r5 + beq r3, ZERO, tr0 + bne r7, ZERO, tr1 +! The line below used to be active. This meant led to a junk byte lying between each pair +! of entries in the argv & envp structures in memory. Whilst the program saw the right data +! via the argv and envp arguments to main, it meant the 'flat' representation visible through +! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example. +! addi r5, 1, r5 /* Include '\0' */ + +___strnlen_user_set_reply: + or r5, ZERO, r6 /* If done, return counter */ + +___strnlen_user_exit: + or r6, ZERO, r2 + ptabs LINK, tr0 + blink tr0, ZERO + /* * extern long __get_user_asm_?(void *val, long addr) * @@ -1902,6 +1982,8 @@ asm_uaccess_start: .long ___copy_user2, ___copy_user_exit .long ___clear_user1, ___clear_user_exit #endif + .long ___strncpy_from_user1, ___strncpy_from_user_exit + .long ___strnlen_user1, ___strnlen_user_exit .long ___get_user_asm_b1, ___get_user_asm_b_exit .long ___get_user_asm_w1, ___get_user_asm_w_exit .long ___get_user_asm_l1, ___get_user_asm_l_exit diff --git a/trunk/arch/sh/kernel/process.c b/trunk/arch/sh/kernel/process.c index 055d91b70305..9b7a459a4613 100644 --- a/trunk/arch/sh/kernel/process.c +++ b/trunk/arch/sh/kernel/process.c @@ -4,7 +4,6 @@ #include #include #include -#include struct kmem_cache *task_xstate_cachep = NULL; unsigned int xstate_size; diff --git a/trunk/arch/sh/kernel/process_64.c b/trunk/arch/sh/kernel/process_64.c index 602545b12a86..4264583eabac 100644 --- a/trunk/arch/sh/kernel/process_64.c +++ b/trunk/arch/sh/kernel/process_64.c @@ -33,7 +33,6 @@ #include struct task_struct *last_task_used_math = NULL; -struct pt_regs fake_swapper_regs = { 0, }; void show_regs(struct pt_regs *regs) { diff --git a/trunk/arch/sh/kernel/sh_ksyms_64.c b/trunk/arch/sh/kernel/sh_ksyms_64.c index 26a0774f5272..45afa5c51f67 100644 --- a/trunk/arch/sh/kernel/sh_ksyms_64.c +++ b/trunk/arch/sh/kernel/sh_ksyms_64.c @@ -32,6 +32,8 @@ EXPORT_SYMBOL(__get_user_asm_b); EXPORT_SYMBOL(__get_user_asm_w); EXPORT_SYMBOL(__get_user_asm_l); EXPORT_SYMBOL(__get_user_asm_q); +EXPORT_SYMBOL(__strnlen_user); +EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__copy_user); diff --git a/trunk/arch/sh/kernel/signal_32.c b/trunk/arch/sh/kernel/signal_32.c index d6b7b6154f87..cb4172c8af7d 100644 --- a/trunk/arch/sh/kernel/signal_32.c +++ b/trunk/arch/sh/kernel/signal_32.c @@ -32,6 +32,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + struct fdpic_func_descriptor { unsigned long text; unsigned long GOT; @@ -224,6 +226,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, sizeof(frame->extramask)))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc, &r0)) @@ -253,6 +256,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) @@ -518,11 +522,10 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs, /* * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, - struct pt_regs *regs, unsigned int save_r0) + sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0) { - sigset_t *oldset = sigmask_to_save(); int ret; /* Set up the stack frame */ @@ -531,10 +534,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, else ret = setup_frame(sig, ka, oldset, regs); - if (ret) - return; - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLESTEP)); + if (ret == 0) + block_sigmask(ka, sig); + + return ret; } /* @@ -551,6 +554,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -561,12 +565,30 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) if (!user_mode(regs)) return; + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { handle_syscall_restart(save_r0, regs, &ka.sa); /* Whee! Actually deliver the signal. */ - handle_signal(signr, &ka, &info, regs, save_r0); + if (handle_signal(signr, &ka, &info, oldset, + regs, save_r0) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + } + return; } @@ -588,7 +610,10 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) * If there's no signal to deliver, we just put the saved sigmask * back. */ - restore_saved_sigmask(); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, @@ -601,5 +626,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/sh/kernel/signal_64.c b/trunk/arch/sh/kernel/signal_64.c index 6b5b3dfe886b..b589a354c069 100644 --- a/trunk/arch/sh/kernel/signal_64.c +++ b/trunk/arch/sh/kernel/signal_64.c @@ -41,9 +41,11 @@ #define DEBUG_SIG 0 -static void +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs * regs); + sigset_t *oldset, struct pt_regs * regs); static inline void handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) @@ -86,6 +88,7 @@ static void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -96,13 +99,28 @@ static void do_signal(struct pt_regs *regs) if (!user_mode(regs)) return; + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, 0); if (signr > 0) { handle_syscall_restart(regs, &ka.sa); /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, regs); - return; + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* + * If a signal was successfully delivered, the + * saved sigmask is in its frame, and we can + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + return; + } } /* Did we come from a system call? */ @@ -125,7 +143,12 @@ static void do_signal(struct pt_regs *regs) } /* No signal to deliver -- put the saved sigmask back */ - restore_saved_sigmask(); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + + return; } /* @@ -328,6 +351,7 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3, sizeof(frame->extramask)))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc, &ret)) @@ -360,6 +384,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret)) @@ -634,11 +659,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* * OK, we're invoking a handler */ -static void +static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - struct pt_regs * regs) + sigset_t *oldset, struct pt_regs * regs) { - sigset_t *oldset = sigmask_to_save(); int ret; /* Set up the stack frame */ @@ -647,11 +671,10 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, else ret = setup_frame(sig, ka, oldset, regs); - if (ret) - return; + if (ret == 0) + block_sigmask(ka, sig); - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLESTEP)); + return ret; } asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) @@ -662,5 +685,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/sh/kernel/smp.c b/trunk/arch/sh/kernel/smp.c index 2062aa88af41..b86e9ca79455 100644 --- a/trunk/arch/sh/kernel/smp.c +++ b/trunk/arch/sh/kernel/smp.c @@ -123,6 +123,7 @@ void native_play_dead(void) int __cpu_disable(void) { unsigned int cpu = smp_processor_id(); + struct task_struct *p; int ret; ret = mp_ops->cpu_disable(cpu); @@ -152,7 +153,11 @@ int __cpu_disable(void) flush_cache_all(); local_flush_tlb_all(); - clear_tasks_mm_cpumask(cpu); + read_lock(&tasklist_lock); + for_each_process(p) + if (p->mm) + cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); + read_unlock(&tasklist_lock); return 0; } diff --git a/trunk/arch/sparc/include/asm/cmt.h b/trunk/arch/sparc/include/asm/cmt.h new file mode 100644 index 000000000000..870db5928577 --- /dev/null +++ b/trunk/arch/sparc/include/asm/cmt.h @@ -0,0 +1,59 @@ +#ifndef _SPARC64_CMT_H +#define _SPARC64_CMT_H + +/* cmt.h: Chip Multi-Threading register definitions + * + * Copyright (C) 2004 David S. Miller (davem@redhat.com) + */ + +/* ASI_CORE_ID - private */ +#define LP_ID 0x0000000000000010UL +#define LP_ID_MAX 0x00000000003f0000UL +#define LP_ID_ID 0x000000000000003fUL + +/* ASI_INTR_ID - private */ +#define LP_INTR_ID 0x0000000000000000UL +#define LP_INTR_ID_ID 0x00000000000003ffUL + +/* ASI_CESR_ID - private */ +#define CESR_ID 0x0000000000000040UL +#define CESR_ID_ID 0x00000000000000ffUL + +/* ASI_CORE_AVAILABLE - shared */ +#define LP_AVAIL 0x0000000000000000UL +#define LP_AVAIL_1 0x0000000000000002UL +#define LP_AVAIL_0 0x0000000000000001UL + +/* ASI_CORE_ENABLE_STATUS - shared */ +#define LP_ENAB_STAT 0x0000000000000010UL +#define LP_ENAB_STAT_1 0x0000000000000002UL +#define LP_ENAB_STAT_0 0x0000000000000001UL + +/* ASI_CORE_ENABLE - shared */ +#define LP_ENAB 0x0000000000000020UL +#define LP_ENAB_1 0x0000000000000002UL +#define LP_ENAB_0 0x0000000000000001UL + +/* ASI_CORE_RUNNING - shared */ +#define LP_RUNNING_RW 0x0000000000000050UL +#define LP_RUNNING_W1S 0x0000000000000060UL +#define LP_RUNNING_W1C 0x0000000000000068UL +#define LP_RUNNING_1 0x0000000000000002UL +#define LP_RUNNING_0 0x0000000000000001UL + +/* ASI_CORE_RUNNING_STAT - shared */ +#define LP_RUN_STAT 0x0000000000000058UL +#define LP_RUN_STAT_1 0x0000000000000002UL +#define LP_RUN_STAT_0 0x0000000000000001UL + +/* ASI_XIR_STEERING - shared */ +#define LP_XIR_STEER 0x0000000000000030UL +#define LP_XIR_STEER_1 0x0000000000000002UL +#define LP_XIR_STEER_0 0x0000000000000001UL + +/* ASI_CMT_ERROR_STEERING - shared */ +#define CMT_ER_STEER 0x0000000000000040UL +#define CMT_ER_STEER_1 0x0000000000000002UL +#define CMT_ER_STEER_0 0x0000000000000001UL + +#endif /* _SPARC64_CMT_H */ diff --git a/trunk/arch/sparc/include/asm/mpmbox.h b/trunk/arch/sparc/include/asm/mpmbox.h new file mode 100644 index 000000000000..f8423039b242 --- /dev/null +++ b/trunk/arch/sparc/include/asm/mpmbox.h @@ -0,0 +1,67 @@ +/* + * mpmbox.h: Interface and defines for the OpenProm mailbox + * facilities for MP machines under Linux. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_MPMBOX_H +#define _SPARC_MPMBOX_H + +/* The prom allocates, for each CPU on the machine an unsigned + * byte in physical ram. You probe the device tree prom nodes + * for these values. The purpose of this byte is to be able to + * pass messages from one cpu to another. + */ + +/* These are the main message types we have to look for in our + * Cpu mailboxes, based upon these values we decide what course + * of action to take. + */ + +/* The CPU is executing code in the kernel. */ +#define MAILBOX_ISRUNNING 0xf0 + +/* Another CPU called romvec->pv_exit(), you should call + * prom_stopcpu() when you see this in your mailbox. + */ +#define MAILBOX_EXIT 0xfb + +/* Another CPU called romvec->pv_enter(), you should call + * prom_cpuidle() when this is seen. + */ +#define MAILBOX_GOSPIN 0xfc + +/* Another CPU has hit a breakpoint either into kadb or the prom + * itself. Just like MAILBOX_GOSPIN, you should call prom_cpuidle() + * at this point. + */ +#define MAILBOX_BPT_SPIN 0xfd + +/* Oh geese, some other nitwit got a damn watchdog reset. The party's + * over so go call prom_stopcpu(). + */ +#define MAILBOX_WDOG_STOP 0xfe + +#ifndef __ASSEMBLY__ + +/* Handy macro's to determine a cpu's state. */ + +/* Is the cpu still in Power On Self Test? */ +#define MBOX_POST_P(letter) ((letter) >= 0x00 && (letter) <= 0x7f) + +/* Is the cpu at the 'ok' prompt of the PROM? */ +#define MBOX_PROMPROMPT_P(letter) ((letter) >= 0x80 && (letter) <= 0x8f) + +/* Is the cpu spinning in the PROM? */ +#define MBOX_PROMSPIN_P(letter) ((letter) >= 0x90 && (letter) <= 0xef) + +/* Sanity check... This is junk mail, throw it out. */ +#define MBOX_BOGON_P(letter) ((letter) >= 0xf1 && (letter) <= 0xfa) + +/* Is the cpu actively running an application/kernel-code? */ +#define MBOX_RUNNING_P(letter) ((letter) == MAILBOX_ISRUNNING) + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(_SPARC_MPMBOX_H) */ diff --git a/trunk/arch/sparc/include/asm/posix_types.h b/trunk/arch/sparc/include/asm/posix_types.h index 156220ed99eb..3070f25ae90a 100644 --- a/trunk/arch/sparc/include/asm/posix_types.h +++ b/trunk/arch/sparc/include/asm/posix_types.h @@ -9,6 +9,8 @@ #if defined(__sparc__) && defined(__arch64__) /* sparc 64 bit */ +typedef unsigned int __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t typedef unsigned short __kernel_old_uid_t; typedef unsigned short __kernel_old_gid_t; @@ -36,6 +38,9 @@ typedef unsigned short __kernel_gid_t; typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef long __kernel_daddr_t; #define __kernel_daddr_t __kernel_daddr_t diff --git a/trunk/arch/sparc/include/asm/thread_info_32.h b/trunk/arch/sparc/include/asm/thread_info_32.h index e6cd224506a9..5af664932452 100644 --- a/trunk/arch/sparc/include/asm/thread_info_32.h +++ b/trunk/arch/sparc/include/asm/thread_info_32.h @@ -131,7 +131,8 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define _TIF_POLLING_NRFLAG (1<status |= TS_RESTORE_SIGMASK; - WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags)); -} -static inline void clear_restore_sigmask(void) -{ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -} -static inline bool test_restore_sigmask(void) -{ - return current_thread_info()->status & TS_RESTORE_SIGMASK; -} -static inline bool test_and_clear_restore_sigmask(void) -{ - struct thread_info *ti = current_thread_info(); - if (!(ti->status & TS_RESTORE_SIGMASK)) - return false; - ti->status &= ~TS_RESTORE_SIGMASK; - return true; + set_bit(TIF_SIGPENDING, &ti->flags); } #endif /* !__ASSEMBLY__ */ diff --git a/trunk/arch/sparc/kernel/signal32.c b/trunk/arch/sparc/kernel/signal32.c index a53e0a5fd3a3..bb1513e45f1a 100644 --- a/trunk/arch/sparc/kernel/signal32.c +++ b/trunk/arch/sparc/kernel/signal32.c @@ -32,6 +32,8 @@ #include "sigutil.h" +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* This magic should be in g_upper[0] for all upper parts * to be valid. */ @@ -272,6 +274,7 @@ void do_sigreturn32(struct pt_regs *regs) case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32); case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); } + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; @@ -373,6 +376,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) case 2: set.sig[1] = seta.sig[2] + (((long)seta.sig[3]) << 32); case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); } + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; segv: @@ -771,7 +775,7 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, return -EFAULT; } -static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, +static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { @@ -783,9 +787,12 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, err = setup_frame32(ka, regs, signr, oldset); if (err) - return; + return err; + + block_sigmask(ka, signr); + tracehook_signal_handler(signr, info, ka, regs, 0); - signal_delivered(signr, info, ka, regs, 0); + return 0; } static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, @@ -834,7 +841,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs) if (signr > 0) { if (restart_syscall) syscall_restart32(orig_i0, regs, &ka.sa); - handle_signal32(signr, &ka, &info, oldset, regs); + if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) { + /* A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + } return; } if (restart_syscall && @@ -858,7 +872,10 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs) /* If there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + set_current_blocked(¤t->saved_sigmask); + } } struct sigstack32 { diff --git a/trunk/arch/sparc/kernel/signal_32.c b/trunk/arch/sparc/kernel/signal_32.c index 68f9c8650af4..2b7e849f7c65 100644 --- a/trunk/arch/sparc/kernel/signal_32.c +++ b/trunk/arch/sparc/kernel/signal_32.c @@ -29,6 +29,8 @@ #include "sigutil.h" +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + extern void fpsave(unsigned long *fpregs, unsigned long *fsr, void *fpqueue, unsigned long *fpqdepth); extern void fpload(unsigned long *fpregs, unsigned long *fsr); @@ -128,6 +130,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) if (err) goto segv_and_exit; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; @@ -194,6 +197,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) goto segv; } + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; segv: @@ -445,11 +449,10 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, return -EFAULT; } -static inline void +static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, struct pt_regs *regs) + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - sigset_t *oldset = sigmask_to_save(); int err; if (ka->sa.sa_flags & SA_SIGINFO) @@ -458,9 +461,12 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, err = setup_frame(ka, regs, signr, oldset); if (err) - return; + return err; - signal_delivered(signr, info, ka, regs, 0); + block_sigmask(ka, signr); + tracehook_signal_handler(signr, info, ka, regs, 0); + + return 0; } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -492,6 +498,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { struct k_sigaction ka; int restart_syscall; + sigset_t *oldset; siginfo_t info; int signr; @@ -516,6 +523,11 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) regs->u_regs[UREG_G6] = orig_i0; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* If the debugger messes with the program counter, it clears @@ -532,7 +544,15 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, regs); + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } return; } if (restart_syscall && @@ -556,17 +576,22 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) /* if there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + set_current_blocked(¤t->saved_sigmask); + } } void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) { - if (thread_info_flags & _TIF_SIGPENDING) + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) do_signal(regs, orig_i0); if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/sparc/kernel/signal_64.c b/trunk/arch/sparc/kernel/signal_64.c index 867de2f8189c..eafaab486b2d 100644 --- a/trunk/arch/sparc/kernel/signal_64.c +++ b/trunk/arch/sparc/kernel/signal_64.c @@ -38,6 +38,8 @@ #include "systbls.h" #include "sigutil.h" +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* {set, get}context() needed for 64-bit SparcLinux userland. */ asmlinkage void sparc64_set_context(struct pt_regs *regs) { @@ -69,6 +71,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t))) goto do_sigsegv; } + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); } if (test_thread_flag(TIF_32BIT)) { @@ -312,6 +315,7 @@ void do_rt_sigreturn(struct pt_regs *regs) /* Prevent syscall restart. */ pt_regs_clear_syscall(regs); + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; segv: @@ -462,7 +466,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, return -EFAULT; } -static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, +static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { @@ -471,9 +475,12 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, err = setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); if (err) - return; + return err; - signal_delivered(signr, info, ka, regs, 0); + block_sigmask(ka, signr); + tracehook_signal_handler(signr, info, ka, regs, 0); + + return 0; } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -505,7 +512,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { struct k_sigaction ka; int restart_syscall; - sigset_t *oldset = sigmask_to_save(); + sigset_t *oldset; siginfo_t info; int signr; @@ -531,6 +538,11 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) regs->u_regs[UREG_G6] = orig_i0; + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { extern void do_signal32(sigset_t *, struct pt_regs *); @@ -551,7 +563,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, oldset, regs); + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + /* A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + } return; } if (restart_syscall && @@ -575,7 +594,10 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) /* If there's no signal to deliver, we just put the saved sigmask * back */ - restore_saved_sigmask(); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + set_current_blocked(¤t->saved_sigmask); + } } void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) @@ -585,6 +607,8 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/sparc/kernel/sys_sparc_64.c b/trunk/arch/sparc/kernel/sys_sparc_64.c index 275f74fd6f6a..3ee51f189a55 100644 --- a/trunk/arch/sparc/kernel/sys_sparc_64.c +++ b/trunk/arch/sparc/kernel/sys_sparc_64.c @@ -580,9 +580,16 @@ SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr) { + unsigned long ret = -EINVAL; + if (test_thread_flag(TIF_32BIT)) - return -EINVAL; - return sys_mremap(addr, old_len, new_len, flags, new_addr); + goto out; + + down_write(¤t->mm->mmap_sem); + ret = do_mremap(addr, old_len, new_len, flags, new_addr); + up_write(¤t->mm->mmap_sem); +out: + return ret; } /* we come to here via sys_nis_syscall so it can setup the regs argument */ diff --git a/trunk/arch/tile/include/asm/compat.h b/trunk/arch/tile/include/asm/compat.h index 6e74450ff0a1..69adc08d36a5 100644 --- a/trunk/arch/tile/include/asm/compat.h +++ b/trunk/arch/tile/include/asm/compat.h @@ -44,6 +44,7 @@ typedef __kernel_uid32_t __compat_gid32_t; typedef __kernel_mode_t compat_mode_t; typedef __kernel_dev_t compat_dev_t; typedef __kernel_loff_t compat_loff_t; +typedef __kernel_nlink_t compat_nlink_t; typedef __kernel_ipc_pid_t compat_ipc_pid_t; typedef __kernel_daddr_t compat_daddr_t; typedef __kernel_fsid_t compat_fsid_t; diff --git a/trunk/arch/tile/include/asm/thread_info.h b/trunk/arch/tile/include/asm/thread_info.h index e9c670d7a7fe..656c486e64fa 100644 --- a/trunk/arch/tile/include/asm/thread_info.h +++ b/trunk/arch/tile/include/asm/thread_info.h @@ -91,6 +91,11 @@ extern void smp_nap(void); /* Enable interrupts racelessly and nap forever: helper for cpu_idle(). */ extern void _cpu_idle(void); +/* Switch boot idle thread to a freshly-allocated stack and free old stack. */ +extern void cpu_idle_on_new_stack(struct thread_info *old_ti, + unsigned long new_sp, + unsigned long new_ss10); + #else /* __ASSEMBLY__ */ /* @@ -161,23 +166,7 @@ static inline void set_restore_sigmask(void) { struct thread_info *ti = current_thread_info(); ti->status |= TS_RESTORE_SIGMASK; - WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags)); -} -static inline void clear_restore_sigmask(void) -{ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -} -static inline bool test_restore_sigmask(void) -{ - return current_thread_info()->status & TS_RESTORE_SIGMASK; -} -static inline bool test_and_clear_restore_sigmask(void) -{ - struct thread_info *ti = current_thread_info(); - if (!(ti->status & TS_RESTORE_SIGMASK)) - return false; - ti->status &= ~TS_RESTORE_SIGMASK; - return true; + set_bit(TIF_SIGPENDING, &ti->flags); } #endif /* !__ASSEMBLY__ */ diff --git a/trunk/arch/tile/kernel/compat_signal.c b/trunk/arch/tile/kernel/compat_signal.c index 474571b84085..cdef6e5ec022 100644 --- a/trunk/arch/tile/kernel/compat_signal.c +++ b/trunk/arch/tile/kernel/compat_signal.c @@ -118,6 +118,8 @@ struct compat_rt_sigframe { struct compat_ucontext uc; }; +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, struct compat_sigaction __user *oact, size_t sigsetsize) @@ -300,6 +302,7 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) diff --git a/trunk/arch/tile/kernel/entry.S b/trunk/arch/tile/kernel/entry.S index c31637baff28..133c4b56a99e 100644 --- a/trunk/arch/tile/kernel/entry.S +++ b/trunk/arch/tile/kernel/entry.S @@ -68,6 +68,20 @@ STD_ENTRY(KBacktraceIterator_init_current) jrp lr /* keep backtracer happy */ STD_ENDPROC(KBacktraceIterator_init_current) +/* + * Reset our stack to r1/r2 (sp and ksp0+cpu respectively), then + * free the old stack (passed in r0) and re-invoke cpu_idle(). + * We update sp and ksp0 simultaneously to avoid backtracer warnings. + */ +STD_ENTRY(cpu_idle_on_new_stack) + { + move sp, r1 + mtspr SPR_SYSTEM_SAVE_K_0, r2 + } + jal free_thread_info + j cpu_idle + STD_ENDPROC(cpu_idle_on_new_stack) + /* Loop forever on a nap during SMP boot. */ STD_ENTRY(smp_nap) nap diff --git a/trunk/arch/tile/kernel/process.c b/trunk/arch/tile/kernel/process.c index 6be799150501..ba1023d8a021 100644 --- a/trunk/arch/tile/kernel/process.c +++ b/trunk/arch/tile/kernel/process.c @@ -565,6 +565,8 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); return 1; } if (thread_info_flags & _TIF_SINGLESTEP) { diff --git a/trunk/arch/tile/kernel/setup.c b/trunk/arch/tile/kernel/setup.c index dd87f3420390..6098ccc59be2 100644 --- a/trunk/arch/tile/kernel/setup.c +++ b/trunk/arch/tile/kernel/setup.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/arch/tile/kernel/signal.c b/trunk/arch/tile/kernel/signal.c index e29b0553211d..f79d4b88c747 100644 --- a/trunk/arch/tile/kernel/signal.c +++ b/trunk/arch/tile/kernel/signal.c @@ -37,6 +37,8 @@ #define DEBUG_SIG 0 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, stack_t __user *, uoss, struct pt_regs *, regs) { @@ -94,6 +96,7 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) @@ -239,11 +242,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka, +static int handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) { - sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ @@ -276,9 +278,15 @@ static void handle_signal(unsigned long sig, siginfo_t *info, else #endif ret = setup_rt_frame(sig, ka, info, oldset, regs); - if (ret) - return; - signal_delivered(sig, info, ka, regs, 0); + if (ret == 0) { + /* This code is only called from system calls or from + * the work_pending path in the return-to-user code, and + * either way we can re-enable interrupts unconditionally. + */ + block_sigmask(ka, sig); + } + + return ret; } /* @@ -291,6 +299,7 @@ void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * i386 will check if we're coming from kernel mode and bail out @@ -299,10 +308,24 @@ void do_signal(struct pt_regs *regs) * helpful, we can reinstate the check on "!user_mode(regs)". */ + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, regs); + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TS_RESTORE_SIGMASK flag. + */ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + } + goto done; } @@ -327,7 +350,10 @@ void do_signal(struct pt_regs *regs) } /* If there's no signal to deliver, just put the saved sigmask back. */ - restore_saved_sigmask(); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } done: /* Avoid double syscall restart if there are nested signals. */ diff --git a/trunk/arch/um/include/shared/frame_kern.h b/trunk/arch/um/include/shared/frame_kern.h index e584e40ee832..76078490c258 100644 --- a/trunk/arch/um/include/shared/frame_kern.h +++ b/trunk/arch/um/include/shared/frame_kern.h @@ -6,6 +6,9 @@ #ifndef __FRAME_KERN_H_ #define __FRAME_KERN_H_ +#define _S(nr) (1<<((nr)-1)) +#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) + extern int setup_signal_stack_sc(unsigned long stack_top, int sig, struct k_sigaction *ka, struct pt_regs *regs, diff --git a/trunk/arch/um/kernel/process.c b/trunk/arch/um/kernel/process.c index ccb9a9d283f1..3a2235e0abc3 100644 --- a/trunk/arch/um/kernel/process.c +++ b/trunk/arch/um/kernel/process.c @@ -117,8 +117,11 @@ void interrupt_end(void) schedule(); if (test_thread_flag(TIF_SIGPENDING)) do_signal(); - if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) + if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { tracehook_notify_resume(¤t->thread.regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); + } } void exit_thread(void) diff --git a/trunk/arch/um/kernel/reboot.c b/trunk/arch/um/kernel/reboot.c index 3d15243ce692..4d93dff6b371 100644 --- a/trunk/arch/um/kernel/reboot.c +++ b/trunk/arch/um/kernel/reboot.c @@ -4,9 +4,7 @@ */ #include "linux/sched.h" -#include "linux/spinlock.h" #include "linux/slab.h" -#include "linux/oom.h" #include "kern_util.h" #include "os.h" #include "skas.h" @@ -24,18 +22,13 @@ static void kill_off_processes(void) struct task_struct *p; int pid; - read_lock(&tasklist_lock); for_each_process(p) { - struct task_struct *t; - - t = find_lock_task_mm(p); - if (!t) + if (p->mm == NULL) continue; - pid = t->mm->context.id.u.pid; - task_unlock(t); + + pid = p->mm->context.id.u.pid; os_kill_ptraced_process(pid, 1); } - read_unlock(&tasklist_lock); } } diff --git a/trunk/arch/um/kernel/signal.c b/trunk/arch/um/kernel/signal.c index 7362d58efc29..292e706016c5 100644 --- a/trunk/arch/um/kernel/signal.c +++ b/trunk/arch/um/kernel/signal.c @@ -15,13 +15,17 @@ EXPORT_SYMBOL(block_signals); EXPORT_SYMBOL(unblock_signals); +#define _S(nr) (1<<((nr)-1)) + +#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) + /* * OK, we're invoking a handler */ -static void handle_signal(struct pt_regs *regs, unsigned long signr, - struct k_sigaction *ka, siginfo_t *info) +static int handle_signal(struct pt_regs *regs, unsigned long signr, + struct k_sigaction *ka, siginfo_t *info, + sigset_t *oldset) { - sigset_t *oldset = sigmask_to_save(); unsigned long sp; int err; @@ -61,7 +65,9 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, if (err) force_sigsegv(signr, current); else - signal_delivered(signr, info, ka, regs, 0); + block_sigmask(ka, signr); + + return err; } static int kern_do_signal(struct pt_regs *regs) @@ -71,9 +77,24 @@ static int kern_do_signal(struct pt_regs *regs) int sig, handled_sig = 0; while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { + sigset_t *oldset; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; handled_sig = 1; /* Whee! Actually deliver the signal. */ - handle_signal(regs, sig, &ka_copy, &info); + if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) { + /* + * a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + break; + } } /* Did we come from a system call? */ @@ -109,8 +130,10 @@ static int kern_do_signal(struct pt_regs *regs) * if there's no signal to deliver, we just put the saved sigmask * back */ - if (!handled_sig) - restore_saved_sigmask(); + if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return handled_sig; } diff --git a/trunk/arch/um/kernel/trap.c b/trunk/arch/um/kernel/trap.c index 3be60765c0e2..dafc94715950 100644 --- a/trunk/arch/um/kernel/trap.c +++ b/trunk/arch/um/kernel/trap.c @@ -30,8 +30,6 @@ int handle_page_fault(unsigned long address, unsigned long ip, pmd_t *pmd; pte_t *pte; int err = -EFAULT; - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | - (is_write ? FAULT_FLAG_WRITE : 0); *code_out = SEGV_MAPERR; @@ -42,7 +40,6 @@ int handle_page_fault(unsigned long address, unsigned long ip, if (in_atomic()) goto out_nosemaphore; -retry: down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -68,11 +65,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, do { int fault; - fault = handle_mm_fault(mm, vma, address, flags); - - if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) - goto out_nosemaphore; - + fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) { goto out_of_memory; @@ -82,17 +75,10 @@ int handle_page_fault(unsigned long address, unsigned long ip, } BUG(); } - if (flags & FAULT_FLAG_ALLOW_RETRY) { - if (fault & VM_FAULT_MAJOR) - current->maj_flt++; - else - current->min_flt++; - if (fault & VM_FAULT_RETRY) { - flags &= ~FAULT_FLAG_ALLOW_RETRY; - - goto retry; - } - } + if (fault & VM_FAULT_MAJOR) + current->maj_flt++; + else + current->min_flt++; pgd = pgd_offset(mm, address); pud = pud_offset(pgd, address); diff --git a/trunk/arch/unicore32/kernel/signal.c b/trunk/arch/unicore32/kernel/signal.c index 8adedb37720a..7754df6ef7d4 100644 --- a/trunk/arch/unicore32/kernel/signal.c +++ b/trunk/arch/unicore32/kernel/signal.c @@ -21,6 +21,8 @@ #include #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + /* * For UniCore syscalls, we encode the syscall number into the instruction. */ @@ -59,8 +61,10 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) int err; err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); - if (err == 0) + if (err == 0) { + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); + } err |= __get_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00); err |= __get_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01); @@ -308,12 +312,13 @@ static inline void setup_syscall_restart(struct pt_regs *regs) /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, struct pt_regs *regs, int syscall) +static int handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs *regs, int syscall) { struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; - sigset_t *oldset = sigmask_to_save(); + sigset_t blocked; int usig = sig; int ret; @@ -359,10 +364,15 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, if (ret != 0) { force_sigsegv(sig, tsk); - return; + return ret; } - signal_delivered(sig, info, ka, regs, 0); + /* + * Block the signal if we were successful. + */ + block_sigmask(ka, sig); + + return 0; } /* @@ -389,12 +399,32 @@ static void do_signal(struct pt_regs *regs, int syscall) if (!user_mode(regs)) return; + if (try_to_freeze()) + goto no_signal; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - handle_signal(signr, &ka, &info, regs, syscall); + sigset_t *oldset; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + if (handle_signal(signr, &ka, &info, oldset, regs, syscall) + == 0) { + /* + * A signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } return; } + no_signal: /* * No signal to deliver to the process - restart the syscall. */ @@ -421,7 +451,8 @@ static void do_signal(struct pt_regs *regs, int syscall) /* If there's no signal to deliver, we just put the saved * sigmask back. */ - restore_saved_sigmask(); + if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) + set_current_blocked(¤t->saved_sigmask); } asmlinkage void do_notify_resume(struct pt_regs *regs, @@ -433,6 +464,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, if (thread_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } } diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index c70684f859e1..d700811785ea 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -1506,8 +1506,6 @@ config EFI_STUB This kernel feature allows a bzImage to be loaded directly by EFI firmware without the use of a bootloader. - See Documentation/x86/efi-stub.txt for more information. - config SECCOMP def_bool y prompt "Enable seccomp to safely compute untrusted bytecode" diff --git a/trunk/arch/x86/boot/compressed/eboot.c b/trunk/arch/x86/boot/compressed/eboot.c index 4e85f5f85837..2c14e76bb4c7 100644 --- a/trunk/arch/x86/boot/compressed/eboot.c +++ b/trunk/arch/x86/boot/compressed/eboot.c @@ -16,26 +16,6 @@ static efi_system_table_t *sys_table; -static void efi_printk(char *str) -{ - char *s8; - - for (s8 = str; *s8; s8++) { - struct efi_simple_text_output_protocol *out; - efi_char16_t ch[2] = { 0 }; - - ch[0] = *s8; - out = (struct efi_simple_text_output_protocol *)sys_table->con_out; - - if (*s8 == '\n') { - efi_char16_t nl[2] = { '\r', 0 }; - efi_call_phys2(out->output_string, out, nl); - } - - efi_call_phys2(out->output_string, out, ch); - } -} - static efi_status_t __get_map(efi_memory_desc_t **map, unsigned long *map_size, unsigned long *desc_size) { @@ -551,10 +531,8 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image, EFI_LOADER_DATA, nr_initrds * sizeof(*initrds), &initrds); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc mem for initrds\n"); + if (status != EFI_SUCCESS) goto fail; - } str = (char *)(unsigned long)hdr->cmd_line_ptr; for (i = 0; i < nr_initrds; i++) { @@ -597,42 +575,32 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image, status = efi_call_phys3(boottime->handle_protocol, image->device_handle, &fs_proto, &io); - if (status != EFI_SUCCESS) { - efi_printk("Failed to handle fs_proto\n"); + if (status != EFI_SUCCESS) goto free_initrds; - } status = efi_call_phys2(io->open_volume, io, &fh); - if (status != EFI_SUCCESS) { - efi_printk("Failed to open volume\n"); + if (status != EFI_SUCCESS) goto free_initrds; - } } status = efi_call_phys5(fh->open, fh, &h, filename_16, EFI_FILE_MODE_READ, (u64)0); - if (status != EFI_SUCCESS) { - efi_printk("Failed to open initrd file\n"); + if (status != EFI_SUCCESS) goto close_handles; - } initrd->handle = h; info_sz = 0; status = efi_call_phys4(h->get_info, h, &info_guid, &info_sz, NULL); - if (status != EFI_BUFFER_TOO_SMALL) { - efi_printk("Failed to get initrd info size\n"); + if (status != EFI_BUFFER_TOO_SMALL) goto close_handles; - } grow: status = efi_call_phys3(sys_table->boottime->allocate_pool, EFI_LOADER_DATA, info_sz, &info); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc mem for initrd info\n"); + if (status != EFI_SUCCESS) goto close_handles; - } status = efi_call_phys4(h->get_info, h, &info_guid, &info_sz, info); @@ -644,10 +612,8 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image, file_sz = info->file_size; efi_call_phys1(sys_table->boottime->free_pool, info); - if (status != EFI_SUCCESS) { - efi_printk("Failed to get initrd info\n"); + if (status != EFI_SUCCESS) goto close_handles; - } initrd->size = file_sz; initrd_total += file_sz; @@ -663,14 +629,11 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image, */ status = high_alloc(initrd_total, 0x1000, &initrd_addr, hdr->initrd_addr_max); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc highmem for initrds\n"); + if (status != EFI_SUCCESS) goto close_handles; - } /* We've run out of free low memory. */ if (initrd_addr > hdr->initrd_addr_max) { - efi_printk("We've run out of free low memory\n"); status = EFI_INVALID_PARAMETER; goto free_initrd_total; } @@ -689,10 +652,8 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image, status = efi_call_phys3(fh->read, initrds[j].handle, &chunksize, addr); - if (status != EFI_SUCCESS) { - efi_printk("Failed to read initrd\n"); + if (status != EFI_SUCCESS) goto free_initrd_total; - } addr += chunksize; size -= chunksize; } @@ -713,7 +674,7 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image, low_free(initrd_total, initrd_addr); close_handles: - for (k = j; k < i; k++) + for (k = j; k < nr_initrds; k++) efi_call_phys1(fh->close, initrds[k].handle); free_initrds: efi_call_phys1(sys_table->boottime->free_pool, initrds); @@ -771,10 +732,8 @@ static efi_status_t make_boot_params(struct boot_params *boot_params, options_size++; /* NUL termination */ status = low_alloc(options_size, 1, &cmdline); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc mem for cmdline\n"); + if (status != EFI_SUCCESS) goto fail; - } s1 = (u8 *)(unsigned long)cmdline; s2 = (u16 *)options; @@ -936,16 +895,12 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) status = efi_call_phys3(sys_table->boottime->handle_protocol, handle, &proto, (void *)&image); - if (status != EFI_SUCCESS) { - efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); + if (status != EFI_SUCCESS) goto fail; - } status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc lowmem for boot params\n"); + if (status != EFI_SUCCESS) goto fail; - } memset(boot_params, 0x0, 0x4000); @@ -978,10 +933,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) if (status != EFI_SUCCESS) { status = low_alloc(hdr->init_size, hdr->kernel_alignment, &start); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc mem for kernel\n"); + if (status != EFI_SUCCESS) goto fail; - } } hdr->code32_start = (__u32)start; @@ -992,25 +945,19 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) status = efi_call_phys3(sys_table->boottime->allocate_pool, EFI_LOADER_DATA, sizeof(*gdt), (void **)&gdt); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc mem for gdt structure\n"); + if (status != EFI_SUCCESS) goto fail; - } gdt->size = 0x800; status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc mem for gdt\n"); + if (status != EFI_SUCCESS) goto fail; - } status = efi_call_phys3(sys_table->boottime->allocate_pool, EFI_LOADER_DATA, sizeof(*idt), (void **)&idt); - if (status != EFI_SUCCESS) { - efi_printk("Failed to alloc mem for idt structure\n"); + if (status != EFI_SUCCESS) goto fail; - } idt->size = 0; idt->address = 0; diff --git a/trunk/arch/x86/boot/compressed/eboot.h b/trunk/arch/x86/boot/compressed/eboot.h index 3b6e15627c55..39251663e65b 100644 --- a/trunk/arch/x86/boot/compressed/eboot.h +++ b/trunk/arch/x86/boot/compressed/eboot.h @@ -58,10 +58,4 @@ struct efi_uga_draw_protocol { void *blt; }; -struct efi_simple_text_output_protocol { - void *reset; - void *output_string; - void *test_string; -}; - #endif /* BOOT_COMPRESSED_EBOOT_H */ diff --git a/trunk/arch/x86/boot/header.S b/trunk/arch/x86/boot/header.S index efe5acfc79c3..8bbea6aa40d9 100644 --- a/trunk/arch/x86/boot/header.S +++ b/trunk/arch/x86/boot/header.S @@ -94,10 +94,10 @@ bs_die: .section ".bsdata", "a" bugger_off_msg: - .ascii "Direct floppy boot is not supported. " - .ascii "Use a boot loader program instead.\r\n" + .ascii "Direct booting from floppy is no longer supported.\r\n" + .ascii "Please use a boot loader program instead.\r\n" .ascii "\n" - .ascii "Remove disk and press any key to reboot ...\r\n" + .ascii "Remove disk and press any key to reboot . . .\r\n" .byte 0 #ifdef CONFIG_EFI_STUB @@ -111,7 +111,7 @@ coff_header: #else .word 0x8664 # x86-64 #endif - .word 3 # nr_sections + .word 2 # nr_sections .long 0 # TimeDateStamp .long 0 # PointerToSymbolTable .long 1 # NumberOfSymbols @@ -158,8 +158,8 @@ extra_header_fields: #else .quad 0 # ImageBase #endif - .long 0x20 # SectionAlignment - .long 0x20 # FileAlignment + .long 0x1000 # SectionAlignment + .long 0x200 # FileAlignment .word 0 # MajorOperatingSystemVersion .word 0 # MinorOperatingSystemVersion .word 0 # MajorImageVersion @@ -200,10 +200,8 @@ extra_header_fields: # Section table section_table: - # - # The offset & size fields are filled in by build.c. - # - .ascii ".setup" + .ascii ".text" + .byte 0 .byte 0 .byte 0 .long 0 @@ -219,8 +217,9 @@ section_table: # # The EFI application loader requires a relocation section - # because EFI applications must be relocatable. The .reloc - # offset & size fields are filled in by build.c. + # because EFI applications must be relocatable. But since + # we don't need the loader to fixup any relocs for us, we + # just create an empty (zero-length) .reloc section header. # .ascii ".reloc" .byte 0 @@ -234,25 +233,6 @@ section_table: .word 0 # NumberOfRelocations .word 0 # NumberOfLineNumbers .long 0x42100040 # Characteristics (section flags) - - # - # The offset & size fields are filled in by build.c. - # - .ascii ".text" - .byte 0 - .byte 0 - .byte 0 - .long 0 - .long 0x0 # startup_{32,64} - .long 0 # Size of initialized data - # on disk - .long 0x0 # startup_{32,64} - .long 0 # PointerToRelocations - .long 0 # PointerToLineNumbers - .word 0 # NumberOfRelocations - .word 0 # NumberOfLineNumbers - .long 0x60500020 # Characteristics (section flags) - #endif /* CONFIG_EFI_STUB */ # Kernel attributes; used by setup. This is part 1 of the diff --git a/trunk/arch/x86/boot/tools/build.c b/trunk/arch/x86/boot/tools/build.c index 4b8e165ee572..3f61f6e2b46f 100644 --- a/trunk/arch/x86/boot/tools/build.c +++ b/trunk/arch/x86/boot/tools/build.c @@ -50,8 +50,6 @@ typedef unsigned int u32; u8 buf[SETUP_SECT_MAX*512]; int is_big_kernel; -#define PECOFF_RELOC_RESERVE 0x20 - /*----------------------------------------------------------------------*/ static const u32 crctab32[] = { @@ -135,103 +133,11 @@ static void usage(void) die("Usage: build setup system [> image]"); } -#ifdef CONFIG_EFI_STUB - -static void update_pecoff_section_header(char *section_name, u32 offset, u32 size) -{ - unsigned int pe_header; - unsigned short num_sections; - u8 *section; - - pe_header = get_unaligned_le32(&buf[0x3c]); - num_sections = get_unaligned_le16(&buf[pe_header + 6]); - -#ifdef CONFIG_X86_32 - section = &buf[pe_header + 0xa8]; -#else - section = &buf[pe_header + 0xb8]; -#endif - - while (num_sections > 0) { - if (strncmp((char*)section, section_name, 8) == 0) { - /* section header size field */ - put_unaligned_le32(size, section + 0x8); - - /* section header vma field */ - put_unaligned_le32(offset, section + 0xc); - - /* section header 'size of initialised data' field */ - put_unaligned_le32(size, section + 0x10); - - /* section header 'file offset' field */ - put_unaligned_le32(offset, section + 0x14); - - break; - } - section += 0x28; - num_sections--; - } -} - -static void update_pecoff_setup_and_reloc(unsigned int size) -{ - u32 setup_offset = 0x200; - u32 reloc_offset = size - PECOFF_RELOC_RESERVE; - u32 setup_size = reloc_offset - setup_offset; - - update_pecoff_section_header(".setup", setup_offset, setup_size); - update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE); - - /* - * Modify .reloc section contents with a single entry. The - * relocation is applied to offset 10 of the relocation section. - */ - put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]); - put_unaligned_le32(10, &buf[reloc_offset + 4]); -} - -static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) -{ - unsigned int pe_header; - unsigned int text_sz = file_sz - text_start; - - pe_header = get_unaligned_le32(&buf[0x3c]); - - /* Size of image */ - put_unaligned_le32(file_sz, &buf[pe_header + 0x50]); - - /* - * Size of code: Subtract the size of the first sector (512 bytes) - * which includes the header. - */ - put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]); - -#ifdef CONFIG_X86_32 - /* - * Address of entry point. - * - * The EFI stub entry point is +16 bytes from the start of - * the .text section. - */ - put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]); -#else - /* - * Address of entry point. startup_32 is at the beginning and - * the 64-bit entry point (startup_64) is always 512 bytes - * after. The EFI stub entry point is 16 bytes after that, as - * the first instruction allows legacy loaders to jump over - * the EFI stub initialisation - */ - put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]); -#endif /* CONFIG_X86_32 */ - - update_pecoff_section_header(".text", text_start, text_sz); -} - -#endif /* CONFIG_EFI_STUB */ - int main(int argc, char ** argv) { +#ifdef CONFIG_EFI_STUB + unsigned int file_sz, pe_header; +#endif unsigned int i, sz, setup_sectors; int c; u32 sys_size; @@ -257,12 +163,6 @@ int main(int argc, char ** argv) die("Boot block hasn't got boot flag (0xAA55)"); fclose(file); -#ifdef CONFIG_EFI_STUB - /* Reserve 0x20 bytes for .reloc section */ - memset(buf+c, 0, PECOFF_RELOC_RESERVE); - c += PECOFF_RELOC_RESERVE; -#endif - /* Pad unused space with zeros */ setup_sectors = (c + 511) / 512; if (setup_sectors < SETUP_SECT_MIN) @@ -270,10 +170,6 @@ int main(int argc, char ** argv) i = setup_sectors*512; memset(buf+c, 0, i-c); -#ifdef CONFIG_EFI_STUB - update_pecoff_setup_and_reloc(i); -#endif - /* Set the default root device */ put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]); @@ -298,8 +194,66 @@ int main(int argc, char ** argv) put_unaligned_le32(sys_size, &buf[0x1f4]); #ifdef CONFIG_EFI_STUB - update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); -#endif + file_sz = sz + i + ((sys_size * 16) - sz); + + pe_header = get_unaligned_le32(&buf[0x3c]); + + /* Size of image */ + put_unaligned_le32(file_sz, &buf[pe_header + 0x50]); + + /* + * Subtract the size of the first section (512 bytes) which + * includes the header and .reloc section. The remaining size + * is that of the .text section. + */ + file_sz -= 512; + + /* Size of code */ + put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]); + +#ifdef CONFIG_X86_32 + /* + * Address of entry point. + * + * The EFI stub entry point is +16 bytes from the start of + * the .text section. + */ + put_unaligned_le32(i + 16, &buf[pe_header + 0x28]); + + /* .text size */ + put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]); + + /* .text vma */ + put_unaligned_le32(0x200, &buf[pe_header + 0xb4]); + + /* .text size of initialised data */ + put_unaligned_le32(file_sz, &buf[pe_header + 0xb8]); + + /* .text file offset */ + put_unaligned_le32(0x200, &buf[pe_header + 0xbc]); +#else + /* + * Address of entry point. startup_32 is at the beginning and + * the 64-bit entry point (startup_64) is always 512 bytes + * after. The EFI stub entry point is 16 bytes after that, as + * the first instruction allows legacy loaders to jump over + * the EFI stub initialisation + */ + put_unaligned_le32(i + 528, &buf[pe_header + 0x28]); + + /* .text size */ + put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]); + + /* .text vma */ + put_unaligned_le32(0x200, &buf[pe_header + 0xc4]); + + /* .text size of initialised data */ + put_unaligned_le32(file_sz, &buf[pe_header + 0xc8]); + + /* .text file offset */ + put_unaligned_le32(0x200, &buf[pe_header + 0xcc]); +#endif /* CONFIG_X86_32 */ +#endif /* CONFIG_EFI_STUB */ crc = partial_crc32(buf, i, crc); if (fwrite(buf, 1, i, stdout) != i) diff --git a/trunk/arch/x86/crypto/aesni-intel_asm.S b/trunk/arch/x86/crypto/aesni-intel_asm.S index 3470624d7835..be6d9e365a80 100644 --- a/trunk/arch/x86/crypto/aesni-intel_asm.S +++ b/trunk/arch/x86/crypto/aesni-intel_asm.S @@ -2460,12 +2460,10 @@ ENTRY(aesni_cbc_dec) pxor IN3, STATE4 movaps IN4, IV #else + pxor (INP), STATE2 + pxor 0x10(INP), STATE3 pxor IN1, STATE4 movaps IN2, IV - movups (INP), IN1 - pxor IN1, STATE2 - movups 0x10(INP), IN2 - pxor IN2, STATE3 #endif movups STATE1, (OUTP) movups STATE2, 0x10(OUTP) diff --git a/trunk/arch/x86/ia32/ia32_signal.c b/trunk/arch/x86/ia32/ia32_signal.c index daeca56211e3..98bd70faccc5 100644 --- a/trunk/arch/x86/ia32/ia32_signal.c +++ b/trunk/arch/x86/ia32/ia32_signal.c @@ -273,6 +273,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs) sizeof(frame->extramask)))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (ia32_restore_sigcontext(regs, &frame->sc, &ax)) @@ -298,6 +299,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) diff --git a/trunk/arch/x86/include/asm/ftrace.h b/trunk/arch/x86/include/asm/ftrace.h index b0767bc08740..18d9005d9e4f 100644 --- a/trunk/arch/x86/include/asm/ftrace.h +++ b/trunk/arch/x86/include/asm/ftrace.h @@ -34,7 +34,7 @@ #ifndef __ASSEMBLY__ extern void mcount(void); -extern atomic_t modifying_ftrace_code; +extern int modifying_ftrace_code; static inline unsigned long ftrace_call_adjust(unsigned long addr) { diff --git a/trunk/arch/x86/include/asm/nmi.h b/trunk/arch/x86/include/asm/nmi.h index dc580c42851c..0e3793b821ef 100644 --- a/trunk/arch/x86/include/asm/nmi.h +++ b/trunk/arch/x86/include/asm/nmi.h @@ -54,20 +54,6 @@ struct nmiaction { __register_nmi_handler((t), &fn##_na); \ }) -/* - * For special handlers that register/unregister in the - * init section only. This should be considered rare. - */ -#define register_nmi_handler_initonly(t, fn, fg, n) \ -({ \ - static struct nmiaction fn##_na __initdata = { \ - .handler = (fn), \ - .name = (n), \ - .flags = (fg), \ - }; \ - __register_nmi_handler((t), &fn##_na); \ -}) - int __register_nmi_handler(unsigned int, struct nmiaction *); void unregister_nmi_handler(unsigned int, const char *); diff --git a/trunk/arch/x86/include/asm/posix_types_32.h b/trunk/arch/x86/include/asm/posix_types_32.h index 8e525059e7d8..99f262e04b91 100644 --- a/trunk/arch/x86/include/asm/posix_types_32.h +++ b/trunk/arch/x86/include/asm/posix_types_32.h @@ -10,6 +10,9 @@ typedef unsigned short __kernel_mode_t; #define __kernel_mode_t __kernel_mode_t +typedef unsigned short __kernel_nlink_t; +#define __kernel_nlink_t __kernel_nlink_t + typedef unsigned short __kernel_ipc_pid_t; #define __kernel_ipc_pid_t __kernel_ipc_pid_t diff --git a/trunk/arch/x86/include/asm/sighandling.h b/trunk/arch/x86/include/asm/sighandling.h index beff97f7df37..ada93b3b8c66 100644 --- a/trunk/arch/x86/include/asm/sighandling.h +++ b/trunk/arch/x86/include/asm/sighandling.h @@ -7,6 +7,8 @@ #include +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + #define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \ X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \ X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \ diff --git a/trunk/arch/x86/include/asm/thread_info.h b/trunk/arch/x86/include/asm/thread_info.h index 89f794f007ec..5c25de07cba8 100644 --- a/trunk/arch/x86/include/asm/thread_info.h +++ b/trunk/arch/x86/include/asm/thread_info.h @@ -248,23 +248,7 @@ static inline void set_restore_sigmask(void) { struct thread_info *ti = current_thread_info(); ti->status |= TS_RESTORE_SIGMASK; - WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags)); -} -static inline void clear_restore_sigmask(void) -{ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; -} -static inline bool test_restore_sigmask(void) -{ - return current_thread_info()->status & TS_RESTORE_SIGMASK; -} -static inline bool test_and_clear_restore_sigmask(void) -{ - struct thread_info *ti = current_thread_info(); - if (!(ti->status & TS_RESTORE_SIGMASK)) - return false; - ti->status &= ~TS_RESTORE_SIGMASK; - return true; + set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); } static inline bool is_ia32_task(void) diff --git a/trunk/arch/x86/include/asm/uaccess.h b/trunk/arch/x86/include/asm/uaccess.h index e1f3a17034fc..04cd6882308e 100644 --- a/trunk/arch/x86/include/asm/uaccess.h +++ b/trunk/arch/x86/include/asm/uaccess.h @@ -33,8 +33,9 @@ #define segment_eq(a, b) ((a).seg == (b).seg) #define user_addr_max() (current_thread_info()->addr_limit.seg) -#define __addr_ok(addr) \ - ((unsigned long __force)(addr) < user_addr_max()) +#define __addr_ok(addr) \ + ((unsigned long __force)(addr) < \ + (current_thread_info()->addr_limit.seg)) /* * Test whether a block of memory is a valid user space address. @@ -46,14 +47,14 @@ * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... */ -#define __range_not_ok(addr, size, limit) \ +#define __range_not_ok(addr, size) \ ({ \ unsigned long flag, roksum; \ __chk_user_ptr(addr); \ asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \ : "=&r" (flag), "=r" (roksum) \ : "1" (addr), "g" ((long)(size)), \ - "rm" (limit)); \ + "rm" (current_thread_info()->addr_limit.seg)); \ flag; \ }) @@ -76,8 +77,7 @@ * checks that the pointer is in the user space range - after calling * this function, memory access functions may still return -EFAULT. */ -#define access_ok(type, addr, size) \ - (likely(__range_not_ok(addr, size, user_addr_max()) == 0)) +#define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0)) /* * The exception table consists of pairs of addresses relative to the diff --git a/trunk/arch/x86/include/asm/uv/uv_bau.h b/trunk/arch/x86/include/asm/uv/uv_bau.h index 6149b476d9df..becf47b81735 100644 --- a/trunk/arch/x86/include/asm/uv/uv_bau.h +++ b/trunk/arch/x86/include/asm/uv/uv_bau.h @@ -149,6 +149,7 @@ /* 4 bits of software ack period */ #define UV2_ACK_MASK 0x7UL #define UV2_ACK_UNITS_SHFT 3 +#define UV2_LEG_SHFT UV2H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_SHFT #define UV2_EXT_SHFT UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT /* diff --git a/trunk/arch/x86/kernel/aperture_64.c b/trunk/arch/x86/kernel/aperture_64.c index d5fd66f0d4cd..6e76c191a835 100644 --- a/trunk/arch/x86/kernel/aperture_64.c +++ b/trunk/arch/x86/kernel/aperture_64.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,11 @@ static u32 __init allocate_aperture(void) return 0; } memblock_reserve(addr, aper_size); + /* + * Kmemleak should not scan this block as it may not be mapped via the + * kernel direct mapping. + */ + kmemleak_ignore(phys_to_virt(addr)); printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n", aper_size >> 10, addr); insert_aperture_resource((u32)addr, aper_size); diff --git a/trunk/arch/x86/kernel/apic/io_apic.c b/trunk/arch/x86/kernel/apic/io_apic.c index 5f0ff597437c..ac96561d1a99 100644 --- a/trunk/arch/x86/kernel/apic/io_apic.c +++ b/trunk/arch/x86/kernel/apic/io_apic.c @@ -1195,7 +1195,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) BUG_ON(!cfg->vector); vector = cfg->vector; - for_each_cpu(cpu, cfg->domain) + for_each_cpu_and(cpu, cfg->domain, cpu_online_mask) per_cpu(vector_irq, cpu)[vector] = -1; cfg->vector = 0; @@ -1203,7 +1203,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) if (likely(!cfg->move_in_progress)) return; - for_each_cpu(cpu, cfg->old_domain) { + for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) { for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { if (per_cpu(vector_irq, cpu)[vector] != irq) diff --git a/trunk/arch/x86/kernel/cpu/common.c b/trunk/arch/x86/kernel/cpu/common.c index 6b9333b429ba..82f29e70d058 100644 --- a/trunk/arch/x86/kernel/cpu/common.c +++ b/trunk/arch/x86/kernel/cpu/common.c @@ -1101,20 +1101,14 @@ int is_debug_stack(unsigned long addr) addr > (__get_cpu_var(debug_stack_addr) - DEBUG_STKSZ)); } -static DEFINE_PER_CPU(u32, debug_stack_use_ctr); - void debug_stack_set_zero(void) { - this_cpu_inc(debug_stack_use_ctr); load_idt((const struct desc_ptr *)&nmi_idt_descr); } void debug_stack_reset(void) { - if (WARN_ON(!this_cpu_read(debug_stack_use_ctr))) - return; - if (this_cpu_dec_return(debug_stack_use_ctr) == 0) - load_idt((const struct desc_ptr *)&idt_descr); + load_idt((const struct desc_ptr *)&idt_descr); } #else /* CONFIG_X86_64 */ diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce.c b/trunk/arch/x86/kernel/cpu/mcheck/mce.c index da27c5d2168a..0a687fd185e6 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce.c @@ -1274,7 +1274,7 @@ static void mce_timer_fn(unsigned long data) */ iv = __this_cpu_read(mce_next_interval); if (mce_notify_irq()) - iv = max(iv / 2, (unsigned long) HZ/100); + iv = max(iv, (unsigned long) HZ/100); else iv = min(iv * 2, round_jiffies_relative(check_interval * HZ)); __this_cpu_write(mce_next_interval, iv); @@ -1557,7 +1557,7 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) static void __mcheck_cpu_init_timer(void) { struct timer_list *t = &__get_cpu_var(mce_timer); - unsigned long iv = check_interval * HZ; + unsigned long iv = __this_cpu_read(mce_next_interval); setup_timer(t, mce_timer_fn, smp_processor_id()); diff --git a/trunk/arch/x86/kernel/cpu/perf_event.c b/trunk/arch/x86/kernel/cpu/perf_event.c index c4706cf9c011..e049d6da0183 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.c +++ b/trunk/arch/x86/kernel/cpu/perf_event.c @@ -1496,7 +1496,6 @@ static struct cpu_hw_events *allocate_fake_cpuc(void) if (!cpuc->shared_regs) goto error; } - cpuc->is_fake = 1; return cpuc; error: free_fake_cpuc(cpuc); @@ -1757,12 +1756,6 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); } -static inline int -valid_user_frame(const void __user *fp, unsigned long size) -{ - return (__range_not_ok(fp, size, TASK_SIZE) == 0); -} - #ifdef CONFIG_COMPAT #include @@ -1787,7 +1780,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) if (bytes != sizeof(frame)) break; - if (!valid_user_frame(fp, sizeof(frame))) + if (fp < compat_ptr(regs->sp)) break; perf_callchain_store(entry, frame.return_address); @@ -1833,7 +1826,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) if (bytes != sizeof(frame)) break; - if (!valid_user_frame(fp, sizeof(frame))) + if ((unsigned long)fp < regs->sp) break; perf_callchain_store(entry, frame.return_address); diff --git a/trunk/arch/x86/kernel/cpu/perf_event.h b/trunk/arch/x86/kernel/cpu/perf_event.h index 7241e2fc3c17..6638aaf54493 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.h +++ b/trunk/arch/x86/kernel/cpu/perf_event.h @@ -117,7 +117,6 @@ struct cpu_hw_events { struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ unsigned int group_flag; - int is_fake; /* * Intel DebugStore bits @@ -365,7 +364,6 @@ struct x86_pmu { int pebs_record_size; void (*drain_pebs)(struct pt_regs *regs); struct event_constraint *pebs_constraints; - void (*pebs_aliases)(struct perf_event *event); /* * Intel LBR diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel.c b/trunk/arch/x86/kernel/cpu/perf_event_intel.c index 187c294bc658..166546ec6aef 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel.c @@ -1119,33 +1119,27 @@ intel_bts_constraints(struct perf_event *event) return NULL; } -static int intel_alt_er(int idx) +static bool intel_try_alt_er(struct perf_event *event, int orig_idx) { if (!(x86_pmu.er_flags & ERF_HAS_RSP_1)) - return idx; + return false; - if (idx == EXTRA_REG_RSP_0) - return EXTRA_REG_RSP_1; - - if (idx == EXTRA_REG_RSP_1) - return EXTRA_REG_RSP_0; - - return idx; -} - -static void intel_fixup_er(struct perf_event *event, int idx) -{ - event->hw.extra_reg.idx = idx; - - if (idx == EXTRA_REG_RSP_0) { - event->hw.config &= ~INTEL_ARCH_EVENT_MASK; - event->hw.config |= 0x01b7; - event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0; - } else if (idx == EXTRA_REG_RSP_1) { + if (event->hw.extra_reg.idx == EXTRA_REG_RSP_0) { event->hw.config &= ~INTEL_ARCH_EVENT_MASK; event->hw.config |= 0x01bb; + event->hw.extra_reg.idx = EXTRA_REG_RSP_1; event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1; + } else if (event->hw.extra_reg.idx == EXTRA_REG_RSP_1) { + event->hw.config &= ~INTEL_ARCH_EVENT_MASK; + event->hw.config |= 0x01b7; + event->hw.extra_reg.idx = EXTRA_REG_RSP_0; + event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0; } + + if (event->hw.extra_reg.idx == orig_idx) + return false; + + return true; } /* @@ -1163,18 +1157,14 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, struct event_constraint *c = &emptyconstraint; struct er_account *era; unsigned long flags; - int idx = reg->idx; + int orig_idx = reg->idx; - /* - * reg->alloc can be set due to existing state, so for fake cpuc we - * need to ignore this, otherwise we might fail to allocate proper fake - * state for this extra reg constraint. Also see the comment below. - */ - if (reg->alloc && !cpuc->is_fake) + /* already allocated shared msr */ + if (reg->alloc) return NULL; /* call x86_get_event_constraint() */ again: - era = &cpuc->shared_regs->regs[idx]; + era = &cpuc->shared_regs->regs[reg->idx]; /* * we use spin_lock_irqsave() to avoid lockdep issues when * passing a fake cpuc @@ -1183,29 +1173,6 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, if (!atomic_read(&era->ref) || era->config == reg->config) { - /* - * If its a fake cpuc -- as per validate_{group,event}() we - * shouldn't touch event state and we can avoid doing so - * since both will only call get_event_constraints() once - * on each event, this avoids the need for reg->alloc. - * - * Not doing the ER fixup will only result in era->reg being - * wrong, but since we won't actually try and program hardware - * this isn't a problem either. - */ - if (!cpuc->is_fake) { - if (idx != reg->idx) - intel_fixup_er(event, idx); - - /* - * x86_schedule_events() can call get_event_constraints() - * multiple times on events in the case of incremental - * scheduling(). reg->alloc ensures we only do the ER - * allocation once. - */ - reg->alloc = 1; - } - /* lock in msr value */ era->config = reg->config; era->reg = reg->reg; @@ -1213,17 +1180,17 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, /* one more user */ atomic_inc(&era->ref); + /* no need to reallocate during incremental event scheduling */ + reg->alloc = 1; + /* * need to call x86_get_event_constraint() * to check if associated event has constraints */ c = NULL; - } else { - idx = intel_alt_er(idx); - if (idx != reg->idx) { - raw_spin_unlock_irqrestore(&era->lock, flags); - goto again; - } + } else if (intel_try_alt_er(event, orig_idx)) { + raw_spin_unlock_irqrestore(&era->lock, flags); + goto again; } raw_spin_unlock_irqrestore(&era->lock, flags); @@ -1237,14 +1204,11 @@ __intel_shared_reg_put_constraints(struct cpu_hw_events *cpuc, struct er_account *era; /* - * Only put constraint if extra reg was actually allocated. Also takes - * care of event which do not use an extra shared reg. - * - * Also, if this is a fake cpuc we shouldn't touch any event state - * (reg->alloc) and we don't care about leaving inconsistent cpuc state - * either since it'll be thrown out. + * only put constraint if extra reg was actually + * allocated. Also takes care of event which do + * not use an extra shared reg */ - if (!reg->alloc || cpuc->is_fake) + if (!reg->alloc) return; era = &cpuc->shared_regs->regs[reg->idx]; @@ -1336,9 +1300,15 @@ static void intel_put_event_constraints(struct cpu_hw_events *cpuc, intel_put_shared_regs_event_constraints(cpuc, event); } -static void intel_pebs_aliases_core2(struct perf_event *event) +static int intel_pmu_hw_config(struct perf_event *event) { - if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { + int ret = x86_pmu_hw_config(event); + + if (ret) + return ret; + + if (event->attr.precise_ip && + (event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { /* * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P * (0x003c) so that we can use it with PEBS. @@ -1359,48 +1329,10 @@ static void intel_pebs_aliases_core2(struct perf_event *event) */ u64 alt_config = X86_CONFIG(.event=0xc0, .inv=1, .cmask=16); - alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); - event->hw.config = alt_config; - } -} - -static void intel_pebs_aliases_snb(struct perf_event *event) -{ - if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { - /* - * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P - * (0x003c) so that we can use it with PEBS. - * - * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't - * PEBS capable. However we can use UOPS_RETIRED.ALL - * (0x01c2), which is a PEBS capable event, to get the same - * count. - * - * UOPS_RETIRED.ALL counts the number of cycles that retires - * CNTMASK micro-ops. By setting CNTMASK to a value (16) - * larger than the maximum number of micro-ops that can be - * retired per cycle (4) and then inverting the condition, we - * count all cycles that retire 16 or less micro-ops, which - * is every cycle. - * - * Thereby we gain a PEBS capable cycle counter. - */ - u64 alt_config = X86_CONFIG(.event=0xc2, .umask=0x01, .inv=1, .cmask=16); alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); event->hw.config = alt_config; } -} - -static int intel_pmu_hw_config(struct perf_event *event) -{ - int ret = x86_pmu_hw_config(event); - - if (ret) - return ret; - - if (event->attr.precise_ip && x86_pmu.pebs_aliases) - x86_pmu.pebs_aliases(event); if (intel_pmu_needs_lbr_smpl(event)) { ret = intel_pmu_setup_lbr_filter(event); @@ -1675,7 +1607,6 @@ static __initconst const struct x86_pmu intel_pmu = { .max_period = (1ULL << 31) - 1, .get_event_constraints = intel_get_event_constraints, .put_event_constraints = intel_put_event_constraints, - .pebs_aliases = intel_pebs_aliases_core2, .format_attrs = intel_arch3_formats_attr, @@ -1909,9 +1840,8 @@ __init int intel_pmu_init(void) break; case 42: /* SandyBridge */ - case 45: /* SandyBridge, "Romely-EP" */ x86_add_quirk(intel_sandybridge_quirk); - case 58: /* IvyBridge */ + case 45: /* SandyBridge, "Romely-EP" */ memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); @@ -1919,7 +1849,6 @@ __init int intel_pmu_init(void) x86_pmu.event_constraints = intel_snb_event_constraints; x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints; - x86_pmu.pebs_aliases = intel_pebs_aliases_snb; x86_pmu.extra_regs = intel_snb_extra_regs; /* all extra regs are per-cpu when HT is on */ x86_pmu.er_flags |= ERF_HAS_RSP_1; diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c index 35e2192df9f4..5a3edc27f6e5 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -400,7 +400,14 @@ struct event_constraint intel_snb_pebs_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ + INTEL_UEVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */ + INTEL_UEVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */ + INTEL_UEVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */ + INTEL_UEVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */ + INTEL_UEVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */ + INTEL_UEVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */ + INTEL_UEVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */ + INTEL_UEVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */ INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */ diff --git a/trunk/arch/x86/kernel/entry_32.S b/trunk/arch/x86/kernel/entry_32.S index 623f28837476..01ccf9b71473 100644 --- a/trunk/arch/x86/kernel/entry_32.S +++ b/trunk/arch/x86/kernel/entry_32.S @@ -316,6 +316,7 @@ ret_from_exception: preempt_stop(CLBR_ANY) ret_from_intr: GET_THREAD_INFO(%ebp) +resume_userspace_sig: #ifdef CONFIG_VM86 movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS movb PT_CS(%esp), %al @@ -614,13 +615,9 @@ work_notifysig: # deal with pending signals and # vm86-space TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) - movb PT_CS(%esp), %bl - andb $SEGMENT_RPL_MASK, %bl - cmpb $USER_RPL, %bl - jb resume_kernel xorl %edx, %edx call do_notify_resume - jmp resume_userspace + jmp resume_userspace_sig ALIGN work_notifysig_v86: @@ -633,13 +630,9 @@ work_notifysig_v86: #endif TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) - movb PT_CS(%esp), %bl - andb $SEGMENT_RPL_MASK, %bl - cmpb $USER_RPL, %bl - jb resume_kernel xorl %edx, %edx call do_notify_resume - jmp resume_userspace + jmp resume_userspace_sig END(work_pending) # perform syscall exit tracing diff --git a/trunk/arch/x86/kernel/entry_64.S b/trunk/arch/x86/kernel/entry_64.S index 7d65133b51be..320852d02026 100644 --- a/trunk/arch/x86/kernel/entry_64.S +++ b/trunk/arch/x86/kernel/entry_64.S @@ -190,44 +190,6 @@ ENDPROC(native_usergs_sysret64) #endif .endm -/* - * When dynamic function tracer is enabled it will add a breakpoint - * to all locations that it is about to modify, sync CPUs, update - * all the code, sync CPUs, then remove the breakpoints. In this time - * if lockdep is enabled, it might jump back into the debug handler - * outside the updating of the IST protection. (TRACE_IRQS_ON/OFF). - * - * We need to change the IDT table before calling TRACE_IRQS_ON/OFF to - * make sure the stack pointer does not get reset back to the top - * of the debug stack, and instead just reuses the current stack. - */ -#if defined(CONFIG_DYNAMIC_FTRACE) && defined(CONFIG_TRACE_IRQFLAGS) - -.macro TRACE_IRQS_OFF_DEBUG - call debug_stack_set_zero - TRACE_IRQS_OFF - call debug_stack_reset -.endm - -.macro TRACE_IRQS_ON_DEBUG - call debug_stack_set_zero - TRACE_IRQS_ON - call debug_stack_reset -.endm - -.macro TRACE_IRQS_IRETQ_DEBUG offset=ARGOFFSET - bt $9,EFLAGS-\offset(%rsp) /* interrupts off? */ - jnc 1f - TRACE_IRQS_ON_DEBUG -1: -.endm - -#else -# define TRACE_IRQS_OFF_DEBUG TRACE_IRQS_OFF -# define TRACE_IRQS_ON_DEBUG TRACE_IRQS_ON -# define TRACE_IRQS_IRETQ_DEBUG TRACE_IRQS_IRETQ -#endif - /* * C code is not supposed to know about undefined top of stack. Every time * a C function with an pt_regs argument is called from the SYSCALL based @@ -1136,7 +1098,7 @@ ENTRY(\sym) subq $ORIG_RAX-R15, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 call save_paranoid - TRACE_IRQS_OFF_DEBUG + TRACE_IRQS_OFF movq %rsp,%rdi /* pt_regs pointer */ xorl %esi,%esi /* no error code */ subq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist) @@ -1431,7 +1393,7 @@ paranoidzeroentry machine_check *machine_check_vector(%rip) ENTRY(paranoid_exit) DEFAULT_FRAME DISABLE_INTERRUPTS(CLBR_NONE) - TRACE_IRQS_OFF_DEBUG + TRACE_IRQS_OFF testl %ebx,%ebx /* swapgs needed? */ jnz paranoid_restore testl $3,CS(%rsp) @@ -1442,7 +1404,7 @@ paranoid_swapgs: RESTORE_ALL 8 jmp irq_return paranoid_restore: - TRACE_IRQS_IRETQ_DEBUG 0 + TRACE_IRQS_IRETQ 0 RESTORE_ALL 8 jmp irq_return paranoid_userspace: diff --git a/trunk/arch/x86/kernel/ftrace.c b/trunk/arch/x86/kernel/ftrace.c index c3a7cb4bf6e6..32ff36596ab1 100644 --- a/trunk/arch/x86/kernel/ftrace.c +++ b/trunk/arch/x86/kernel/ftrace.c @@ -100,7 +100,7 @@ static const unsigned char *ftrace_nop_replace(void) } static int -ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code, +ftrace_modify_code(unsigned long ip, unsigned const char *old_code, unsigned const char *new_code) { unsigned char replaced[MCOUNT_INSN_SIZE]; @@ -141,20 +141,7 @@ int ftrace_make_nop(struct module *mod, old = ftrace_call_replace(ip, addr); new = ftrace_nop_replace(); - /* - * On boot up, and when modules are loaded, the MCOUNT_ADDR - * is converted to a nop, and will never become MCOUNT_ADDR - * again. This code is either running before SMP (on boot up) - * or before the code will ever be executed (module load). - * We do not want to use the breakpoint version in this case, - * just modify the code directly. - */ - if (addr == MCOUNT_ADDR) - return ftrace_modify_code_direct(rec->ip, old, new); - - /* Normal cases use add_brk_on_nop */ - WARN_ONCE(1, "invalid use of ftrace_make_nop"); - return -EINVAL; + return ftrace_modify_code(rec->ip, old, new); } int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) @@ -165,47 +152,9 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) old = ftrace_nop_replace(); new = ftrace_call_replace(ip, addr); - /* Should only be called when module is loaded */ - return ftrace_modify_code_direct(rec->ip, old, new); + return ftrace_modify_code(rec->ip, old, new); } -/* - * The modifying_ftrace_code is used to tell the breakpoint - * handler to call ftrace_int3_handler(). If it fails to - * call this handler for a breakpoint added by ftrace, then - * the kernel may crash. - * - * As atomic_writes on x86 do not need a barrier, we do not - * need to add smp_mb()s for this to work. It is also considered - * that we can not read the modifying_ftrace_code before - * executing the breakpoint. That would be quite remarkable if - * it could do that. Here's the flow that is required: - * - * CPU-0 CPU-1 - * - * atomic_inc(mfc); - * write int3s - * // implicit (r)mb - * if (atomic_read(mfc)) - * call ftrace_int3_handler() - * - * Then when we are finished: - * - * atomic_dec(mfc); - * - * If we hit a breakpoint that was not set by ftrace, it does not - * matter if ftrace_int3_handler() is called or not. It will - * simply be ignored. But it is crucial that a ftrace nop/caller - * breakpoint is handled. No other user should ever place a - * breakpoint on an ftrace nop/caller location. It must only - * be done by this code. - */ -atomic_t modifying_ftrace_code __read_mostly; - -static int -ftrace_modify_code(unsigned long ip, unsigned const char *old_code, - unsigned const char *new_code); - int ftrace_update_ftrace_func(ftrace_func_t func) { unsigned long ip = (unsigned long)(&ftrace_call); @@ -214,17 +163,13 @@ int ftrace_update_ftrace_func(ftrace_func_t func) memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); new = ftrace_call_replace(ip, (unsigned long)func); - - /* See comment above by declaration of modifying_ftrace_code */ - atomic_inc(&modifying_ftrace_code); - ret = ftrace_modify_code(ip, old, new); - atomic_dec(&modifying_ftrace_code); - return ret; } +int modifying_ftrace_code __read_mostly; + /* * A breakpoint was added to the code address we are about to * modify, and this is the handle that will just skip over it. @@ -544,46 +489,13 @@ void ftrace_replace_code(int enable) } } -static int -ftrace_modify_code(unsigned long ip, unsigned const char *old_code, - unsigned const char *new_code) -{ - int ret; - - ret = add_break(ip, old_code); - if (ret) - goto out; - - run_sync(); - - ret = add_update_code(ip, new_code); - if (ret) - goto fail_update; - - run_sync(); - - ret = ftrace_write(ip, new_code, 1); - if (ret) { - ret = -EPERM; - goto out; - } - run_sync(); - out: - return ret; - - fail_update: - probe_kernel_write((void *)ip, &old_code[0], 1); - goto out; -} - void arch_ftrace_update_code(int command) { - /* See comment above by declaration of modifying_ftrace_code */ - atomic_inc(&modifying_ftrace_code); + modifying_ftrace_code++; ftrace_modify_all_code(command); - atomic_dec(&modifying_ftrace_code); + modifying_ftrace_code--; } int __init ftrace_dyn_arch_init(void *data) diff --git a/trunk/arch/x86/kernel/kvmclock.c b/trunk/arch/x86/kernel/kvmclock.c index f1b42b3a186c..086eb58c6e80 100644 --- a/trunk/arch/x86/kernel/kvmclock.c +++ b/trunk/arch/x86/kernel/kvmclock.c @@ -120,6 +120,11 @@ bool kvm_check_and_clear_guest_paused(void) bool ret = false; struct pvclock_vcpu_time_info *src; + /* + * per_cpu() is safe here because this function is only called from + * timer functions where preemption is already disabled. + */ + WARN_ON(!in_atomic()); src = &__get_cpu_var(hv_clock); if ((src->flags & PVCLOCK_GUEST_STOPPED) != 0) { __this_cpu_and(hv_clock.flags, ~PVCLOCK_GUEST_STOPPED); diff --git a/trunk/arch/x86/kernel/nmi.c b/trunk/arch/x86/kernel/nmi.c index a0b2f84457be..90875279ef3d 100644 --- a/trunk/arch/x86/kernel/nmi.c +++ b/trunk/arch/x86/kernel/nmi.c @@ -444,16 +444,14 @@ static inline void nmi_nesting_preprocess(struct pt_regs *regs) */ if (unlikely(is_debug_stack(regs->sp))) { debug_stack_set_zero(); - this_cpu_write(update_debug_stack, 1); + __get_cpu_var(update_debug_stack) = 1; } } static inline void nmi_nesting_postprocess(void) { - if (unlikely(this_cpu_read(update_debug_stack))) { + if (unlikely(__get_cpu_var(update_debug_stack))) debug_stack_reset(); - this_cpu_write(update_debug_stack, 0); - } } #endif diff --git a/trunk/arch/x86/kernel/nmi_selftest.c b/trunk/arch/x86/kernel/nmi_selftest.c index 149b8d9c6ad4..e31bf8d5c4d2 100644 --- a/trunk/arch/x86/kernel/nmi_selftest.c +++ b/trunk/arch/x86/kernel/nmi_selftest.c @@ -42,7 +42,7 @@ static int __init nmi_unk_cb(unsigned int val, struct pt_regs *regs) static void __init init_nmi_testsuite(void) { /* trap all the unknown NMIs we may generate */ - register_nmi_handler_initonly(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk"); + register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk"); } static void __init cleanup_nmi_testsuite(void) @@ -64,7 +64,7 @@ static void __init test_nmi_ipi(struct cpumask *mask) { unsigned long timeout; - if (register_nmi_handler_initonly(NMI_LOCAL, test_nmi_ipi_callback, + if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback, NMI_FLAG_FIRST, "nmi_selftest")) { nmi_fail = FAILURE; return; diff --git a/trunk/arch/x86/kernel/pci-dma.c b/trunk/arch/x86/kernel/pci-dma.c index c0f420f76cd3..62c9457ccd2f 100644 --- a/trunk/arch/x86/kernel/pci-dma.c +++ b/trunk/arch/x86/kernel/pci-dma.c @@ -100,7 +100,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, struct dma_attrs *attrs) { unsigned long dma_mask; - struct page *page; + struct page *page = NULL; unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; dma_addr_t addr; @@ -108,7 +108,6 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size, flag |= __GFP_ZERO; again: - page = NULL; if (!(flag & GFP_ATOMIC)) page = dma_alloc_from_contiguous(dev, count, get_order(size)); if (!page) diff --git a/trunk/arch/x86/kernel/ptrace.c b/trunk/arch/x86/kernel/ptrace.c index c4c6a5c2bf0f..13b1990c7c58 100644 --- a/trunk/arch/x86/kernel/ptrace.c +++ b/trunk/arch/x86/kernel/ptrace.c @@ -1211,6 +1211,12 @@ static long x32_arch_ptrace(struct task_struct *child, 0, sizeof(struct user_i387_struct), datap); + /* normal 64bit interface to access TLS data. + Works just like arch_prctl, except that the arguments + are reversed. */ + case PTRACE_ARCH_PRCTL: + return do_arch_prctl(child, data, addr); + default: return compat_ptrace_request(child, request, addr, data); } diff --git a/trunk/arch/x86/kernel/reboot.c b/trunk/arch/x86/kernel/reboot.c index 25b48edb847c..79c45af81604 100644 --- a/trunk/arch/x86/kernel/reboot.c +++ b/trunk/arch/x86/kernel/reboot.c @@ -639,11 +639,9 @@ void native_machine_shutdown(void) set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id)); /* - * O.K Now that I'm on the appropriate processor, stop all of the - * others. Also disable the local irq to not receive the per-cpu - * timer interrupt which may trigger scheduler's load balance. + * O.K Now that I'm on the appropriate processor, + * stop all of the others. */ - local_irq_disable(); stop_other_cpus(); #endif diff --git a/trunk/arch/x86/kernel/signal.c b/trunk/arch/x86/kernel/signal.c index 21af737053aa..965dfda0fd5e 100644 --- a/trunk/arch/x86/kernel/signal.c +++ b/trunk/arch/x86/kernel/signal.c @@ -555,6 +555,7 @@ unsigned long sys_sigreturn(struct pt_regs *regs) sizeof(frame->extramask)))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc, &ax)) @@ -580,6 +581,7 @@ long sys_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) @@ -645,28 +647,42 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct pt_regs *regs) { int usig = signr_convert(sig); - sigset_t *set = sigmask_to_save(); + sigset_t *set = ¤t->blocked; + int ret; + + if (current_thread_info()->status & TS_RESTORE_SIGMASK) + set = ¤t->saved_sigmask; /* Set up the stack frame */ if (is_ia32) { if (ka->sa.sa_flags & SA_SIGINFO) - return ia32_setup_rt_frame(usig, ka, info, set, regs); + ret = ia32_setup_rt_frame(usig, ka, info, set, regs); else - return ia32_setup_frame(usig, ka, set, regs); + ret = ia32_setup_frame(usig, ka, set, regs); #ifdef CONFIG_X86_X32_ABI } else if (is_x32) { - return x32_setup_rt_frame(usig, ka, info, + ret = x32_setup_rt_frame(usig, ka, info, (compat_sigset_t *)set, regs); #endif } else { - return __setup_rt_frame(sig, ka, info, set, regs); + ret = __setup_rt_frame(sig, ka, info, set, regs); + } + + if (ret) { + force_sigsegv(sig, current); + return -EFAULT; } + + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + return ret; } -static void +static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs) { + int ret; + /* Are we from a system call? */ if (syscall_get_nr(current, regs) >= 0) { /* If so, check system call restarting.. */ @@ -697,10 +713,10 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, likely(test_and_clear_thread_flag(TIF_FORCED_TF))) regs->flags &= ~X86_EFLAGS_TF; - if (setup_rt_frame(sig, ka, info, regs) < 0) { - force_sigsegv(sig, current); - return; - } + ret = setup_rt_frame(sig, ka, info, regs); + + if (ret) + return ret; /* * Clear the direction flag as per the ABI for function entry. @@ -715,8 +731,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, */ regs->flags &= ~X86_EFLAGS_TF; - signal_delivered(sig, info, ka, regs, - test_thread_flag(TIF_SINGLESTEP)); + block_sigmask(ka, sig); + + tracehook_signal_handler(sig, info, ka, regs, + test_thread_flag(TIF_SINGLESTEP)); + + return 0; } #ifdef CONFIG_X86_32 @@ -737,6 +757,16 @@ static void do_signal(struct pt_regs *regs) siginfo_t info; int signr; + /* + * We want the common case to go fast, which is why we may in certain + * cases get here from kernel mode. Just return without doing anything + * if so. + * X86_32: vm86 regs switched out by assembly code before reaching + * here, so testing against kernel CS suffices. + */ + if (!user_mode(regs)) + return; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ @@ -766,7 +796,10 @@ static void do_signal(struct pt_regs *regs) * If there's no signal to deliver, we just put the saved sigmask * back. */ - restore_saved_sigmask(); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; + set_current_blocked(¤t->saved_sigmask); + } } /* @@ -794,6 +827,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); } if (thread_info_flags & _TIF_USER_RETURN_NOTIFY) fire_user_return_notifiers(); @@ -901,6 +936,7 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) diff --git a/trunk/arch/x86/kernel/smpboot.c b/trunk/arch/x86/kernel/smpboot.c index 7bd8a0823654..f56f96da77f5 100644 --- a/trunk/arch/x86/kernel/smpboot.c +++ b/trunk/arch/x86/kernel/smpboot.c @@ -349,12 +349,9 @@ static bool __cpuinit match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) static bool __cpuinit match_mc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) { - if (c->phys_proc_id == o->phys_proc_id) { - if (cpu_has(c, X86_FEATURE_AMD_DCM)) - return true; - + if (c->phys_proc_id == o->phys_proc_id) return topology_sane(c, o, "mc"); - } + return false; } @@ -385,15 +382,6 @@ void __cpuinit set_cpu_sibling_map(int cpu) if ((i == cpu) || (has_mc && match_llc(c, o))) link_mask(llc_shared, cpu, i); - } - - /* - * This needs a separate iteration over the cpus because we rely on all - * cpu_sibling_mask links to be set-up. - */ - for_each_cpu(i, cpu_sibling_setup_mask) { - o = &cpu_data(i); - if ((i == cpu) || (has_mc && match_mc(c, o))) { link_mask(core, cpu, i); @@ -422,7 +410,15 @@ void __cpuinit set_cpu_sibling_map(int cpu) /* maps the cpu to the sched domain representing multi-core */ const struct cpumask *cpu_coregroup_mask(int cpu) { - return cpu_llc_shared_mask(cpu); + struct cpuinfo_x86 *c = &cpu_data(cpu); + /* + * For perf, we return last level cache shared map. + * And for power savings, we return cpu_core_map + */ + if (!(cpu_has(c, X86_FEATURE_AMD_DCM))) + return cpu_core_mask(cpu); + else + return cpu_llc_shared_mask(cpu); } static void impress_friends(void) diff --git a/trunk/arch/x86/kernel/traps.c b/trunk/arch/x86/kernel/traps.c index 05b31d92f69c..ff08457a025d 100644 --- a/trunk/arch/x86/kernel/traps.c +++ b/trunk/arch/x86/kernel/traps.c @@ -303,12 +303,8 @@ do_general_protection(struct pt_regs *regs, long error_code) dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_code) { #ifdef CONFIG_DYNAMIC_FTRACE - /* - * ftrace must be first, everything else may cause a recursive crash. - * See note by declaration of modifying_ftrace_code in ftrace.c - */ - if (unlikely(atomic_read(&modifying_ftrace_code)) && - ftrace_int3_handler(regs)) + /* ftrace must be first, everything else may cause a recursive crash */ + if (unlikely(modifying_ftrace_code) && ftrace_int3_handler(regs)) return; #endif #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP diff --git a/trunk/arch/x86/kvm/mmu.c b/trunk/arch/x86/kvm/mmu.c index be3cea4407ff..72102e0ab7cb 100644 --- a/trunk/arch/x86/kvm/mmu.c +++ b/trunk/arch/x86/kvm/mmu.c @@ -2595,7 +2595,8 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu, *gfnp = gfn; kvm_release_pfn_clean(pfn); pfn &= ~mask; - kvm_get_pfn(pfn); + if (!get_page_unless_zero(pfn_to_page(pfn))) + BUG(); *pfnp = pfn; } } diff --git a/trunk/arch/x86/lib/usercopy.c b/trunk/arch/x86/lib/usercopy.c index 4f74d94c8d97..f61ee67ec00f 100644 --- a/trunk/arch/x86/lib/usercopy.c +++ b/trunk/arch/x86/lib/usercopy.c @@ -8,7 +8,6 @@ #include #include -#include /* * best effort, GUP based copy_from_user() that is NMI-safe @@ -22,9 +21,6 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) void *map; int ret; - if (__range_not_ok(from, n, TASK_SIZE)) - return len; - do { ret = __get_user_pages_fast(addr, 1, 0, &page); if (!ret) diff --git a/trunk/arch/x86/lib/x86-opcode-map.txt b/trunk/arch/x86/lib/x86-opcode-map.txt index 5d7e51f3fd28..819137904428 100644 --- a/trunk/arch/x86/lib/x86-opcode-map.txt +++ b/trunk/arch/x86/lib/x86-opcode-map.txt @@ -28,7 +28,7 @@ # - (66): the last prefix is 0x66 # - (F3): the last prefix is 0xF3 # - (F2): the last prefix is 0xF2 -# - (!F3) : the last prefix is not 0xF3 (including non-last prefix case) +# Table: one byte opcode Referrer: @@ -515,12 +515,12 @@ b4: LFS Gv,Mp b5: LGS Gv,Mp b6: MOVZX Gv,Eb b7: MOVZX Gv,Ew -b8: JMPE (!F3) | POPCNT Gv,Ev (F3) +b8: JMPE | POPCNT Gv,Ev (F3) b9: Grp10 (1A) ba: Grp8 Ev,Ib (1A) bb: BTC Ev,Gv -bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3) -bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3) +bc: BSF Gv,Ev | TZCNT Gv,Ev (F3) +bd: BSR Gv,Ev | LZCNT Gv,Ev (F3) be: MOVSX Gv,Eb bf: MOVSX Gv,Ew # 0x0f 0xc0-0xcf diff --git a/trunk/arch/x86/mm/init.c b/trunk/arch/x86/mm/init.c index bc4e9d84157f..97141c26a13a 100644 --- a/trunk/arch/x86/mm/init.c +++ b/trunk/arch/x86/mm/init.c @@ -62,8 +62,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en extra += PMD_SIZE; #endif /* The first 2/4M doesn't use large pages. */ - if (mr->start < PMD_SIZE) - extra += mr->end - mr->start; + extra += mr->end - mr->start; ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; } else diff --git a/trunk/arch/x86/mm/ioremap.c b/trunk/arch/x86/mm/ioremap.c index 78fe3f1ac49f..be1ef574ce9a 100644 --- a/trunk/arch/x86/mm/ioremap.c +++ b/trunk/arch/x86/mm/ioremap.c @@ -180,7 +180,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, /** * ioremap_nocache - map bus memory into CPU space - * @phys_addr: bus address of the memory + * @offset: bus address of the memory * @size: size of the resource to map * * ioremap_nocache performs a platform specific sequence of operations to @@ -217,7 +217,7 @@ EXPORT_SYMBOL(ioremap_nocache); /** * ioremap_wc - map memory into CPU space write combined - * @phys_addr: bus address of the memory + * @offset: bus address of the memory * @size: size of the resource to map * * This version of ioremap ensures that the memory is marked write combining. diff --git a/trunk/arch/x86/mm/pageattr.c b/trunk/arch/x86/mm/pageattr.c index a718e0d23503..e1ebde315210 100644 --- a/trunk/arch/x86/mm/pageattr.c +++ b/trunk/arch/x86/mm/pageattr.c @@ -122,7 +122,7 @@ within(unsigned long addr, unsigned long start, unsigned long end) /** * clflush_cache_range - flush a cache range with clflush - * @vaddr: virtual start address + * @addr: virtual start address * @size: number of bytes to flush * * clflush is an unordered instruction which needs fencing with mfence diff --git a/trunk/arch/x86/mm/srat.c b/trunk/arch/x86/mm/srat.c index 4599c3e8bcb6..732af3a96183 100644 --- a/trunk/arch/x86/mm/srat.c +++ b/trunk/arch/x86/mm/srat.c @@ -176,8 +176,6 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) return; } - node_set(node, numa_nodes_parsed); - printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n", node, pxm, (unsigned long long) start, (unsigned long long) end - 1); diff --git a/trunk/arch/x86/platform/mrst/mrst.c b/trunk/arch/x86/platform/mrst/mrst.c index fd41a9262d65..e31bcd8f2eee 100644 --- a/trunk/arch/x86/platform/mrst/mrst.c +++ b/trunk/arch/x86/platform/mrst/mrst.c @@ -782,7 +782,7 @@ BLOCKING_NOTIFIER_HEAD(intel_scu_notifier); EXPORT_SYMBOL_GPL(intel_scu_notifier); /* Called by IPC driver */ -void __devinit intel_scu_devices_create(void) +void intel_scu_devices_create(void) { int i; diff --git a/trunk/arch/x86/platform/uv/tlb_uv.c b/trunk/arch/x86/platform/uv/tlb_uv.c index 59880afa851f..3ae0e61abd23 100644 --- a/trunk/arch/x86/platform/uv/tlb_uv.c +++ b/trunk/arch/x86/platform/uv/tlb_uv.c @@ -1295,6 +1295,7 @@ static void __init enable_timeouts(void) */ mmr_image |= (1L << SOFTACK_MSHIFT); if (is_uv2_hub()) { + mmr_image &= ~(1L << UV2_LEG_SHFT); mmr_image |= (1L << UV2_EXT_SHFT); } write_mmr_misc_control(pnode, mmr_image); diff --git a/trunk/arch/x86/syscalls/syscall_32.tbl b/trunk/arch/x86/syscalls/syscall_32.tbl index 7a35a6e71d44..29f9f0554f7d 100644 --- a/trunk/arch/x86/syscalls/syscall_32.tbl +++ b/trunk/arch/x86/syscalls/syscall_32.tbl @@ -355,4 +355,3 @@ 346 i386 setns sys_setns 347 i386 process_vm_readv sys_process_vm_readv compat_sys_process_vm_readv 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev -349 i386 kcmp sys_kcmp diff --git a/trunk/arch/x86/syscalls/syscall_64.tbl b/trunk/arch/x86/syscalls/syscall_64.tbl index 51171aeff0dc..dd29a9ea27c5 100644 --- a/trunk/arch/x86/syscalls/syscall_64.tbl +++ b/trunk/arch/x86/syscalls/syscall_64.tbl @@ -318,8 +318,6 @@ 309 common getcpu sys_getcpu 310 64 process_vm_readv sys_process_vm_readv 311 64 process_vm_writev sys_process_vm_writev -312 64 kcmp sys_kcmp - # # x32-specific system call numbers start at 512 to avoid cache impact # for native 64-bit operation. diff --git a/trunk/arch/x86/tools/gen-insn-attr-x86.awk b/trunk/arch/x86/tools/gen-insn-attr-x86.awk index ddcf39b1a18d..5f6a5b6c3a15 100644 --- a/trunk/arch/x86/tools/gen-insn-attr-x86.awk +++ b/trunk/arch/x86/tools/gen-insn-attr-x86.awk @@ -66,10 +66,9 @@ BEGIN { rex_expr = "^REX(\\.[XRWB]+)*" fpu_expr = "^ESC" # TODO - lprefix1_expr = "\\((66|!F3)\\)" + lprefix1_expr = "\\(66\\)" lprefix2_expr = "\\(F3\\)" - lprefix3_expr = "\\((F2|!F3)\\)" - lprefix_expr = "\\((66|F2|F3)\\)" + lprefix3_expr = "\\(F2\\)" max_lprefix = 4 # All opcodes starting with lower-case 'v' or with (v1) superscript @@ -334,16 +333,13 @@ function convert_operands(count,opnd, i,j,imm,mod) if (match(ext, lprefix1_expr)) { lptable1[idx] = add_flags(lptable1[idx],flags) variant = "INAT_VARIANT" - } - if (match(ext, lprefix2_expr)) { + } else if (match(ext, lprefix2_expr)) { lptable2[idx] = add_flags(lptable2[idx],flags) variant = "INAT_VARIANT" - } - if (match(ext, lprefix3_expr)) { + } else if (match(ext, lprefix3_expr)) { lptable3[idx] = add_flags(lptable3[idx],flags) variant = "INAT_VARIANT" - } - if (!match(ext, lprefix_expr)){ + } else { table[idx] = add_flags(table[idx],flags) } } diff --git a/trunk/arch/x86/um/signal.c b/trunk/arch/x86/um/signal.c index a508cea13503..bb0fb03b9f85 100644 --- a/trunk/arch/x86/um/signal.c +++ b/trunk/arch/x86/um/signal.c @@ -486,6 +486,7 @@ long sys_sigreturn(struct pt_regs *regs) copy_from_user(&set.sig[1], extramask, sig_size)) goto segfault; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (copy_sc_from_user(¤t->thread.regs, sc)) @@ -599,6 +600,7 @@ long sys_rt_sigreturn(struct pt_regs *regs) if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) goto segfault; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) diff --git a/trunk/arch/x86/um/sys_call_table_32.c b/trunk/arch/x86/um/sys_call_table_32.c index 68d1dc91b37b..416bd40c0eba 100644 --- a/trunk/arch/x86/um/sys_call_table_32.c +++ b/trunk/arch/x86/um/sys_call_table_32.c @@ -39,9 +39,9 @@ #undef __SYSCALL_I386 #define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym, -typedef asmlinkage void (*sys_call_ptr_t)(void); +typedef void (*sys_call_ptr_t)(void); -extern asmlinkage void sys_ni_syscall(void); +extern void sys_ni_syscall(void); const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { /* diff --git a/trunk/arch/x86/xen/enlighten.c b/trunk/arch/x86/xen/enlighten.c index ff962d4b821e..e74df9548a02 100644 --- a/trunk/arch/x86/xen/enlighten.c +++ b/trunk/arch/x86/xen/enlighten.c @@ -209,9 +209,6 @@ static void __init xen_banner(void) xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); } -#define CPUID_THERM_POWER_LEAF 6 -#define APERFMPERF_PRESENT 0 - static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; @@ -245,11 +242,6 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, *dx = cpuid_leaf5_edx_val; return; - case CPUID_THERM_POWER_LEAF: - /* Disabling APERFMPERF for kernel usage */ - maskecx = ~(1 << APERFMPERF_PRESENT); - break; - case 0xb: /* Suppress extended topology stuff */ maskebx = 0; diff --git a/trunk/arch/x86/xen/p2m.c b/trunk/arch/x86/xen/p2m.c index 64effdc6da94..ffd08c414e91 100644 --- a/trunk/arch/x86/xen/p2m.c +++ b/trunk/arch/x86/xen/p2m.c @@ -706,7 +706,6 @@ int m2p_add_override(unsigned long mfn, struct page *page, unsigned long uninitialized_var(address); unsigned level; pte_t *ptep = NULL; - int ret = 0; pfn = page_to_pfn(page); if (!PageHighMem(page)) { @@ -742,24 +741,6 @@ int m2p_add_override(unsigned long mfn, struct page *page, list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); spin_unlock_irqrestore(&m2p_override_lock, flags); - /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in - * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other - * pfn so that the following mfn_to_pfn(mfn) calls will return the - * pfn from the m2p_override (the backend pfn) instead. - * We need to do this because the pages shared by the frontend - * (xen-blkfront) can be already locked (lock_page, called by - * do_read_cache_page); when the userspace backend tries to use them - * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so - * do_blockdev_direct_IO is going to try to lock the same pages - * again resulting in a deadlock. - * As a side effect get_user_pages_fast might not be safe on the - * frontend pages while they are being shared with the backend, - * because mfn_to_pfn (that ends up being called by GUPF) will - * return the backend pfn rather than the frontend pfn. */ - ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); - if (ret == 0 && get_phys_to_machine(pfn) == mfn) - set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); - return 0; } EXPORT_SYMBOL_GPL(m2p_add_override); @@ -771,7 +752,6 @@ int m2p_remove_override(struct page *page, bool clear_pte) unsigned long uninitialized_var(address); unsigned level; pte_t *ptep = NULL; - int ret = 0; pfn = page_to_pfn(page); mfn = get_phys_to_machine(pfn); @@ -841,22 +821,6 @@ int m2p_remove_override(struct page *page, bool clear_pte) } else set_phys_to_machine(pfn, page->index); - /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present - * somewhere in this domain, even before being added to the - * m2p_override (see comment above in m2p_add_override). - * If there are no other entries in the m2p_override corresponding - * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for - * the original pfn (the one shared by the frontend): the backend - * cannot do any IO on this page anymore because it has been - * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of - * the original pfn causes mfn_to_pfn(mfn) to return the frontend - * pfn again. */ - mfn &= ~FOREIGN_FRAME_BIT; - ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); - if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && - m2p_find_override(mfn) == NULL) - set_phys_to_machine(pfn, mfn); - return 0; } EXPORT_SYMBOL_GPL(m2p_remove_override); diff --git a/trunk/arch/x86/xen/setup.c b/trunk/arch/x86/xen/setup.c index a4790bf22c59..3ebba0753d38 100644 --- a/trunk/arch/x86/xen/setup.c +++ b/trunk/arch/x86/xen/setup.c @@ -371,8 +371,7 @@ char * __init xen_memory_setup(void) populated = xen_populate_chunk(map, memmap.nr_entries, max_pfn, &last_pfn, xen_released_pages); - xen_released_pages -= populated; - extra_pages += xen_released_pages; + extra_pages += (xen_released_pages - populated); if (last_pfn > max_pfn) { max_pfn = min(MAX_DOMAIN_PAGES, last_pfn); diff --git a/trunk/arch/xtensa/include/asm/syscall.h b/trunk/arch/xtensa/include/asm/syscall.h index c1dacca312f3..0b9f2e13c781 100644 --- a/trunk/arch/xtensa/include/asm/syscall.h +++ b/trunk/arch/xtensa/include/asm/syscall.h @@ -31,5 +31,5 @@ asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, struct timespec __user *tsp, const sigset_t __user *sigmask, size_t sigsetsize); -asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, - size_t sigsetsize); + + diff --git a/trunk/arch/xtensa/kernel/signal.c b/trunk/arch/xtensa/kernel/signal.c index efe4e854b3cd..c5e4ec0598d2 100644 --- a/trunk/arch/xtensa/kernel/signal.c +++ b/trunk/arch/xtensa/kernel/signal.c @@ -30,6 +30,8 @@ #define DEBUG_SIG 0 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + extern struct task_struct *coproc_owners[]; struct rt_sigframe @@ -259,6 +261,7 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3, if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); if (restore_sigcontext(regs, frame)) @@ -449,6 +452,15 @@ static void do_signal(struct pt_regs *regs) siginfo_t info; int signr; struct k_sigaction ka; + sigset_t oldset; + + if (try_to_freeze()) + goto no_signal; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; task_pt_regs(current)->icountlevel = 0; @@ -489,17 +501,19 @@ static void do_signal(struct pt_regs *regs) /* Whee! Actually deliver the signal. */ /* Set up the stack frame */ - ret = setup_frame(signr, &ka, &info, sigmask_to_save(), regs); + ret = setup_frame(signr, &ka, &info, oldset, regs); if (ret) return; - signal_delivered(signr, &info, &ka, regs, 0); + clear_thread_flag(TIF_RESTORE_SIGMASK); + block_sigmask(&ka, signr); if (current->ptrace & PT_SINGLESTEP) task_pt_regs(current)->icountlevel = 1; return; } +no_signal: /* Did we come from a system call? */ if ((signed) regs->syscall >= 0) { /* Restart the system call - no handlers present */ @@ -518,7 +532,8 @@ static void do_signal(struct pt_regs *regs) } /* If there's no signal to deliver, we just restore the saved mask. */ - restore_saved_sigmask(); + if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) + set_current_blocked(¤t->saved_sigmask); if (current->ptrace & PT_SINGLESTEP) task_pt_regs(current)->icountlevel = 1; @@ -533,6 +548,9 @@ void do_notify_resume(struct pt_regs *regs) if (test_thread_flag(TIF_SIGPENDING)) do_signal(regs); - if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) + if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); + } } diff --git a/trunk/block/blk-ioc.c b/trunk/block/blk-ioc.c index 893b8007c657..1e2d53b04858 100644 --- a/trunk/block/blk-ioc.c +++ b/trunk/block/blk-ioc.c @@ -235,7 +235,6 @@ void ioc_clear_queue(struct request_queue *q) int create_task_io_context(struct task_struct *task, gfp_t gfp_flags, int node) { struct io_context *ioc; - int ret; ioc = kmem_cache_alloc_node(iocontext_cachep, gfp_flags | __GFP_ZERO, node); @@ -263,12 +262,9 @@ int create_task_io_context(struct task_struct *task, gfp_t gfp_flags, int node) task->io_context = ioc; else kmem_cache_free(iocontext_cachep, ioc); - - ret = task->io_context ? 0 : -EBUSY; - task_unlock(task); - return ret; + return 0; } /** diff --git a/trunk/drivers/acpi/Kconfig b/trunk/drivers/acpi/Kconfig index 80998958cf45..47768ff87343 100644 --- a/trunk/drivers/acpi/Kconfig +++ b/trunk/drivers/acpi/Kconfig @@ -208,7 +208,7 @@ config ACPI_IPMI config ACPI_HOTPLUG_CPU bool - depends on EXPERIMENTAL && ACPI_PROCESSOR && HOTPLUG_CPU + depends on ACPI_PROCESSOR && HOTPLUG_CPU select ACPI_CONTAINER default y diff --git a/trunk/drivers/acpi/battery.c b/trunk/drivers/acpi/battery.c index 7dd3f9fb9f3f..86933ca8b472 100644 --- a/trunk/drivers/acpi/battery.c +++ b/trunk/drivers/acpi/battery.c @@ -643,19 +643,11 @@ static int acpi_battery_update(struct acpi_battery *battery) static void acpi_battery_refresh(struct acpi_battery *battery) { - int power_unit; - if (!battery->bat.dev) return; - power_unit = battery->power_unit; - acpi_battery_get_info(battery); - - if (power_unit == battery->power_unit) - return; - - /* The battery has changed its reporting units. */ + /* The battery may have changed its reporting units. */ sysfs_remove_battery(battery); sysfs_add_battery(battery); } diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index adceafda9c17..3188da3df8da 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -182,66 +182,41 @@ EXPORT_SYMBOL(acpi_bus_get_private_data); Power Management -------------------------------------------------------------------------- */ -static const char *state_string(int state) -{ - switch (state) { - case ACPI_STATE_D0: - return "D0"; - case ACPI_STATE_D1: - return "D1"; - case ACPI_STATE_D2: - return "D2"; - case ACPI_STATE_D3_HOT: - return "D3hot"; - case ACPI_STATE_D3_COLD: - return "D3"; - default: - return "(unknown)"; - } -} - static int __acpi_bus_get_power(struct acpi_device *device, int *state) { - int result = ACPI_STATE_UNKNOWN; + int result = 0; + acpi_status status = 0; + unsigned long long psc = 0; if (!device || !state) return -EINVAL; - if (!device->flags.power_manageable) { + *state = ACPI_STATE_UNKNOWN; + + if (device->flags.power_manageable) { + /* + * Get the device's power state either directly (via _PSC) or + * indirectly (via power resources). + */ + if (device->power.flags.power_resources) { + result = acpi_power_get_inferred_state(device, state); + if (result) + return result; + } else if (device->power.flags.explicit_get) { + status = acpi_evaluate_integer(device->handle, "_PSC", + NULL, &psc); + if (ACPI_FAILURE(status)) + return -ENODEV; + *state = (int)psc; + } + } else { /* TBD: Non-recursive algorithm for walking up hierarchy. */ *state = device->parent ? device->parent->power.state : ACPI_STATE_D0; - goto out; - } - - /* - * Get the device's power state either directly (via _PSC) or - * indirectly (via power resources). - */ - if (device->power.flags.explicit_get) { - unsigned long long psc; - acpi_status status = acpi_evaluate_integer(device->handle, - "_PSC", NULL, &psc); - if (ACPI_FAILURE(status)) - return -ENODEV; - - result = psc; - } - /* The test below covers ACPI_STATE_UNKNOWN too. */ - if (result <= ACPI_STATE_D2) { - ; /* Do nothing. */ - } else if (device->power.flags.power_resources) { - int error = acpi_power_get_inferred_state(device, &result); - if (error) - return error; - } else if (result == ACPI_STATE_D3_HOT) { - result = ACPI_STATE_D3; } - *state = result; - out: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", - device->pnp.bus_id, state_string(*state))); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", + device->pnp.bus_id, *state)); return 0; } @@ -259,14 +234,13 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) /* Make sure this is a valid target state */ if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n", - state_string(state))); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", + state)); return 0; } if (!device->power.states[state].flags.valid) { - printk(KERN_WARNING PREFIX "Device does not support %s\n", - state_string(state)); + printk(KERN_WARNING PREFIX "Device does not support D%d\n", state); return -ENODEV; } if (device->parent && (state < device->parent->power.state)) { @@ -320,13 +294,13 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) end: if (result) printk(KERN_WARNING PREFIX - "Device [%s] failed to transition to %s\n", - device->pnp.bus_id, state_string(state)); + "Device [%s] failed to transition to D%d\n", + device->pnp.bus_id, state); else { device->power.state = state; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device [%s] transitioned to %s\n", - device->pnp.bus_id, state_string(state))); + "Device [%s] transitioned to D%d\n", + device->pnp.bus_id, state)); } return result; diff --git a/trunk/drivers/acpi/power.c b/trunk/drivers/acpi/power.c index dd6d6a3c6780..0500f719f63e 100644 --- a/trunk/drivers/acpi/power.c +++ b/trunk/drivers/acpi/power.c @@ -631,7 +631,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state) * We know a device's inferred power state when all the resources * required for a given D-state are 'on'. */ - for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { + for (i = ACPI_STATE_D0; i < ACPI_STATE_D3_HOT; i++) { list = &device->power.states[i].resources; if (list->count < 1) continue; diff --git a/trunk/drivers/acpi/processor_perflib.c b/trunk/drivers/acpi/processor_perflib.c index a093dc163a42..0af48a8554cd 100644 --- a/trunk/drivers/acpi/processor_perflib.c +++ b/trunk/drivers/acpi/processor_perflib.c @@ -333,7 +333,6 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) struct acpi_buffer state = { 0, NULL }; union acpi_object *pss = NULL; int i; - int last_invalid = -1; status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); @@ -395,33 +394,14 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) ((u32)(px->core_frequency * 1000) != (px->core_frequency * 1000))) { printk(KERN_ERR FW_BUG PREFIX - "Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n", - pr->id, px->core_frequency); - if (last_invalid == -1) - last_invalid = i; - } else { - if (last_invalid != -1) { - /* - * Copy this valid entry over last_invalid entry - */ - memcpy(&(pr->performance->states[last_invalid]), - px, sizeof(struct acpi_processor_px)); - ++last_invalid; - } + "Invalid BIOS _PSS frequency: 0x%llx MHz\n", + px->core_frequency); + result = -EFAULT; + kfree(pr->performance->states); + goto end; } } - if (last_invalid == 0) { - printk(KERN_ERR FW_BUG PREFIX - "No valid BIOS _PSS frequency found for processor %d\n", pr->id); - result = -EFAULT; - kfree(pr->performance->states); - pr->performance->states = NULL; - } - - if (last_invalid > 0) - pr->performance->state_count = last_invalid; - end: kfree(buffer.pointer); diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index c8a1f3b68110..85cbfdccc97c 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -1567,7 +1567,6 @@ static int acpi_bus_scan_fixed(void) ACPI_BUS_TYPE_POWER_BUTTON, ACPI_STA_DEFAULT, &ops); - device_init_wakeup(&device->dev, true); } if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { diff --git a/trunk/drivers/acpi/sleep.c b/trunk/drivers/acpi/sleep.c index 88561029cca8..74ee4ab577b6 100644 --- a/trunk/drivers/acpi/sleep.c +++ b/trunk/drivers/acpi/sleep.c @@ -57,7 +57,6 @@ MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); static u8 sleep_states[ACPI_S_STATE_COUNT]; -static bool pwr_btn_event_pending; static void acpi_sleep_tts_switch(u32 acpi_state) { @@ -185,14 +184,6 @@ static int acpi_pm_prepare(void) return error; } -static int find_powerf_dev(struct device *dev, void *data) -{ - struct acpi_device *device = to_acpi_device(dev); - const char *hid = acpi_device_hid(device); - - return !strcmp(hid, ACPI_BUTTON_HID_POWERF); -} - /** * acpi_pm_finish - Instruct the platform to leave a sleep state. * @@ -201,7 +192,6 @@ static int find_powerf_dev(struct device *dev, void *data) */ static void acpi_pm_finish(void) { - struct device *pwr_btn_dev; u32 acpi_state = acpi_target_sleep_state; acpi_ec_unblock_transactions(); @@ -219,23 +209,6 @@ static void acpi_pm_finish(void) acpi_set_firmware_waking_vector((acpi_physical_address) 0); acpi_target_sleep_state = ACPI_STATE_S0; - - /* If we were woken with the fixed power button, provide a small - * hint to userspace in the form of a wakeup event on the fixed power - * button device (if it can be found). - * - * We delay the event generation til now, as the PM layer requires - * timekeeping to be running before we generate events. */ - if (!pwr_btn_event_pending) - return; - - pwr_btn_event_pending = false; - pwr_btn_dev = bus_find_device(&acpi_bus_type, NULL, NULL, - find_powerf_dev); - if (pwr_btn_dev) { - pm_wakeup_event(pwr_btn_dev, 0); - put_device(pwr_btn_dev); - } } /** @@ -325,23 +298,9 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* ACPI 3.0 specs (P62) says that it's the responsibility * of the OSPM to clear the status bit [ implying that the * POWER_BUTTON event should not reach userspace ] - * - * However, we do generate a small hint for userspace in the form of - * a wakeup event. We flag this condition for now and generate the - * event later, as we're currently too early in resume to be able to - * generate wakeup events. */ - if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) { - acpi_event_status pwr_btn_status; - - acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status); - - if (pwr_btn_status & ACPI_EVENT_FLAG_SET) { - acpi_clear_event(ACPI_EVENT_POWER_BUTTON); - /* Flag for later */ - pwr_btn_event_pending = true; - } - } + if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) + acpi_clear_event(ACPI_EVENT_POWER_BUTTON); /* * Disable and clear GPE status before interrupt is enabled. Some GPEs @@ -771,8 +730,8 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) * can wake the system. _S0W may be valid, too. */ if (acpi_target_sleep_state == ACPI_STATE_S0 || - (device_may_wakeup(dev) && adev->wakeup.flags.valid && - adev->wakeup.sleep_state >= acpi_target_sleep_state)) { + (device_may_wakeup(dev) && + adev->wakeup.sleep_state <= acpi_target_sleep_state)) { acpi_status status; acpi_method[3] = 'W'; diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index a576575617d7..9577b6fa2650 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -1687,6 +1687,10 @@ static int acpi_video_bus_add(struct acpi_device *device) set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); set_bit(KEY_DISPLAY_OFF, input->keybit); + error = input_register_device(input); + if (error) + goto err_stop_video; + printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), video->flags.multihead ? "yes" : "no", @@ -1697,16 +1701,12 @@ static int acpi_video_bus_add(struct acpi_device *device) video->pm_nb.priority = 0; error = register_pm_notifier(&video->pm_nb); if (error) - goto err_stop_video; - - error = input_register_device(input); - if (error) - goto err_unregister_pm_notifier; + goto err_unregister_input_dev; return 0; - err_unregister_pm_notifier: - unregister_pm_notifier(&video->pm_nb); + err_unregister_input_dev: + input_unregister_device(input); err_stop_video: acpi_video_bus_stop_devices(video); err_free_input_dev: @@ -1743,18 +1743,9 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) return 0; } -static int __init is_i740(struct pci_dev *dev) -{ - if (dev->device == 0x00D1) - return 1; - if (dev->device == 0x7000) - return 1; - return 0; -} - static int __init intel_opregion_present(void) { - int opregion = 0; +#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) struct pci_dev *dev = NULL; u32 address; @@ -1763,15 +1754,13 @@ static int __init intel_opregion_present(void) continue; if (dev->vendor != PCI_VENDOR_ID_INTEL) continue; - /* We don't want to poke around undefined i740 registers */ - if (is_i740(dev)) - continue; pci_read_config_dword(dev, 0xfc, &address); if (!address) continue; - opregion = 1; + return 1; } - return opregion; +#endif + return 0; } int acpi_video_register(void) diff --git a/trunk/drivers/base/regmap/regmap.c b/trunk/drivers/base/regmap/regmap.c index c89aa01fb1de..0bcda488f11c 100644 --- a/trunk/drivers/base/regmap/regmap.c +++ b/trunk/drivers/base/regmap/regmap.c @@ -246,11 +246,11 @@ struct regmap *regmap_init(struct device *dev, map->lock = regmap_lock_mutex; map->unlock = regmap_unlock_mutex; } + map->format.buf_size = (config->reg_bits + config->val_bits) / 8; map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); map->format.pad_bytes = config->pad_bits / 8; map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); - map->format.buf_size = DIV_ROUND_UP(config->reg_bits + - config->val_bits + config->pad_bits, 8); + map->format.buf_size += map->format.pad_bytes; map->reg_shift = config->pad_bits % 8; if (config->reg_stride) map->reg_stride = config->reg_stride; @@ -368,7 +368,7 @@ struct regmap *regmap_init(struct device *dev, ret = regcache_init(map, config); if (ret < 0) - goto err_debugfs; + goto err_free_workbuf; /* Add a devres resource for dev_get_regmap() */ m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL); @@ -383,8 +383,7 @@ struct regmap *regmap_init(struct device *dev, err_cache: regcache_exit(map); -err_debugfs: - regmap_debugfs_exit(map); +err_free_workbuf: kfree(map->work_buf); err_map: kfree(map); @@ -472,7 +471,6 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) return ret; } -EXPORT_SYMBOL_GPL(regmap_reinit_cache); /** * regmap_exit(): Free a previously allocated register map diff --git a/trunk/drivers/base/soc.c b/trunk/drivers/base/soc.c index 72b5e7280d14..ba29b2e73d48 100644 --- a/trunk/drivers/base/soc.c +++ b/trunk/drivers/base/soc.c @@ -42,7 +42,7 @@ struct device *soc_device_to_device(struct soc_device *soc_dev) return &soc_dev->dev; } -static umode_t soc_attribute_mode(struct kobject *kobj, +static mode_t soc_attribute_mode(struct kobject *kobj, struct attribute *attr, int index) { diff --git a/trunk/drivers/bcma/driver_chipcommon_pmu.c b/trunk/drivers/bcma/driver_chipcommon_pmu.c index 61ce4054b3c3..a058842f14fd 100644 --- a/trunk/drivers/bcma/driver_chipcommon_pmu.c +++ b/trunk/drivers/bcma/driver_chipcommon_pmu.c @@ -139,9 +139,7 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); break; case 0x4331: - case 43431: - /* Ext PA lines must be enabled for tx on BCM4331 */ - bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); + /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ break; case 43224: if (bus->chipinfo.rev == 0) { diff --git a/trunk/drivers/bcma/driver_pci.c b/trunk/drivers/bcma/driver_pci.c index c32ebd537abe..9a96f14c8f47 100644 --- a/trunk/drivers/bcma/driver_pci.c +++ b/trunk/drivers/bcma/driver_pci.c @@ -232,19 +232,17 @@ void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, bool enable) { - struct pci_dev *pdev; + struct pci_dev *pdev = pc->core->bus->host_pci; u32 coremask, tmp; int err = 0; - if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) { + if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) { /* This bcma device is not on a PCI host-bus. So the IRQs are * not routed through the PCI core. * So we must not enable routing through the PCI core. */ goto out; } - pdev = pc->core->bus->host_pci; - err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); if (err) goto out; diff --git a/trunk/drivers/bcma/sprom.c b/trunk/drivers/bcma/sprom.c index f16f42d36071..c7f93359acb0 100644 --- a/trunk/drivers/bcma/sprom.c +++ b/trunk/drivers/bcma/sprom.c @@ -579,13 +579,13 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; - if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) + if (bus->chipinfo.id == 0x4331) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); pr_debug("SPROM offset 0x%x\n", offset); bcma_sprom_read(bus, offset, sprom); - if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) + if (bus->chipinfo.id == 0x4331) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); err = bcma_sprom_valid(sprom); diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.c b/trunk/drivers/block/mtip32xx/mtip32xx.c index 264bc77dcb91..304000c3d433 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.c +++ b/trunk/drivers/block/mtip32xx/mtip32xx.c @@ -294,16 +294,18 @@ static int hba_reset_nosleep(struct driver_data *dd) */ static inline void mtip_issue_ncq_command(struct mtip_port *port, int tag) { + unsigned long flags = 0; + atomic_set(&port->commands[tag].active, 1); - spin_lock(&port->cmd_issue_lock); + spin_lock_irqsave(&port->cmd_issue_lock, flags); writel((1 << MTIP_TAG_BIT(tag)), port->s_active[MTIP_TAG_INDEX(tag)]); writel((1 << MTIP_TAG_BIT(tag)), port->cmd_issue[MTIP_TAG_INDEX(tag)]); - spin_unlock(&port->cmd_issue_lock); + spin_unlock_irqrestore(&port->cmd_issue_lock, flags); /* Set the command's timeout value.*/ port->commands[tag].comp_time = jiffies + msecs_to_jiffies( @@ -434,7 +436,8 @@ static void mtip_init_port(struct mtip_port *port) writel(0xFFFFFFFF, port->completed[i]); /* Clear any pending interrupts for this port */ - writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT); + writel(readl(port->dd->mmio + PORT_IRQ_STAT), + port->dd->mmio + PORT_IRQ_STAT); /* Clear any pending interrupts on the HBA. */ writel(readl(port->dd->mmio + HOST_IRQ_STAT), @@ -779,24 +782,13 @@ static void mtip_handle_tfe(struct driver_data *dd) /* Stop the timer to prevent command timeouts. */ del_timer(&port->cmd_timer); - set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); - - if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags) && - test_bit(MTIP_TAG_INTERNAL, port->allocated)) { - cmd = &port->commands[MTIP_TAG_INTERNAL]; - dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n"); - - atomic_inc(&cmd->active); /* active > 1 indicates error */ - if (cmd->comp_data && cmd->comp_func) { - cmd->comp_func(port, MTIP_TAG_INTERNAL, - cmd->comp_data, PORT_IRQ_TF_ERR); - } - goto handle_tfe_exit; - } /* clear the tag accumulator */ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + /* Set eh_active */ + set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); + /* Loop through all the groups */ for (group = 0; group < dd->slot_groups; group++) { completed = readl(port->completed[group]); @@ -948,7 +940,6 @@ static void mtip_handle_tfe(struct driver_data *dd) } print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt); -handle_tfe_exit: /* clear eh_active */ clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); wake_up_interruptible(&port->svc_wait); @@ -970,8 +961,6 @@ static inline void mtip_process_sdbf(struct driver_data *dd) /* walk all bits in all slot groups */ for (group = 0; group < dd->slot_groups; group++) { completed = readl(port->completed[group]); - if (!completed) - continue; /* clear completed status register in the hardware.*/ writel(completed, port->completed[group]); @@ -1340,6 +1329,22 @@ static int mtip_exec_internal_command(struct mtip_port *port, } rv = -EAGAIN; } + + if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) + & (1 << MTIP_TAG_INTERNAL)) { + dev_warn(&port->dd->pdev->dev, + "Retiring internal command but CI is 1.\n"); + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &port->dd->dd_flag)) { + hba_reset_nosleep(port->dd); + rv = -ENXIO; + } else { + mtip_restart_port(port); + rv = -EAGAIN; + } + goto exec_ic_exit; + } + } else { /* Spin for checking if command still outstanding */ timeout = jiffies + msecs_to_jiffies(timeout); @@ -1356,25 +1361,21 @@ static int mtip_exec_internal_command(struct mtip_port *port, rv = -ENXIO; goto exec_ic_exit; } - if (readl(port->mmio + PORT_IRQ_STAT) & PORT_IRQ_ERR) { - atomic_inc(&int_cmd->active); /* error */ - break; - } } - } - if (atomic_read(&int_cmd->active) > 1) { - dev_err(&port->dd->pdev->dev, - "Internal command [%02X] failed\n", fis->command); - rv = -EIO; - } - if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) + if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) & (1 << MTIP_TAG_INTERNAL)) { - rv = -ENXIO; - if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT, - &port->dd->dd_flag)) { - mtip_restart_port(port); + dev_err(&port->dd->pdev->dev, + "Internal command did not complete [atomic]\n"); rv = -EAGAIN; + if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, + &port->dd->dd_flag)) { + hba_reset_nosleep(port->dd); + rv = -ENXIO; + } else { + mtip_restart_port(port); + rv = -EAGAIN; + } } } exec_ic_exit: @@ -1892,33 +1893,13 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, void __user *user_buffer) { struct host_to_dev_fis fis; - struct host_to_dev_fis *reply; - u8 *buf = NULL; - dma_addr_t dma_addr = 0; - int rv = 0, xfer_sz = command[3]; - - if (xfer_sz) { - if (user_buffer) - return -EFAULT; - - buf = dmam_alloc_coherent(&port->dd->pdev->dev, - ATA_SECT_SIZE * xfer_sz, - &dma_addr, - GFP_KERNEL); - if (!buf) { - dev_err(&port->dd->pdev->dev, - "Memory allocation failed (%d bytes)\n", - ATA_SECT_SIZE * xfer_sz); - return -ENOMEM; - } - memset(buf, 0, ATA_SECT_SIZE * xfer_sz); - } + struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); /* Build the FIS. */ memset(&fis, 0, sizeof(struct host_to_dev_fis)); - fis.type = 0x27; - fis.opts = 1 << 7; - fis.command = command[0]; + fis.type = 0x27; + fis.opts = 1 << 7; + fis.command = command[0]; fis.features = command[2]; fis.sect_count = command[3]; if (fis.command == ATA_CMD_SMART) { @@ -1927,11 +1908,6 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, fis.cyl_hi = 0xC2; } - if (xfer_sz) - reply = (port->rxfis + RX_FIS_PIO_SETUP); - else - reply = (port->rxfis + RX_FIS_D2H_REG); - dbg_printk(MTIP_DRV_NAME " %s: User Command: cmd %x, sect %x, " "feat %x, sectcnt %x\n", @@ -1941,46 +1917,43 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, command[2], command[3]); + memset(port->sector_buffer, 0x00, ATA_SECT_SIZE); + /* Execute the command. */ if (mtip_exec_internal_command(port, &fis, 5, - (xfer_sz ? dma_addr : 0), - (xfer_sz ? ATA_SECT_SIZE * xfer_sz : 0), + port->sector_buffer_dma, + (command[3] != 0) ? ATA_SECT_SIZE : 0, 0, GFP_KERNEL, MTIP_IOCTL_COMMAND_TIMEOUT_MS) < 0) { - rv = -EFAULT; - goto exit_drive_command; + return -1; } /* Collect the completion status. */ command[0] = reply->command; /* Status*/ command[1] = reply->features; /* Error*/ - command[2] = reply->sect_count; + command[2] = command[3]; dbg_printk(MTIP_DRV_NAME " %s: Completion Status: stat %x, " - "err %x, nsect %x\n", + "err %x, cmd %x\n", __func__, command[0], command[1], command[2]); - if (xfer_sz) { + if (user_buffer && command[3]) { if (copy_to_user(user_buffer, - buf, + port->sector_buffer, ATA_SECT_SIZE * command[3])) { - rv = -EFAULT; - goto exit_drive_command; + return -EFAULT; } } -exit_drive_command: - if (buf) - dmam_free_coherent(&port->dd->pdev->dev, - ATA_SECT_SIZE * xfer_sz, buf, dma_addr); - return rv; + + return 0; } /* @@ -2030,32 +2003,6 @@ static unsigned int implicit_sector(unsigned char command, return rv; } -static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) -{ - switch (fis->command) { - case ATA_CMD_DOWNLOAD_MICRO: - *timeout = 120000; /* 2 minutes */ - break; - case ATA_CMD_SEC_ERASE_UNIT: - case 0xFC: - *timeout = 240000; /* 4 minutes */ - break; - case ATA_CMD_STANDBYNOW1: - *timeout = 10000; /* 10 seconds */ - break; - case 0xF7: - case 0xFA: - *timeout = 60000; /* 60 seconds */ - break; - case ATA_CMD_SMART: - *timeout = 15000; /* 15 seconds */ - break; - default: - *timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS; - break; - } -} - /* * Executes a taskfile * See ide_taskfile_ioctl() for derivation @@ -2076,7 +2023,7 @@ static int exec_drive_taskfile(struct driver_data *dd, unsigned int taskin = 0; unsigned int taskout = 0; u8 nsect = 0; - unsigned int timeout; + unsigned int timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS; unsigned int force_single_sector; unsigned int transfer_size; unsigned long task_file_data; @@ -2206,7 +2153,32 @@ static int exec_drive_taskfile(struct driver_data *dd, fis.lba_hi, fis.device); - mtip_set_timeout(&fis, &timeout); + switch (fis.command) { + case ATA_CMD_DOWNLOAD_MICRO: + /* Change timeout for Download Microcode to 2 minutes */ + timeout = 120000; + break; + case ATA_CMD_SEC_ERASE_UNIT: + /* Change timeout for Security Erase Unit to 4 minutes.*/ + timeout = 240000; + break; + case ATA_CMD_STANDBYNOW1: + /* Change timeout for standby immediate to 10 seconds.*/ + timeout = 10000; + break; + case 0xF7: + case 0xFA: + /* Change timeout for vendor unique command to 10 secs */ + timeout = 10000; + break; + case ATA_CMD_SMART: + /* Change timeout for vendor unique command to 15 secs */ + timeout = 15000; + break; + default: + timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS; + break; + } /* Determine the correct transfer size.*/ if (force_single_sector) @@ -2323,12 +2295,13 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, { switch (cmd) { case HDIO_GET_IDENTITY: - { - if (copy_to_user((void __user *)arg, dd->port->identify, - sizeof(u16) * ATA_ID_WORDS)) - return -EFAULT; + if (mtip_get_identify(dd->port, (void __user *) arg) < 0) { + dev_warn(&dd->pdev->dev, + "Unable to read identity\n"); + return -EIO; + } + break; - } case HDIO_DRIVE_CMD: { u8 drive_command[4]; @@ -2564,58 +2537,40 @@ static ssize_t mtip_hw_show_registers(struct device *dev, int size = 0; int n; - size += sprintf(&buf[size], "Hardware\n--------\n"); - size += sprintf(&buf[size], "S ACTive : [ 0x"); + size += sprintf(&buf[size], "S ACTive:\n"); - for (n = dd->slot_groups-1; n >= 0; n--) - size += sprintf(&buf[size], "%08X ", + for (n = 0; n < dd->slot_groups; n++) + size += sprintf(&buf[size], "0x%08x\n", readl(dd->port->s_active[n])); - size += sprintf(&buf[size], "]\n"); - size += sprintf(&buf[size], "Command Issue : [ 0x"); + size += sprintf(&buf[size], "Command Issue:\n"); - for (n = dd->slot_groups-1; n >= 0; n--) - size += sprintf(&buf[size], "%08X ", + for (n = 0; n < dd->slot_groups; n++) + size += sprintf(&buf[size], "0x%08x\n", readl(dd->port->cmd_issue[n])); - size += sprintf(&buf[size], "]\n"); - size += sprintf(&buf[size], "Completed : [ 0x"); - - for (n = dd->slot_groups-1; n >= 0; n--) - size += sprintf(&buf[size], "%08X ", - readl(dd->port->completed[n])); - - size += sprintf(&buf[size], "]\n"); - size += sprintf(&buf[size], "PORT IRQ STAT : [ 0x%08X ]\n", - readl(dd->port->mmio + PORT_IRQ_STAT)); - size += sprintf(&buf[size], "HOST IRQ STAT : [ 0x%08X ]\n", - readl(dd->mmio + HOST_IRQ_STAT)); - size += sprintf(&buf[size], "\n"); + size += sprintf(&buf[size], "Allocated:\n"); - size += sprintf(&buf[size], "Local\n-----\n"); - size += sprintf(&buf[size], "Allocated : [ 0x"); - - for (n = dd->slot_groups-1; n >= 0; n--) { + for (n = 0; n < dd->slot_groups; n++) { if (sizeof(long) > sizeof(u32)) group_allocated = dd->port->allocated[n/2] >> (32*(n&1)); else group_allocated = dd->port->allocated[n]; - size += sprintf(&buf[size], "%08X ", group_allocated); + size += sprintf(&buf[size], "0x%08x\n", + group_allocated); } - size += sprintf(&buf[size], "]\n"); - size += sprintf(&buf[size], "Commands in Q: [ 0x"); + size += sprintf(&buf[size], "Completed:\n"); - for (n = dd->slot_groups-1; n >= 0; n--) { - if (sizeof(long) > sizeof(u32)) - group_allocated = - dd->port->cmds_to_issue[n/2] >> (32*(n&1)); - else - group_allocated = dd->port->cmds_to_issue[n]; - size += sprintf(&buf[size], "%08X ", group_allocated); - } - size += sprintf(&buf[size], "]\n"); + for (n = 0; n < dd->slot_groups; n++) + size += sprintf(&buf[size], "0x%08x\n", + readl(dd->port->completed[n])); + + size += sprintf(&buf[size], "PORT IRQ STAT : 0x%08x\n", + readl(dd->port->mmio + PORT_IRQ_STAT)); + size += sprintf(&buf[size], "HOST IRQ STAT : 0x%08x\n", + readl(dd->mmio + HOST_IRQ_STAT)); return size; } @@ -2637,24 +2592,8 @@ static ssize_t mtip_hw_show_status(struct device *dev, return size; } -static ssize_t mtip_hw_show_flags(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct driver_data *dd = dev_to_disk(dev)->private_data; - int size = 0; - - size += sprintf(&buf[size], "Flag in port struct : [ %08lX ]\n", - dd->port->flags); - size += sprintf(&buf[size], "Flag in dd struct : [ %08lX ]\n", - dd->dd_flag); - - return size; -} - static DEVICE_ATTR(registers, S_IRUGO, mtip_hw_show_registers, NULL); static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL); -static DEVICE_ATTR(flags, S_IRUGO, mtip_hw_show_flags, NULL); /* * Create the sysfs related attributes. @@ -2677,9 +2616,6 @@ static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj) if (sysfs_create_file(kobj, &dev_attr_status.attr)) dev_warn(&dd->pdev->dev, "Error creating 'status' sysfs entry\n"); - if (sysfs_create_file(kobj, &dev_attr_flags.attr)) - dev_warn(&dd->pdev->dev, - "Error creating 'flags' sysfs entry\n"); return 0; } @@ -2700,7 +2636,6 @@ static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj) sysfs_remove_file(kobj, &dev_attr_registers.attr); sysfs_remove_file(kobj, &dev_attr_status.attr); - sysfs_remove_file(kobj, &dev_attr_flags.attr); return 0; } @@ -3699,10 +3634,7 @@ static int mtip_block_initialize(struct driver_data *dd) set_bit(QUEUE_FLAG_NONROT, &dd->queue->queue_flags); blk_queue_max_segments(dd->queue, MTIP_MAX_SG); blk_queue_physical_block_size(dd->queue, 4096); - blk_queue_max_hw_sectors(dd->queue, 0xffff); - blk_queue_max_segment_size(dd->queue, 0x400000); blk_queue_io_min(dd->queue, 4096); - /* * write back cache is not supported in the device. FUA depends on * write back cache support, hence setting flush support to zero. diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.h b/trunk/drivers/block/mtip32xx/mtip32xx.h index b2c88da26b2a..4ef58336310a 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.h +++ b/trunk/drivers/block/mtip32xx/mtip32xx.h @@ -113,35 +113,33 @@ #define __force_bit2int (unsigned int __force) -enum { - /* below are bit numbers in 'flags' defined in mtip_port */ - MTIP_PF_IC_ACTIVE_BIT = 0, /* pio/ioctl */ - MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */ - MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */ - MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */ - MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) | \ +/* below are bit numbers in 'flags' defined in mtip_port */ +#define MTIP_PF_IC_ACTIVE_BIT 0 /* pio/ioctl */ +#define MTIP_PF_EH_ACTIVE_BIT 1 /* error handling */ +#define MTIP_PF_SE_ACTIVE_BIT 2 /* secure erase */ +#define MTIP_PF_DM_ACTIVE_BIT 3 /* download microcde */ +#define MTIP_PF_PAUSE_IO ((1 << MTIP_PF_IC_ACTIVE_BIT) | \ (1 << MTIP_PF_EH_ACTIVE_BIT) | \ (1 << MTIP_PF_SE_ACTIVE_BIT) | \ - (1 << MTIP_PF_DM_ACTIVE_BIT)), - - MTIP_PF_SVC_THD_ACTIVE_BIT = 4, - MTIP_PF_ISSUE_CMDS_BIT = 5, - MTIP_PF_REBUILD_BIT = 6, - MTIP_PF_SVC_THD_STOP_BIT = 8, - - /* below are bit numbers in 'dd_flag' defined in driver_data */ - MTIP_DDF_REMOVE_PENDING_BIT = 1, - MTIP_DDF_OVER_TEMP_BIT = 2, - MTIP_DDF_WRITE_PROTECT_BIT = 3, - MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \ + (1 << MTIP_PF_DM_ACTIVE_BIT)) + +#define MTIP_PF_SVC_THD_ACTIVE_BIT 4 +#define MTIP_PF_ISSUE_CMDS_BIT 5 +#define MTIP_PF_REBUILD_BIT 6 +#define MTIP_PF_SVC_THD_STOP_BIT 8 + +/* below are bit numbers in 'dd_flag' defined in driver_data */ +#define MTIP_DDF_REMOVE_PENDING_BIT 1 +#define MTIP_DDF_OVER_TEMP_BIT 2 +#define MTIP_DDF_WRITE_PROTECT_BIT 3 +#define MTIP_DDF_STOP_IO ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \ (1 << MTIP_DDF_OVER_TEMP_BIT) | \ - (1 << MTIP_DDF_WRITE_PROTECT_BIT)), + (1 << MTIP_DDF_WRITE_PROTECT_BIT)) - MTIP_DDF_CLEANUP_BIT = 5, - MTIP_DDF_RESUME_BIT = 6, - MTIP_DDF_INIT_DONE_BIT = 7, - MTIP_DDF_REBUILD_FAILED_BIT = 8, -}; +#define MTIP_DDF_CLEANUP_BIT 5 +#define MTIP_DDF_RESUME_BIT 6 +#define MTIP_DDF_INIT_DONE_BIT 7 +#define MTIP_DDF_REBUILD_FAILED_BIT 8 __packed struct smart_attr{ u8 attr_id; diff --git a/trunk/drivers/char/agp/intel-agp.c b/trunk/drivers/char/agp/intel-agp.c index 0a4185279417..764f70c5e690 100644 --- a/trunk/drivers/char/agp/intel-agp.c +++ b/trunk/drivers/char/agp/intel-agp.c @@ -898,7 +898,6 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_B43_HB), ID(PCI_DEVICE_ID_INTEL_B43_1_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), - ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), diff --git a/trunk/drivers/char/agp/intel-agp.h b/trunk/drivers/char/agp/intel-agp.h index 8e2d9140f300..c0091753a0d1 100644 --- a/trunk/drivers/char/agp/intel-agp.h +++ b/trunk/drivers/char/agp/intel-agp.h @@ -212,7 +212,6 @@ #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 -#define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 diff --git a/trunk/drivers/char/hw_random/atmel-rng.c b/trunk/drivers/char/hw_random/atmel-rng.c index 6289f0eee24c..f518b99f53f5 100644 --- a/trunk/drivers/char/hw_random/atmel-rng.c +++ b/trunk/drivers/char/hw_random/atmel-rng.c @@ -36,13 +36,6 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max, /* data ready? */ if (readl(trng->base + TRNG_ODATA) & 1) { *data = readl(trng->base + TRNG_ODATA); - /* - ensure data ready is only set again AFTER the next data - word is ready in case it got set between checking ISR - and reading ODATA, so we don't risk re-reading the - same word - */ - readl(trng->base + TRNG_ISR); return 4; } else return 0; diff --git a/trunk/drivers/clocksource/Makefile b/trunk/drivers/clocksource/Makefile index dd3e661a124d..8d81a1d32653 100644 --- a/trunk/drivers/clocksource/Makefile +++ b/trunk/drivers/clocksource/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += cs5535-clockevt.o obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o -obj-$(CONFIG_EM_TIMER_STI) += em_sti.o obj-$(CONFIG_CLKBLD_I8253) += i8253.o obj-$(CONFIG_CLKSRC_MMIO) += mmio.o obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o diff --git a/trunk/drivers/clocksource/em_sti.c b/trunk/drivers/clocksource/em_sti.c deleted file mode 100644 index 372051d1bba8..000000000000 --- a/trunk/drivers/clocksource/em_sti.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Emma Mobile Timer Support - STI - * - * Copyright (C) 2012 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { USER_CLOCKSOURCE, USER_CLOCKEVENT, USER_NR }; - -struct em_sti_priv { - void __iomem *base; - struct clk *clk; - struct platform_device *pdev; - unsigned int active[USER_NR]; - unsigned long rate; - raw_spinlock_t lock; - struct clock_event_device ced; - struct clocksource cs; -}; - -#define STI_CONTROL 0x00 -#define STI_COMPA_H 0x10 -#define STI_COMPA_L 0x14 -#define STI_COMPB_H 0x18 -#define STI_COMPB_L 0x1c -#define STI_COUNT_H 0x20 -#define STI_COUNT_L 0x24 -#define STI_COUNT_RAW_H 0x28 -#define STI_COUNT_RAW_L 0x2c -#define STI_SET_H 0x30 -#define STI_SET_L 0x34 -#define STI_INTSTATUS 0x40 -#define STI_INTRAWSTATUS 0x44 -#define STI_INTENSET 0x48 -#define STI_INTENCLR 0x4c -#define STI_INTFFCLR 0x50 - -static inline unsigned long em_sti_read(struct em_sti_priv *p, int offs) -{ - return ioread32(p->base + offs); -} - -static inline void em_sti_write(struct em_sti_priv *p, int offs, - unsigned long value) -{ - iowrite32(value, p->base + offs); -} - -static int em_sti_enable(struct em_sti_priv *p) -{ - int ret; - - /* enable clock */ - ret = clk_enable(p->clk); - if (ret) { - dev_err(&p->pdev->dev, "cannot enable clock\n"); - return ret; - } - - /* configure channel, periodic mode and maximum timeout */ - p->rate = clk_get_rate(p->clk); - - /* reset the counter */ - em_sti_write(p, STI_SET_H, 0x40000000); - em_sti_write(p, STI_SET_L, 0x00000000); - - /* mask and clear pending interrupts */ - em_sti_write(p, STI_INTENCLR, 3); - em_sti_write(p, STI_INTFFCLR, 3); - - /* enable updates of counter registers */ - em_sti_write(p, STI_CONTROL, 1); - - return 0; -} - -static void em_sti_disable(struct em_sti_priv *p) -{ - /* mask interrupts */ - em_sti_write(p, STI_INTENCLR, 3); - - /* stop clock */ - clk_disable(p->clk); -} - -static cycle_t em_sti_count(struct em_sti_priv *p) -{ - cycle_t ticks; - unsigned long flags; - - /* the STI hardware buffers the 48-bit count, but to - * break it out into two 32-bit access the registers - * must be accessed in a certain order. - * Always read STI_COUNT_H before STI_COUNT_L. - */ - raw_spin_lock_irqsave(&p->lock, flags); - ticks = (cycle_t)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32; - ticks |= em_sti_read(p, STI_COUNT_L); - raw_spin_unlock_irqrestore(&p->lock, flags); - - return ticks; -} - -static cycle_t em_sti_set_next(struct em_sti_priv *p, cycle_t next) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&p->lock, flags); - - /* mask compare A interrupt */ - em_sti_write(p, STI_INTENCLR, 1); - - /* update compare A value */ - em_sti_write(p, STI_COMPA_H, next >> 32); - em_sti_write(p, STI_COMPA_L, next & 0xffffffff); - - /* clear compare A interrupt source */ - em_sti_write(p, STI_INTFFCLR, 1); - - /* unmask compare A interrupt */ - em_sti_write(p, STI_INTENSET, 1); - - raw_spin_unlock_irqrestore(&p->lock, flags); - - return next; -} - -static irqreturn_t em_sti_interrupt(int irq, void *dev_id) -{ - struct em_sti_priv *p = dev_id; - - p->ced.event_handler(&p->ced); - return IRQ_HANDLED; -} - -static int em_sti_start(struct em_sti_priv *p, unsigned int user) -{ - unsigned long flags; - int used_before; - int ret = 0; - - raw_spin_lock_irqsave(&p->lock, flags); - used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; - if (!used_before) - ret = em_sti_enable(p); - - if (!ret) - p->active[user] = 1; - raw_spin_unlock_irqrestore(&p->lock, flags); - - return ret; -} - -static void em_sti_stop(struct em_sti_priv *p, unsigned int user) -{ - unsigned long flags; - int used_before, used_after; - - raw_spin_lock_irqsave(&p->lock, flags); - used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; - p->active[user] = 0; - used_after = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; - - if (used_before && !used_after) - em_sti_disable(p); - raw_spin_unlock_irqrestore(&p->lock, flags); -} - -static struct em_sti_priv *cs_to_em_sti(struct clocksource *cs) -{ - return container_of(cs, struct em_sti_priv, cs); -} - -static cycle_t em_sti_clocksource_read(struct clocksource *cs) -{ - return em_sti_count(cs_to_em_sti(cs)); -} - -static int em_sti_clocksource_enable(struct clocksource *cs) -{ - int ret; - struct em_sti_priv *p = cs_to_em_sti(cs); - - ret = em_sti_start(p, USER_CLOCKSOURCE); - if (!ret) - __clocksource_updatefreq_hz(cs, p->rate); - return ret; -} - -static void em_sti_clocksource_disable(struct clocksource *cs) -{ - em_sti_stop(cs_to_em_sti(cs), USER_CLOCKSOURCE); -} - -static void em_sti_clocksource_resume(struct clocksource *cs) -{ - em_sti_clocksource_enable(cs); -} - -static int em_sti_register_clocksource(struct em_sti_priv *p) -{ - struct clocksource *cs = &p->cs; - - memset(cs, 0, sizeof(*cs)); - cs->name = dev_name(&p->pdev->dev); - cs->rating = 200; - cs->read = em_sti_clocksource_read; - cs->enable = em_sti_clocksource_enable; - cs->disable = em_sti_clocksource_disable; - cs->suspend = em_sti_clocksource_disable; - cs->resume = em_sti_clocksource_resume; - cs->mask = CLOCKSOURCE_MASK(48); - cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - - dev_info(&p->pdev->dev, "used as clock source\n"); - - /* Register with dummy 1 Hz value, gets updated in ->enable() */ - clocksource_register_hz(cs, 1); - return 0; -} - -static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced) -{ - return container_of(ced, struct em_sti_priv, ced); -} - -static void em_sti_clock_event_mode(enum clock_event_mode mode, - struct clock_event_device *ced) -{ - struct em_sti_priv *p = ced_to_em_sti(ced); - - /* deal with old setting first */ - switch (ced->mode) { - case CLOCK_EVT_MODE_ONESHOT: - em_sti_stop(p, USER_CLOCKEVENT); - break; - default: - break; - } - - switch (mode) { - case CLOCK_EVT_MODE_ONESHOT: - dev_info(&p->pdev->dev, "used for oneshot clock events\n"); - em_sti_start(p, USER_CLOCKEVENT); - clockevents_config(&p->ced, p->rate); - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - em_sti_stop(p, USER_CLOCKEVENT); - break; - default: - break; - } -} - -static int em_sti_clock_event_next(unsigned long delta, - struct clock_event_device *ced) -{ - struct em_sti_priv *p = ced_to_em_sti(ced); - cycle_t next; - int safe; - - next = em_sti_set_next(p, em_sti_count(p) + delta); - safe = em_sti_count(p) < (next - 1); - - return !safe; -} - -static void em_sti_register_clockevent(struct em_sti_priv *p) -{ - struct clock_event_device *ced = &p->ced; - - memset(ced, 0, sizeof(*ced)); - ced->name = dev_name(&p->pdev->dev); - ced->features = CLOCK_EVT_FEAT_ONESHOT; - ced->rating = 200; - ced->cpumask = cpumask_of(0); - ced->set_next_event = em_sti_clock_event_next; - ced->set_mode = em_sti_clock_event_mode; - - dev_info(&p->pdev->dev, "used for clock events\n"); - - /* Register with dummy 1 Hz value, gets updated in ->set_mode() */ - clockevents_config_and_register(ced, 1, 2, 0xffffffff); -} - -static int __devinit em_sti_probe(struct platform_device *pdev) -{ - struct em_sti_priv *p; - struct resource *res; - int irq, ret; - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) { - dev_err(&pdev->dev, "failed to allocate driver data\n"); - ret = -ENOMEM; - goto err0; - } - - p->pdev = pdev; - platform_set_drvdata(pdev, p); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "failed to get I/O memory\n"); - ret = -EINVAL; - goto err0; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); - ret = -EINVAL; - goto err0; - } - - /* map memory, let base point to the STI instance */ - p->base = ioremap_nocache(res->start, resource_size(res)); - if (p->base == NULL) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - ret = -ENXIO; - goto err0; - } - - /* get hold of clock */ - p->clk = clk_get(&pdev->dev, "sclk"); - if (IS_ERR(p->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(p->clk); - goto err1; - } - - if (request_irq(irq, em_sti_interrupt, - IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, - dev_name(&pdev->dev), p)) { - dev_err(&pdev->dev, "failed to request low IRQ\n"); - ret = -ENOENT; - goto err2; - } - - raw_spin_lock_init(&p->lock); - em_sti_register_clockevent(p); - em_sti_register_clocksource(p); - return 0; - -err2: - clk_put(p->clk); -err1: - iounmap(p->base); -err0: - kfree(p); - return ret; -} - -static int __devexit em_sti_remove(struct platform_device *pdev) -{ - return -EBUSY; /* cannot unregister clockevent and clocksource */ -} - -static const struct of_device_id em_sti_dt_ids[] __devinitconst = { - { .compatible = "renesas,em-sti", }, - {}, -}; -MODULE_DEVICE_TABLE(of, em_sti_dt_ids); - -static struct platform_driver em_sti_device_driver = { - .probe = em_sti_probe, - .remove = __devexit_p(em_sti_remove), - .driver = { - .name = "em_sti", - .of_match_table = em_sti_dt_ids, - } -}; - -module_platform_driver(em_sti_device_driver); - -MODULE_AUTHOR("Magnus Damm"); -MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/clocksource/sh_cmt.c b/trunk/drivers/clocksource/sh_cmt.c index 98b06baafcc6..32fe9ef5cc5c 100644 --- a/trunk/drivers/clocksource/sh_cmt.c +++ b/trunk/drivers/clocksource/sh_cmt.c @@ -48,13 +48,13 @@ struct sh_cmt_priv { unsigned long next_match_value; unsigned long max_match_value; unsigned long rate; - raw_spinlock_t lock; + spinlock_t lock; struct clock_event_device ced; struct clocksource cs; unsigned long total_cycles; }; -static DEFINE_RAW_SPINLOCK(sh_cmt_lock); +static DEFINE_SPINLOCK(sh_cmt_lock); #define CMSTR -1 /* shared register */ #define CMCSR 0 /* channel register */ @@ -139,7 +139,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - raw_spin_lock_irqsave(&sh_cmt_lock, flags); + spin_lock_irqsave(&sh_cmt_lock, flags); value = sh_cmt_read(p, CMSTR); if (start) @@ -148,7 +148,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_cmt_write(p, CMSTR, value); - raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); + spin_unlock_irqrestore(&sh_cmt_lock, flags); } static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) @@ -328,9 +328,9 @@ static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) { unsigned long flags; - raw_spin_lock_irqsave(&p->lock, flags); + spin_lock_irqsave(&p->lock, flags); __sh_cmt_set_next(p, delta); - raw_spin_unlock_irqrestore(&p->lock, flags); + spin_unlock_irqrestore(&p->lock, flags); } static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) @@ -385,7 +385,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) int ret = 0; unsigned long flags; - raw_spin_lock_irqsave(&p->lock, flags); + spin_lock_irqsave(&p->lock, flags); if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) ret = sh_cmt_enable(p, &p->rate); @@ -398,7 +398,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT))) __sh_cmt_set_next(p, p->max_match_value); out: - raw_spin_unlock_irqrestore(&p->lock, flags); + spin_unlock_irqrestore(&p->lock, flags); return ret; } @@ -408,7 +408,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) unsigned long flags; unsigned long f; - raw_spin_lock_irqsave(&p->lock, flags); + spin_lock_irqsave(&p->lock, flags); f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE); p->flags &= ~flag; @@ -420,7 +420,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE)) __sh_cmt_set_next(p, p->max_match_value); - raw_spin_unlock_irqrestore(&p->lock, flags); + spin_unlock_irqrestore(&p->lock, flags); } static struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs) @@ -435,13 +435,13 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs) unsigned long value; int has_wrapped; - raw_spin_lock_irqsave(&p->lock, flags); + spin_lock_irqsave(&p->lock, flags); value = p->total_cycles; raw = sh_cmt_get_counter(p, &has_wrapped); if (unlikely(has_wrapped)) raw += p->match_value + 1; - raw_spin_unlock_irqrestore(&p->lock, flags); + spin_unlock_irqrestore(&p->lock, flags); return value + raw; } @@ -591,7 +591,7 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name, p->max_match_value = (1 << p->width) - 1; p->match_value = p->max_match_value; - raw_spin_lock_init(&p->lock); + spin_lock_init(&p->lock); if (clockevent_rating) sh_cmt_register_clockevent(p, name, clockevent_rating); diff --git a/trunk/drivers/clocksource/sh_mtu2.c b/trunk/drivers/clocksource/sh_mtu2.c index d9b76ca64a61..a2172f690418 100644 --- a/trunk/drivers/clocksource/sh_mtu2.c +++ b/trunk/drivers/clocksource/sh_mtu2.c @@ -43,7 +43,7 @@ struct sh_mtu2_priv { struct clock_event_device ced; }; -static DEFINE_RAW_SPINLOCK(sh_mtu2_lock); +static DEFINE_SPINLOCK(sh_mtu2_lock); #define TSTR -1 /* shared register */ #define TCR 0 /* channel register */ @@ -107,7 +107,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - raw_spin_lock_irqsave(&sh_mtu2_lock, flags); + spin_lock_irqsave(&sh_mtu2_lock, flags); value = sh_mtu2_read(p, TSTR); if (start) @@ -116,7 +116,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_mtu2_write(p, TSTR, value); - raw_spin_unlock_irqrestore(&sh_mtu2_lock, flags); + spin_unlock_irqrestore(&sh_mtu2_lock, flags); } static int sh_mtu2_enable(struct sh_mtu2_priv *p) diff --git a/trunk/drivers/clocksource/sh_tmu.c b/trunk/drivers/clocksource/sh_tmu.c index c1b51d49d106..97f54b634be4 100644 --- a/trunk/drivers/clocksource/sh_tmu.c +++ b/trunk/drivers/clocksource/sh_tmu.c @@ -45,7 +45,7 @@ struct sh_tmu_priv { struct clocksource cs; }; -static DEFINE_RAW_SPINLOCK(sh_tmu_lock); +static DEFINE_SPINLOCK(sh_tmu_lock); #define TSTR -1 /* shared register */ #define TCOR 0 /* channel register */ @@ -95,7 +95,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - raw_spin_lock_irqsave(&sh_tmu_lock, flags); + spin_lock_irqsave(&sh_tmu_lock, flags); value = sh_tmu_read(p, TSTR); if (start) @@ -104,7 +104,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_tmu_write(p, TSTR, value); - raw_spin_unlock_irqrestore(&sh_tmu_lock, flags); + spin_unlock_irqrestore(&sh_tmu_lock, flags); } static int sh_tmu_enable(struct sh_tmu_priv *p) @@ -245,7 +245,12 @@ static void sh_tmu_clock_event_start(struct sh_tmu_priv *p, int periodic) sh_tmu_enable(p); - clockevents_config(ced, p->rate); + /* TODO: calculate good shift from rate and counter bit width */ + + ced->shift = 32; + ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift); + ced->max_delta_ns = clockevent_delta2ns(0xffffffff, ced); + ced->min_delta_ns = 5000; if (periodic) { p->periodic = (p->rate + HZ/2) / HZ; @@ -318,8 +323,7 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, ced->set_mode = sh_tmu_clock_event_mode; dev_info(&p->pdev->dev, "used for clock events\n"); - - clockevents_config_and_register(ced, 1, 0x300, 0xffffffff); + clockevents_register_device(ced); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { diff --git a/trunk/drivers/gpio/gpio-samsung.c b/trunk/drivers/gpio/gpio-samsung.c index b6453d0e44ad..7bb00448e13d 100644 --- a/trunk/drivers/gpio/gpio-samsung.c +++ b/trunk/drivers/gpio/gpio-samsung.c @@ -2833,7 +2833,7 @@ static __init void exynos5_gpiolib_init(void) } /* need to set base address for gpc4 */ - exynos5_gpios_1[11].base = gpio_base1 + 0x2E0; + exonys5_gpios_1[11].base = gpio_base1 + 0x2E0; /* need to set base address for gpx */ chip = &exynos5_gpios_1[21]; diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c index 7053140c6596..d7038230b71e 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -35,28 +35,9 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { {0,} }; - -static void cirrus_kick_out_firmware_fb(struct pci_dev *pdev) -{ - struct apertures_struct *ap; - bool primary = false; - - ap = alloc_apertures(1); - ap->ranges[0].base = pci_resource_start(pdev, 0); - ap->ranges[0].size = pci_resource_len(pdev, 0); - -#ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; -#endif - remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary); - kfree(ap); -} - static int __devinit cirrus_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - cirrus_kick_out_firmware_fb(pdev); - return drm_get_pci_dev(pdev, ent, &driver); } diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.h b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.h index 64ea597cb6d3..21bdfa8836f7 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -145,7 +145,7 @@ struct cirrus_device { struct ttm_bo_device bdev; atomic_t validate_sequence; } ttm; - bool mm_inited; + }; diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c b/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c index 50e170f879de..2ebcd11a5023 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_ttm.c @@ -275,17 +275,12 @@ int cirrus_mm_init(struct cirrus_device *cirrus) pci_resource_len(dev->pdev, 0), DRM_MTRR_WC); - cirrus->mm_inited = true; return 0; } void cirrus_mm_fini(struct cirrus_device *cirrus) { struct drm_device *dev = cirrus->dev; - - if (!cirrus->mm_inited) - return; - ttm_bo_device_release(&cirrus->ttm.bdev); cirrus_ttm_global_release(cirrus); diff --git a/trunk/drivers/gpu/drm/drm_edid.c b/trunk/drivers/gpu/drm/drm_edid.c index eb92fe257a39..c3b5139eba7f 100644 --- a/trunk/drivers/gpu/drm/drm_edid.c +++ b/trunk/drivers/gpu/drm/drm_edid.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include "drmP.h" #include "drm_edid.h" #include "drm_edid_modes.h" @@ -149,10 +149,6 @@ int drm_edid_header_is_valid(const u8 *raw_edid) } EXPORT_SYMBOL(drm_edid_header_is_valid); -static int edid_fixup __read_mostly = 6; -module_param_named(edid_fixup, edid_fixup, int, 0400); -MODULE_PARM_DESC(edid_fixup, - "Minimum number of valid EDID header bytes (0-8, default 6)"); /* * Sanity check the EDID block (base or extension). Return 0 if the block @@ -164,13 +160,10 @@ bool drm_edid_block_valid(u8 *raw_edid, int block) u8 csum = 0; struct edid *edid = (struct edid *)raw_edid; - if (edid_fixup > 8 || edid_fixup < 0) - edid_fixup = 6; - if (block == 0) { int score = drm_edid_header_is_valid(raw_edid); if (score == 8) ; - else if (score >= edid_fixup) { + else if (score >= 6) { DRM_DEBUG("Fixing EDID header, your hardware may be failing\n"); memcpy(raw_edid, edid_header, sizeof(edid_header)); } else { diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c index d6de2e07fa03..420953197d0a 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -244,8 +244,8 @@ static const struct file_operations exynos_drm_driver_fops = { }; static struct drm_driver exynos_drm_driver = { - .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET | - DRIVER_GEM | DRIVER_PRIME, + .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM | + DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, .load = exynos_drm_load, .unload = exynos_drm_unload, .open = exynos_drm_open, diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 23d5ad379f86..6e9ac7bd1dcf 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -172,12 +172,19 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder) manager_ops->commit(manager->dev); } +static struct drm_crtc * +exynos_drm_encoder_get_crtc(struct drm_encoder *encoder) +{ + return encoder->crtc; +} + static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { .dpms = exynos_drm_encoder_dpms, .mode_fixup = exynos_drm_encoder_mode_fixup, .mode_set = exynos_drm_encoder_mode_set, .prepare = exynos_drm_encoder_prepare, .commit = exynos_drm_encoder_commit, + .get_crtc = exynos_drm_encoder_get_crtc, }; static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c index 4ccfe4328fab..f82a299553fb 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -51,22 +51,11 @@ struct exynos_drm_fb { static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) { struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - unsigned int i; DRM_DEBUG_KMS("%s\n", __FILE__); drm_framebuffer_cleanup(fb); - for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) { - struct drm_gem_object *obj; - - if (exynos_fb->exynos_gem_obj[i] == NULL) - continue; - - obj = &exynos_fb->exynos_gem_obj[i]->base; - drm_gem_object_unreference_unlocked(obj); - } - kfree(exynos_fb); exynos_fb = NULL; } @@ -145,11 +134,11 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-ENOENT); } + drm_gem_object_unreference_unlocked(obj); + fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj); - if (IS_ERR(fb)) { - drm_gem_object_unreference_unlocked(obj); + if (IS_ERR(fb)) return fb; - } exynos_fb = to_exynos_fb(fb); nr = exynos_drm_format_num_buffers(fb->pixel_format); @@ -163,6 +152,8 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-ENOENT); } + drm_gem_object_unreference_unlocked(obj); + exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h index 50823756cdea..3ecb30d93552 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h @@ -31,10 +31,10 @@ static inline int exynos_drm_format_num_buffers(uint32_t format) { switch (format) { - case DRM_FORMAT_NV12: + case DRM_FORMAT_NV12M: case DRM_FORMAT_NV12MT: return 2; - case DRM_FORMAT_YUV420: + case DRM_FORMAT_YUV420M: return 3; default: return 1; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c index 5c8b683029ea..fc91293c4560 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -689,6 +689,7 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, struct drm_device *dev, uint32_t handle, uint64_t *offset) { + struct exynos_drm_gem_obj *exynos_gem_obj; struct drm_gem_object *obj; int ret = 0; @@ -709,13 +710,15 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, goto unlock; } - if (!obj->map_list.map) { - ret = drm_gem_create_mmap_offset(obj); + exynos_gem_obj = to_exynos_gem_obj(obj); + + if (!exynos_gem_obj->base.map_list.map) { + ret = drm_gem_create_mmap_offset(&exynos_gem_obj->base); if (ret) goto out; } - *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; + *offset = (u64)exynos_gem_obj->base.map_list.hash.key << PAGE_SHIFT; DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); out: diff --git a/trunk/drivers/gpu/drm/exynos/exynos_mixer.c b/trunk/drivers/gpu/drm/exynos/exynos_mixer.c index e2147a2ddcec..68ef01028375 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_mixer.c @@ -365,7 +365,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) switch (win_data->pixel_format) { case DRM_FORMAT_NV12MT: tiled_mode = true; - case DRM_FORMAT_NV12: + case DRM_FORMAT_NV12M: crcb_mode = false; buf_num = 2; break; @@ -601,19 +601,17 @@ static void mixer_win_reset(struct mixer_context *ctx) mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); /* setting graphical layers */ + val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */ val |= MXR_GRP_CFG_WIN_BLEND_EN; - val |= MXR_GRP_CFG_BLEND_PRE_MUL; - val |= MXR_GRP_CFG_PIXEL_BLEND_EN; val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */ /* the same configuration for both layers */ mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val); - mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val); - /* setting video layers */ - val = MXR_GRP_CFG_ALPHA_VAL(0); - mixer_reg_write(res, MXR_VIDEO_CFG, val); + val |= MXR_GRP_CFG_BLEND_PRE_MUL; + val |= MXR_GRP_CFG_PIXEL_BLEND_EN; + mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val); /* configuration of Video Processor Registers */ vp_win_reset(ctx); diff --git a/trunk/drivers/gpu/drm/i810/i810_dma.c b/trunk/drivers/gpu/drm/i810/i810_dma.c index fa9439159ebd..f920fb5e42b6 100644 --- a/trunk/drivers/gpu/drm/i810/i810_dma.c +++ b/trunk/drivers/gpu/drm/i810/i810_dma.c @@ -130,10 +130,11 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv) return -EINVAL; /* This is all entirely broken */ + down_write(¤t->mm->mmap_sem); old_fops = file_priv->filp->f_op; file_priv->filp->f_op = &i810_buffer_fops; dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)vm_mmap(file_priv->filp, 0, buf->total, + buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE, MAP_SHARED, buf->bus_address); dev_priv->mmap_buffer = NULL; @@ -144,6 +145,7 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv) retcode = PTR_ERR(buf_priv->virtual); buf_priv->virtual = NULL; } + up_write(¤t->mm->mmap_sem); return retcode; } diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.c b/trunk/drivers/gpu/drm/i915/i915_drv.c index 9fe9ebe52a7a..238a52165833 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.c +++ b/trunk/drivers/gpu/drm/i915/i915_drv.c @@ -233,7 +233,6 @@ static const struct intel_device_info intel_sandybridge_d_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_sandybridge_m_info = { @@ -244,7 +243,6 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_ivybridge_d_info = { @@ -254,7 +252,6 @@ static const struct intel_device_info intel_ivybridge_d_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_ivybridge_m_info = { @@ -265,7 +262,6 @@ static const struct intel_device_info intel_ivybridge_m_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_valleyview_m_info = { @@ -293,7 +289,6 @@ static const struct intel_device_info intel_haswell_d_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_haswell_m_info = { @@ -303,7 +298,6 @@ static const struct intel_device_info intel_haswell_m_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct pci_device_id pciidlist[] = { /* aka */ @@ -1145,9 +1139,10 @@ MODULE_LICENSE("GPL and additional rights"); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ - ((HAS_FORCE_WAKE((dev_priv)->dev)) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) + (((dev_priv)->info->gen >= 6) && \ + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE)) && \ + (!IS_VALLEYVIEW((dev_priv)->dev)) #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.h b/trunk/drivers/gpu/drm/i915/i915_drv.h index b0b676abde0d..377c21f531e4 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.h +++ b/trunk/drivers/gpu/drm/i915/i915_drv.h @@ -285,7 +285,6 @@ struct intel_device_info { u8 is_ivybridge:1; u8 is_valleyview:1; u8 has_pch_split:1; - u8 has_force_wake:1; u8 is_haswell:1; u8 has_fbc:1; u8 has_pipe_cxsr:1; @@ -943,9 +942,6 @@ struct drm_i915_gem_object { /* prime dma-buf support */ struct sg_table *sg_table; - void *dma_buf_vmapping; - int vmapping_count; - /** * Used for performing relocations during execbuffer insertion. */ @@ -1102,8 +1098,6 @@ struct drm_i915_file_private { #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) -#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) - #include "i915_trace.h" /** diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/trunk/drivers/gpu/drm/i915/i915_gem_dmabuf.c index aa308e1337db..8e269178d6a5 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -74,59 +74,6 @@ static void i915_gem_dmabuf_release(struct dma_buf *dma_buf) } } -static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) -{ - struct drm_i915_gem_object *obj = dma_buf->priv; - struct drm_device *dev = obj->base.dev; - int ret; - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ERR_PTR(ret); - - if (obj->dma_buf_vmapping) { - obj->vmapping_count++; - goto out_unlock; - } - - if (!obj->pages) { - ret = i915_gem_object_get_pages_gtt(obj, __GFP_NORETRY | __GFP_NOWARN); - if (ret) { - mutex_unlock(&dev->struct_mutex); - return ERR_PTR(ret); - } - } - - obj->dma_buf_vmapping = vmap(obj->pages, obj->base.size / PAGE_SIZE, 0, PAGE_KERNEL); - if (!obj->dma_buf_vmapping) { - DRM_ERROR("failed to vmap object\n"); - goto out_unlock; - } - - obj->vmapping_count = 1; -out_unlock: - mutex_unlock(&dev->struct_mutex); - return obj->dma_buf_vmapping; -} - -static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) -{ - struct drm_i915_gem_object *obj = dma_buf->priv; - struct drm_device *dev = obj->base.dev; - int ret; - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return; - - --obj->vmapping_count; - if (obj->vmapping_count == 0) { - vunmap(obj->dma_buf_vmapping); - obj->dma_buf_vmapping = NULL; - } - mutex_unlock(&dev->struct_mutex); -} - static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num) { return NULL; @@ -146,11 +93,6 @@ static void i915_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_n } -static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) -{ - return -EINVAL; -} - static const struct dma_buf_ops i915_dmabuf_ops = { .map_dma_buf = i915_gem_map_dma_buf, .unmap_dma_buf = i915_gem_unmap_dma_buf, @@ -159,9 +101,6 @@ static const struct dma_buf_ops i915_dmabuf_ops = { .kmap_atomic = i915_gem_dmabuf_kmap_atomic, .kunmap = i915_gem_dmabuf_kunmap, .kunmap_atomic = i915_gem_dmabuf_kunmap_atomic, - .mmap = i915_gem_dmabuf_mmap, - .vmap = i915_gem_dmabuf_vmap, - .vunmap = i915_gem_dmabuf_vunmap, }; struct dma_buf *i915_gem_prime_export(struct drm_device *dev, diff --git a/trunk/drivers/gpu/drm/i915/i915_irq.c b/trunk/drivers/gpu/drm/i915/i915_irq.c index b1fe0edda955..1417660a93ec 100644 --- a/trunk/drivers/gpu/drm/i915/i915_irq.c +++ b/trunk/drivers/gpu/drm/i915/i915_irq.c @@ -510,7 +510,7 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) return ret; } -static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) +static void pch_irq_handler(struct drm_device *dev, u32 pch_iir) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; @@ -550,35 +550,6 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); } -static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - int pipe; - - if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) - DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", - (pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> - SDE_AUDIO_POWER_SHIFT_CPT); - - if (pch_iir & SDE_AUX_MASK_CPT) - DRM_DEBUG_DRIVER("AUX channel interrupt\n"); - - if (pch_iir & SDE_GMBUS_CPT) - DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n"); - - if (pch_iir & SDE_AUDIO_CP_REQ_CPT) - DRM_DEBUG_DRIVER("Audio CP request interrupt\n"); - - if (pch_iir & SDE_AUDIO_CP_CHG_CPT) - DRM_DEBUG_DRIVER("Audio CP change interrupt\n"); - - if (pch_iir & SDE_FDI_MASK_CPT) - for_each_pipe(pipe) - DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", - pipe_name(pipe), - I915_READ(FDI_RX_IIR(pipe))); -} - static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -620,7 +591,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) if (pch_iir & SDE_HOTPLUG_MASK_CPT) queue_work(dev_priv->wq, &dev_priv->hotplug_work); - cpt_irq_handler(dev, pch_iir); + pch_irq_handler(dev, pch_iir); /* clear PCH hotplug event before clear CPU irq */ I915_WRITE(SDEIIR, pch_iir); @@ -713,10 +684,7 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_PCH_EVENT) { if (pch_iir & hotplug_mask) queue_work(dev_priv->wq, &dev_priv->hotplug_work); - if (HAS_PCH_CPT(dev)) - cpt_irq_handler(dev, pch_iir); - else - ibx_irq_handler(dev, pch_iir); + pch_irq_handler(dev, pch_iir); } if (de_iir & DE_PCU_EVENT) { diff --git a/trunk/drivers/gpu/drm/i915/i915_reg.h b/trunk/drivers/gpu/drm/i915/i915_reg.h index 48d5e8e051cf..2d49b9507ed0 100644 --- a/trunk/drivers/gpu/drm/i915/i915_reg.h +++ b/trunk/drivers/gpu/drm/i915/i915_reg.h @@ -210,14 +210,6 @@ #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) -/* IVB has funny definitions for which plane to flip. */ -#define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19) -#define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19) -#define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19) -#define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) -#define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) -#define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) - #define MI_SET_CONTEXT MI_INSTR(0x18, 0) #define MI_MM_SPACE_GTT (1<<8) #define MI_MM_SPACE_PHYSICAL (0<<8) @@ -3321,7 +3313,7 @@ /* PCH */ -/* south display engine interrupt: IBX */ +/* south display engine interrupt */ #define SDE_AUDIO_POWER_D (1 << 27) #define SDE_AUDIO_POWER_C (1 << 26) #define SDE_AUDIO_POWER_B (1 << 25) @@ -3357,44 +3349,15 @@ #define SDE_TRANSA_CRC_ERR (1 << 1) #define SDE_TRANSA_FIFO_UNDER (1 << 0) #define SDE_TRANS_MASK (0x3f) - -/* south display engine interrupt: CPT/PPT */ -#define SDE_AUDIO_POWER_D_CPT (1 << 31) -#define SDE_AUDIO_POWER_C_CPT (1 << 30) -#define SDE_AUDIO_POWER_B_CPT (1 << 29) -#define SDE_AUDIO_POWER_SHIFT_CPT 29 -#define SDE_AUDIO_POWER_MASK_CPT (7 << 29) -#define SDE_AUXD_CPT (1 << 27) -#define SDE_AUXC_CPT (1 << 26) -#define SDE_AUXB_CPT (1 << 25) -#define SDE_AUX_MASK_CPT (7 << 25) +/* CPT */ +#define SDE_CRT_HOTPLUG_CPT (1 << 19) #define SDE_PORTD_HOTPLUG_CPT (1 << 23) #define SDE_PORTC_HOTPLUG_CPT (1 << 22) #define SDE_PORTB_HOTPLUG_CPT (1 << 21) -#define SDE_CRT_HOTPLUG_CPT (1 << 19) #define SDE_HOTPLUG_MASK_CPT (SDE_CRT_HOTPLUG_CPT | \ SDE_PORTD_HOTPLUG_CPT | \ SDE_PORTC_HOTPLUG_CPT | \ SDE_PORTB_HOTPLUG_CPT) -#define SDE_GMBUS_CPT (1 << 17) -#define SDE_AUDIO_CP_REQ_C_CPT (1 << 10) -#define SDE_AUDIO_CP_CHG_C_CPT (1 << 9) -#define SDE_FDI_RXC_CPT (1 << 8) -#define SDE_AUDIO_CP_REQ_B_CPT (1 << 6) -#define SDE_AUDIO_CP_CHG_B_CPT (1 << 5) -#define SDE_FDI_RXB_CPT (1 << 4) -#define SDE_AUDIO_CP_REQ_A_CPT (1 << 2) -#define SDE_AUDIO_CP_CHG_A_CPT (1 << 1) -#define SDE_FDI_RXA_CPT (1 << 0) -#define SDE_AUDIO_CP_REQ_CPT (SDE_AUDIO_CP_REQ_C_CPT | \ - SDE_AUDIO_CP_REQ_B_CPT | \ - SDE_AUDIO_CP_REQ_A_CPT) -#define SDE_AUDIO_CP_CHG_CPT (SDE_AUDIO_CP_CHG_C_CPT | \ - SDE_AUDIO_CP_CHG_B_CPT | \ - SDE_AUDIO_CP_CHG_A_CPT) -#define SDE_FDI_MASK_CPT (SDE_FDI_RXC_CPT | \ - SDE_FDI_RXB_CPT | \ - SDE_FDI_RXA_CPT) #define SDEISR 0xc4000 #define SDEIMR 0xc4004 diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index e0aa064def31..914789420906 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -6158,34 +6158,17 @@ static int intel_gen7_queue_flip(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; - uint32_t plane_bit = 0; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; - switch(intel_crtc->plane) { - case PLANE_A: - plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A; - break; - case PLANE_B: - plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B; - break; - case PLANE_C: - plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C; - break; - default: - WARN_ONCE(1, "unknown plane in flip command\n"); - ret = -ENODEV; - goto err; - } - ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; - intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); + intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19)); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); intel_ring_emit(ring, (obj->gtt_offset)); intel_ring_emit(ring, (MI_NOOP)); diff --git a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c index e5b84ff89ca5..b59b6d5b7583 100644 --- a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -266,15 +266,10 @@ u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) static int init_ring_common(struct intel_ring_buffer *ring) { - struct drm_device *dev = ring->dev; - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = ring->dev->dev_private; struct drm_i915_gem_object *obj = ring->obj; - int ret = 0; u32 head; - if (HAS_FORCE_WAKE(dev)) - gen6_gt_force_wake_get(dev_priv); - /* Stop the ring if it's running. */ I915_WRITE_CTL(ring, 0); I915_WRITE_HEAD(ring, 0); @@ -322,8 +317,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_READ_HEAD(ring), I915_READ_TAIL(ring), I915_READ_START(ring)); - ret = -EIO; - goto out; + return -EIO; } if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) @@ -332,14 +326,9 @@ static int init_ring_common(struct intel_ring_buffer *ring) ring->head = I915_READ_HEAD(ring); ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; ring->space = ring_space(ring); - ring->last_retired_head = -1; } -out: - if (HAS_FORCE_WAKE(dev)) - gen6_gt_force_wake_put(dev_priv); - - return ret; + return 0; } static int @@ -998,10 +987,6 @@ static int intel_init_ring_buffer(struct drm_device *dev, if (ret) goto err_unref; - ret = i915_gem_object_set_to_gtt_domain(obj, true); - if (ret) - goto err_unpin; - ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset, ring->size); if (ring->virtual_start == NULL) { diff --git a/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c b/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c index 93e832d6c328..3c8e04f54713 100644 --- a/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/trunk/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -41,28 +41,9 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { MODULE_DEVICE_TABLE(pci, pciidlist); -static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev) -{ - struct apertures_struct *ap; - bool primary = false; - - ap = alloc_apertures(1); - ap->ranges[0].base = pci_resource_start(pdev, 0); - ap->ranges[0].size = pci_resource_len(pdev, 0); - -#ifdef CONFIG_X86 - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; -#endif - remove_conflicting_framebuffers(ap, "mgag200drmfb", primary); - kfree(ap); -} - - static int __devinit mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - mgag200_kick_out_firmware_fb(pdev); - return drm_get_pci_dev(pdev, ent, &driver); } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h index 8613cb23808c..634d222c93de 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -123,9 +123,6 @@ struct nouveau_bo { struct drm_gem_object *gem; int pin_refcnt; - - struct ttm_bo_kmap_obj dma_buf_vmap; - int vmapping_count; }; #define nouveau_bo_tile_layout(nvbo) \ diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_prime.c b/trunk/drivers/gpu/drm/nouveau/nouveau_prime.c index a89240e5fb29..c58aab7370c5 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -61,48 +61,6 @@ static void nouveau_gem_kunmap(struct dma_buf *dma_buf, unsigned long page_num, } -static int nouveau_gem_prime_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) -{ - return -EINVAL; -} - -static void *nouveau_gem_prime_vmap(struct dma_buf *dma_buf) -{ - struct nouveau_bo *nvbo = dma_buf->priv; - struct drm_device *dev = nvbo->gem->dev; - int ret; - - mutex_lock(&dev->struct_mutex); - if (nvbo->vmapping_count) { - nvbo->vmapping_count++; - goto out_unlock; - } - - ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.num_pages, - &nvbo->dma_buf_vmap); - if (ret) { - mutex_unlock(&dev->struct_mutex); - return ERR_PTR(ret); - } - nvbo->vmapping_count = 1; -out_unlock: - mutex_unlock(&dev->struct_mutex); - return nvbo->dma_buf_vmap.virtual; -} - -static void nouveau_gem_prime_vunmap(struct dma_buf *dma_buf, void *vaddr) -{ - struct nouveau_bo *nvbo = dma_buf->priv; - struct drm_device *dev = nvbo->gem->dev; - - mutex_lock(&dev->struct_mutex); - nvbo->vmapping_count--; - if (nvbo->vmapping_count == 0) { - ttm_bo_kunmap(&nvbo->dma_buf_vmap); - } - mutex_unlock(&dev->struct_mutex); -} - static const struct dma_buf_ops nouveau_dmabuf_ops = { .map_dma_buf = nouveau_gem_map_dma_buf, .unmap_dma_buf = nouveau_gem_unmap_dma_buf, @@ -111,9 +69,6 @@ static const struct dma_buf_ops nouveau_dmabuf_ops = { .kmap_atomic = nouveau_gem_kmap_atomic, .kunmap = nouveau_gem_kunmap, .kunmap_atomic = nouveau_gem_kunmap_atomic, - .mmap = nouveau_gem_prime_mmap, - .vmap = nouveau_gem_prime_vmap, - .vunmap = nouveau_gem_prime_vunmap, }; static int diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index 01550d05e273..58991af90502 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -1029,11 +1029,6 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); - if ((rdev->family == CHIP_JUNIPER) || - (rdev->family == CHIP_CYPRESS) || - (rdev->family == CHIP_HEMLOCK) || - (rdev->family == CHIP_BARTS)) - WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); } WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); @@ -1558,10 +1553,163 @@ int evergreen_cp_resume(struct radeon_device *rdev) /* * Core functions */ +static u32 evergreen_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + u32 num_tile_pipes, + u32 num_backends, + u32 backend_disable_mask) +{ + u32 backend_map = 0; + u32 enabled_backends_mask = 0; + u32 enabled_backends_count = 0; + u32 cur_pipe; + u32 swizzle_pipe[EVERGREEN_MAX_PIPES]; + u32 cur_backend = 0; + u32 i; + bool force_no_swizzle; + + if (num_tile_pipes > EVERGREEN_MAX_PIPES) + num_tile_pipes = EVERGREEN_MAX_PIPES; + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_backends > EVERGREEN_MAX_BACKENDS) + num_backends = EVERGREEN_MAX_BACKENDS; + if (num_backends < 1) + num_backends = 1; + + for (i = 0; i < EVERGREEN_MAX_BACKENDS; ++i) { + if (((backend_disable_mask >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends) + break; + } + + if (enabled_backends_count == 0) { + enabled_backends_mask = 1; + enabled_backends_count = 1; + } + + if (enabled_backends_count != num_backends) + num_backends = enabled_backends_count; + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * EVERGREEN_MAX_PIPES); + switch (rdev->family) { + case CHIP_CEDAR: + case CHIP_REDWOOD: + case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: + case CHIP_TURKS: + case CHIP_CAICOS: + force_no_swizzle = false; + break; + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + case CHIP_JUNIPER: + case CHIP_BARTS: + default: + force_no_swizzle = true; + break; + } + if (force_no_swizzle) { + bool last_backend_enabled = false; + + force_no_swizzle = false; + for (i = 0; i < EVERGREEN_MAX_BACKENDS; ++i) { + if (((enabled_backends_mask >> i) & 1) == 1) { + if (last_backend_enabled) + force_no_swizzle = true; + last_backend_enabled = true; + } else + last_backend_enabled = false; + } + } + + switch (num_tile_pipes) { + case 1: + case 3: + case 5: + case 7: + DRM_ERROR("odd number of pipes!\n"); + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + swizzle_pipe[3] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + } + break; + } + + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % EVERGREEN_MAX_BACKENDS; + + backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); + + cur_backend = (cur_backend + 1) % EVERGREEN_MAX_BACKENDS; + } + + return backend_map; +} + static void evergreen_gpu_init(struct radeon_device *rdev) { - u32 gb_addr_config; + u32 cc_rb_backend_disable = 0; + u32 cc_gc_shader_pipe_config; + u32 gb_addr_config = 0; u32 mc_shared_chmap, mc_arb_ramcfg; + u32 gb_backend_map; + u32 grbm_gfx_index; u32 sx_debug_1; u32 smx_dc_ctl0; u32 sq_config; @@ -1576,7 +1724,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) u32 sq_stack_resource_mgmt_3; u32 vgt_cache_invalidation; u32 hdp_host_path_cntl, tmp; - u32 disabled_rb_mask; int i, j, num_shader_engines, ps_thread_count; switch (rdev->family) { @@ -1601,7 +1748,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CYPRESS_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_JUNIPER: rdev->config.evergreen.num_ses = 1; @@ -1623,7 +1769,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = JUNIPER_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_REDWOOD: rdev->config.evergreen.num_ses = 1; @@ -1645,7 +1790,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_CEDAR: default: @@ -1668,7 +1812,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CEDAR_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_PALM: rdev->config.evergreen.num_ses = 1; @@ -1690,7 +1833,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CEDAR_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_SUMO: rdev->config.evergreen.num_ses = 1; @@ -1718,7 +1860,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_SUMO2: rdev->config.evergreen.num_ses = 1; @@ -1740,7 +1881,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_BARTS: rdev->config.evergreen.num_ses = 2; @@ -1762,7 +1902,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = BARTS_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_TURKS: rdev->config.evergreen.num_ses = 1; @@ -1784,7 +1923,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x100; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = TURKS_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_CAICOS: rdev->config.evergreen.num_ses = 1; @@ -1806,7 +1944,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sc_prim_fifo_size = 0x40; rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CAICOS_GB_ADDR_CONFIG_GOLDEN; break; } @@ -1823,6 +1960,20 @@ static void evergreen_gpu_init(struct radeon_device *rdev) evergreen_fix_pci_max_read_req_size(rdev); + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & ~2; + + cc_gc_shader_pipe_config |= + INACTIVE_QD_PIPES((EVERGREEN_MAX_PIPES_MASK << rdev->config.evergreen.max_pipes) + & EVERGREEN_MAX_PIPES_MASK); + cc_gc_shader_pipe_config |= + INACTIVE_SIMDS((EVERGREEN_MAX_SIMDS_MASK << rdev->config.evergreen.max_simds) + & EVERGREEN_MAX_SIMDS_MASK); + + cc_rb_backend_disable = + BACKEND_DISABLE((EVERGREEN_MAX_BACKENDS_MASK << rdev->config.evergreen.max_backends) + & EVERGREEN_MAX_BACKENDS_MASK); + + mc_shared_chmap = RREG32(MC_SHARED_CHMAP); if ((rdev->family == CHIP_PALM) || (rdev->family == CHIP_SUMO) || @@ -1831,6 +1982,134 @@ static void evergreen_gpu_init(struct radeon_device *rdev) else mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + switch (rdev->config.evergreen.max_tile_pipes) { + case 1: + default: + gb_addr_config |= NUM_PIPES(0); + break; + case 2: + gb_addr_config |= NUM_PIPES(1); + break; + case 4: + gb_addr_config |= NUM_PIPES(2); + break; + case 8: + gb_addr_config |= NUM_PIPES(3); + break; + } + + gb_addr_config |= PIPE_INTERLEAVE_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); + gb_addr_config |= BANK_INTERLEAVE_SIZE(0); + gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.evergreen.num_ses - 1); + gb_addr_config |= SHADER_ENGINE_TILE_SIZE(1); + gb_addr_config |= NUM_GPUS(0); /* Hemlock? */ + gb_addr_config |= MULTI_GPU_TILE_SIZE(2); + + if (((mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT) > 2) + gb_addr_config |= ROW_SIZE(2); + else + gb_addr_config |= ROW_SIZE((mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT); + + if (rdev->ddev->pdev->device == 0x689e) { + u32 efuse_straps_4; + u32 efuse_straps_3; + u8 efuse_box_bit_131_124; + + WREG32(RCU_IND_INDEX, 0x204); + efuse_straps_4 = RREG32(RCU_IND_DATA); + WREG32(RCU_IND_INDEX, 0x203); + efuse_straps_3 = RREG32(RCU_IND_DATA); + efuse_box_bit_131_124 = (u8)(((efuse_straps_4 & 0xf) << 4) | ((efuse_straps_3 & 0xf0000000) >> 28)); + + switch(efuse_box_bit_131_124) { + case 0x00: + gb_backend_map = 0x76543210; + break; + case 0x55: + gb_backend_map = 0x77553311; + break; + case 0x56: + gb_backend_map = 0x77553300; + break; + case 0x59: + gb_backend_map = 0x77552211; + break; + case 0x66: + gb_backend_map = 0x77443300; + break; + case 0x99: + gb_backend_map = 0x66552211; + break; + case 0x5a: + gb_backend_map = 0x77552200; + break; + case 0xaa: + gb_backend_map = 0x66442200; + break; + case 0x95: + gb_backend_map = 0x66553311; + break; + default: + DRM_ERROR("bad backend map, using default\n"); + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + break; + } + } else if (rdev->ddev->pdev->device == 0x68b9) { + u32 efuse_straps_3; + u8 efuse_box_bit_127_124; + + WREG32(RCU_IND_INDEX, 0x203); + efuse_straps_3 = RREG32(RCU_IND_DATA); + efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28); + + switch(efuse_box_bit_127_124) { + case 0x0: + gb_backend_map = 0x00003210; + break; + case 0x5: + case 0x6: + case 0x9: + case 0xa: + gb_backend_map = 0x00003311; + break; + default: + DRM_ERROR("bad backend map, using default\n"); + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + break; + } + } else { + switch (rdev->family) { + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + case CHIP_BARTS: + gb_backend_map = 0x66442200; + break; + case CHIP_JUNIPER: + gb_backend_map = 0x00002200; + break; + default: + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + } + } + /* setup tiling info dword. gb_addr_config is not adequate since it does * not have bank info, so create a custom tiling dword. * bits 3:0 num_pipes @@ -1857,54 +2136,45 @@ static void evergreen_gpu_init(struct radeon_device *rdev) /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ if (rdev->flags & RADEON_IS_IGP) rdev->config.evergreen.tile_config |= 1 << 4; - else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.evergreen.tile_config |= 1 << 4; - else - rdev->config.evergreen.tile_config |= 0 << 4; - } - rdev->config.evergreen.tile_config |= 0 << 8; + else + rdev->config.evergreen.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; + rdev->config.evergreen.tile_config |= + ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; rdev->config.evergreen.tile_config |= ((gb_addr_config & 0x30000000) >> 28) << 12; - num_shader_engines = (gb_addr_config & NUM_SHADER_ENGINES(3) >> 12) + 1; + rdev->config.evergreen.backend_map = gb_backend_map; + WREG32(GB_BACKEND_MAP, gb_backend_map); + WREG32(GB_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CONFIG, gb_addr_config); + WREG32(HDP_ADDR_CONFIG, gb_addr_config); - if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) { - u32 efuse_straps_4; - u32 efuse_straps_3; + num_shader_engines = ((RREG32(GB_ADDR_CONFIG) & NUM_SHADER_ENGINES(3)) >> 12) + 1; + grbm_gfx_index = INSTANCE_BROADCAST_WRITES; - WREG32(RCU_IND_INDEX, 0x204); - efuse_straps_4 = RREG32(RCU_IND_DATA); - WREG32(RCU_IND_INDEX, 0x203); - efuse_straps_3 = RREG32(RCU_IND_DATA); - tmp = (((efuse_straps_4 & 0xf) << 4) | - ((efuse_straps_3 & 0xf0000000) >> 28)); - } else { - tmp = 0; - for (i = (rdev->config.evergreen.num_ses - 1); i >= 0; i--) { - u32 rb_disable_bitmap; - - WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); - WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); - rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16; - tmp <<= 4; - tmp |= rb_disable_bitmap; + for (i = 0; i < rdev->config.evergreen.num_ses; i++) { + u32 rb = cc_rb_backend_disable | (0xf0 << 16); + u32 sp = cc_gc_shader_pipe_config; + u32 gfx = grbm_gfx_index | SE_INDEX(i); + + if (i == num_shader_engines) { + rb |= BACKEND_DISABLE(EVERGREEN_MAX_BACKENDS_MASK); + sp |= INACTIVE_SIMDS(EVERGREEN_MAX_SIMDS_MASK); } - } - /* enabled rb are just the one not disabled :) */ - disabled_rb_mask = tmp; - WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); - WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); + WREG32(GRBM_GFX_INDEX, gfx); + WREG32(RLC_GFX_INDEX, gfx); - WREG32(GB_ADDR_CONFIG, gb_addr_config); - WREG32(DMIF_ADDR_CONFIG, gb_addr_config); - WREG32(HDP_ADDR_CONFIG, gb_addr_config); + WREG32(CC_RB_BACKEND_DISABLE, rb); + WREG32(CC_SYS_RB_BACKEND_DISABLE, rb); + WREG32(GC_USER_RB_BACKEND_DISABLE, rb); + WREG32(CC_GC_SHADER_PIPE_CONFIG, sp); + } - tmp = gb_addr_config & NUM_PIPES_MASK; - tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends, - EVERGREEN_MAX_BACKENDS, disabled_rb_mask); - WREG32(GB_BACKEND_MAP, tmp); + grbm_gfx_index |= SE_BROADCAST_WRITES; + WREG32(GRBM_GFX_INDEX, grbm_gfx_index); + WREG32(RLC_GFX_INDEX, grbm_gfx_index); WREG32(CGTS_SYS_TCC_DISABLE, 0); WREG32(CGTS_TCC_DISABLE, 0); diff --git a/trunk/drivers/gpu/drm/radeon/evergreen_cs.c b/trunk/drivers/gpu/drm/radeon/evergreen_cs.c index c16554122ccd..4e7dd2b4843d 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen_cs.c @@ -52,7 +52,6 @@ struct evergreen_cs_track { u32 cb_color_view[12]; u32 cb_color_pitch[12]; u32 cb_color_slice[12]; - u32 cb_color_slice_idx[12]; u32 cb_color_attrib[12]; u32 cb_color_cmask_slice[8];/* unused */ u32 cb_color_fmask_slice[8];/* unused */ @@ -128,14 +127,12 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->cb_color_info[i] = 0; track->cb_color_view[i] = 0xFFFFFFFF; track->cb_color_pitch[i] = 0; - track->cb_color_slice[i] = 0xfffffff; - track->cb_color_slice_idx[i] = 0; + track->cb_color_slice[i] = 0; } track->cb_target_mask = 0xFFFFFFFF; track->cb_shader_mask = 0xFFFFFFFF; track->cb_dirty = true; - track->db_depth_slice = 0xffffffff; track->db_depth_view = 0xFFFFC000; track->db_depth_size = 0xFFFFFFFF; track->db_depth_control = 0xFFFFFFFF; @@ -253,9 +250,10 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, { struct evergreen_cs_track *track = p->track; unsigned palign, halign, tileb, slice_pt; - unsigned mtile_pr, mtile_ps, mtileb; tileb = 64 * surf->bpe * surf->nsamples; + palign = track->group_size / (8 * surf->bpe * surf->nsamples); + palign = MAX(8, palign); slice_pt = 1; if (tileb > surf->tsplit) { slice_pt = tileb / surf->tsplit; @@ -264,10 +262,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, /* macro tile width & height */ palign = (8 * surf->bankw * track->npipes) * surf->mtilea; halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; - mtileb = (palign / 8) * (halign / 8) * tileb;; - mtile_pr = surf->nbx / palign; - mtile_ps = (mtile_pr * surf->nby) / halign; - surf->layer_size = mtile_ps * mtileb * slice_pt; + surf->layer_size = surf->nbx * surf->nby * surf->bpe * slice_pt; surf->base_align = (palign / 8) * (halign / 8) * tileb; surf->palign = palign; surf->halign = halign; @@ -439,39 +434,6 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i offset += surf.layer_size * mslice; if (offset > radeon_bo_size(track->cb_color_bo[id])) { - /* old ddx are broken they allocate bo with w*h*bpp but - * program slice with ALIGN(h, 8), catch this and patch - * command stream. - */ - if (!surf.mode) { - volatile u32 *ib = p->ib.ptr; - unsigned long tmp, nby, bsize, size, min = 0; - - /* find the height the ddx wants */ - if (surf.nby > 8) { - min = surf.nby - 8; - } - bsize = radeon_bo_size(track->cb_color_bo[id]); - tmp = track->cb_color_bo_offset[id] << 8; - for (nby = surf.nby; nby > min; nby--) { - size = nby * surf.nbx * surf.bpe * surf.nsamples; - if ((tmp + size * mslice) <= bsize) { - break; - } - } - if (nby > min) { - surf.nby = nby; - slice = ((nby * surf.nbx) / 64) - 1; - if (!evergreen_surface_check(p, &surf, "cb")) { - /* check if this one works */ - tmp += surf.layer_size * mslice; - if (tmp <= bsize) { - ib[track->cb_color_slice_idx[id]] = slice; - goto old_ddx_ok; - } - } - } - } dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " "offset %d, max layer %d, bo size %ld, slice %d)\n", __func__, __LINE__, id, surf.layer_size, @@ -484,7 +446,6 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i surf.tsplit, surf.mtilea); return -EINVAL; } -old_ddx_ok: return 0; } @@ -1571,7 +1532,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR7_SLICE: tmp = (reg - CB_COLOR0_SLICE) / 0x3c; track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); - track->cb_color_slice_idx[tmp] = idx; track->cb_dirty = true; break; case CB_COLOR8_SLICE: @@ -1580,7 +1540,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR11_SLICE: tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); - track->cb_color_slice_idx[tmp] = idx; track->cb_dirty = true; break; case CB_COLOR0_ATTRIB: diff --git a/trunk/drivers/gpu/drm/radeon/evergreend.h b/trunk/drivers/gpu/drm/radeon/evergreend.h index 2773039b4902..79130bfd1d6f 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreend.h +++ b/trunk/drivers/gpu/drm/radeon/evergreend.h @@ -37,15 +37,6 @@ #define EVERGREEN_MAX_PIPES_MASK 0xFF #define EVERGREEN_MAX_LDS_NUM 0xFFFF -#define CYPRESS_GB_ADDR_CONFIG_GOLDEN 0x02011003 -#define BARTS_GB_ADDR_CONFIG_GOLDEN 0x02011003 -#define CAYMAN_GB_ADDR_CONFIG_GOLDEN 0x02011003 -#define JUNIPER_GB_ADDR_CONFIG_GOLDEN 0x02010002 -#define REDWOOD_GB_ADDR_CONFIG_GOLDEN 0x02010002 -#define TURKS_GB_ADDR_CONFIG_GOLDEN 0x02010002 -#define CEDAR_GB_ADDR_CONFIG_GOLDEN 0x02010001 -#define CAICOS_GB_ADDR_CONFIG_GOLDEN 0x02010001 - /* Registers */ #define RCU_IND_INDEX 0x100 @@ -63,7 +54,6 @@ #define BACKEND_DISABLE(x) ((x) << 16) #define GB_ADDR_CONFIG 0x98F8 #define NUM_PIPES(x) ((x) << 0) -#define NUM_PIPES_MASK 0x0000000f #define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) #define BANK_INTERLEAVE_SIZE(x) ((x) << 8) #define NUM_SHADER_ENGINES(x) ((x) << 12) @@ -462,7 +452,6 @@ #define MC_VM_MD_L1_TLB0_CNTL 0x2654 #define MC_VM_MD_L1_TLB1_CNTL 0x2658 #define MC_VM_MD_L1_TLB2_CNTL 0x265C -#define MC_VM_MD_L1_TLB3_CNTL 0x2698 #define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C #define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660 diff --git a/trunk/drivers/gpu/drm/radeon/ni.c b/trunk/drivers/gpu/drm/radeon/ni.c index 3186522a4458..ce4e7cc6c905 100644 --- a/trunk/drivers/gpu/drm/radeon/ni.c +++ b/trunk/drivers/gpu/drm/radeon/ni.c @@ -417,17 +417,215 @@ int ni_init_microcode(struct radeon_device *rdev) /* * Core functions */ +static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + u32 num_tile_pipes, + u32 num_backends_per_asic, + u32 *backend_disable_mask_per_asic, + u32 num_shader_engines) +{ + u32 backend_map = 0; + u32 enabled_backends_mask = 0; + u32 enabled_backends_count = 0; + u32 num_backends_per_se; + u32 cur_pipe; + u32 swizzle_pipe[CAYMAN_MAX_PIPES]; + u32 cur_backend = 0; + u32 i; + bool force_no_swizzle; + + /* force legal values */ + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_tile_pipes > rdev->config.cayman.max_tile_pipes) + num_tile_pipes = rdev->config.cayman.max_tile_pipes; + if (num_shader_engines < 1) + num_shader_engines = 1; + if (num_shader_engines > rdev->config.cayman.max_shader_engines) + num_shader_engines = rdev->config.cayman.max_shader_engines; + if (num_backends_per_asic < num_shader_engines) + num_backends_per_asic = num_shader_engines; + if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines)) + num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines; + + /* make sure we have the same number of backends per se */ + num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines); + /* set up the number of backends per se */ + num_backends_per_se = num_backends_per_asic / num_shader_engines; + if (num_backends_per_se > rdev->config.cayman.max_backends_per_se) { + num_backends_per_se = rdev->config.cayman.max_backends_per_se; + num_backends_per_asic = num_backends_per_se * num_shader_engines; + } + + /* create enable mask and count for enabled backends */ + for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { + if (((*backend_disable_mask_per_asic >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends_per_asic) + break; + } + + /* force the backends mask to match the current number of backends */ + if (enabled_backends_count != num_backends_per_asic) { + u32 this_backend_enabled; + u32 shader_engine; + u32 backend_per_se; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + *backend_disable_mask_per_asic = CAYMAN_MAX_BACKENDS_MASK; + for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { + /* calc the current se */ + shader_engine = i / rdev->config.cayman.max_backends_per_se; + /* calc the backend per se */ + backend_per_se = i % rdev->config.cayman.max_backends_per_se; + /* default to not enabled */ + this_backend_enabled = 0; + if ((shader_engine < num_shader_engines) && + (backend_per_se < num_backends_per_se)) + this_backend_enabled = 1; + if (this_backend_enabled) { + enabled_backends_mask |= (1 << i); + *backend_disable_mask_per_asic &= ~(1 << i); + ++enabled_backends_count; + } + } + } + + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * CAYMAN_MAX_PIPES); + switch (rdev->family) { + case CHIP_CAYMAN: + case CHIP_ARUBA: + force_no_swizzle = true; + break; + default: + force_no_swizzle = false; + break; + } + if (force_no_swizzle) { + bool last_backend_enabled = false; + + force_no_swizzle = false; + for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { + if (((enabled_backends_mask >> i) & 1) == 1) { + if (last_backend_enabled) + force_no_swizzle = true; + last_backend_enabled = true; + } else + last_backend_enabled = false; + } + } + + switch (num_tile_pipes) { + case 1: + case 3: + case 5: + case 7: + DRM_ERROR("odd number of pipes!\n"); + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + swizzle_pipe[3] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + } + break; + } + + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; + + backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); + + cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; + } + + return backend_map; +} + +static u32 cayman_get_disable_mask_per_asic(struct radeon_device *rdev, + u32 disable_mask_per_se, + u32 max_disable_mask_per_se, + u32 num_shader_engines) +{ + u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se); + u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se; + + if (num_shader_engines == 1) + return disable_mask_per_asic; + else if (num_shader_engines == 2) + return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se); + else + return 0xffffffff; +} + static void cayman_gpu_init(struct radeon_device *rdev) { + u32 cc_rb_backend_disable = 0; + u32 cc_gc_shader_pipe_config; u32 gb_addr_config = 0; u32 mc_shared_chmap, mc_arb_ramcfg; + u32 gb_backend_map; u32 cgts_tcc_disable; u32 sx_debug_1; u32 smx_dc_ctl0; + u32 gc_user_shader_pipe_config; + u32 gc_user_rb_backend_disable; + u32 cgts_user_tcc_disable; u32 cgts_sm_ctrl_reg; u32 hdp_host_path_cntl; u32 tmp; - u32 disabled_rb_mask; int i, j; switch (rdev->family) { @@ -452,7 +650,6 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.sc_prim_fifo_size = 0x100; rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = CAYMAN_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_ARUBA: default: @@ -460,28 +657,15 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.max_pipes_per_simd = 4; rdev->config.cayman.max_tile_pipes = 2; if ((rdev->pdev->device == 0x9900) || - (rdev->pdev->device == 0x9901) || - (rdev->pdev->device == 0x9905) || - (rdev->pdev->device == 0x9906) || - (rdev->pdev->device == 0x9907) || - (rdev->pdev->device == 0x9908) || - (rdev->pdev->device == 0x9909) || - (rdev->pdev->device == 0x9910) || - (rdev->pdev->device == 0x9917)) { + (rdev->pdev->device == 0x9901)) { rdev->config.cayman.max_simds_per_se = 6; rdev->config.cayman.max_backends_per_se = 2; } else if ((rdev->pdev->device == 0x9903) || - (rdev->pdev->device == 0x9904) || - (rdev->pdev->device == 0x990A) || - (rdev->pdev->device == 0x9913) || - (rdev->pdev->device == 0x9918)) { + (rdev->pdev->device == 0x9904)) { rdev->config.cayman.max_simds_per_se = 4; rdev->config.cayman.max_backends_per_se = 2; - } else if ((rdev->pdev->device == 0x9919) || - (rdev->pdev->device == 0x9990) || - (rdev->pdev->device == 0x9991) || - (rdev->pdev->device == 0x9994) || - (rdev->pdev->device == 0x99A0)) { + } else if ((rdev->pdev->device == 0x9990) || + (rdev->pdev->device == 0x9991)) { rdev->config.cayman.max_simds_per_se = 3; rdev->config.cayman.max_backends_per_se = 1; } else { @@ -503,7 +687,6 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.sc_prim_fifo_size = 0x40; rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = ARUBA_GB_ADDR_CONFIG_GOLDEN; break; } @@ -523,6 +706,39 @@ static void cayman_gpu_init(struct radeon_device *rdev) mc_shared_chmap = RREG32(MC_SHARED_CHMAP); mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); + cgts_tcc_disable = 0xffff0000; + for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++) + cgts_tcc_disable &= ~(1 << (16 + i)); + gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); + gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG); + cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); + + rdev->config.cayman.num_shader_engines = rdev->config.cayman.max_shader_engines; + tmp = ((~gc_user_shader_pipe_config) & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; + rdev->config.cayman.num_shader_pipes_per_simd = r600_count_pipe_bits(tmp); + rdev->config.cayman.num_tile_pipes = rdev->config.cayman.max_tile_pipes; + tmp = ((~gc_user_shader_pipe_config) & INACTIVE_SIMDS_MASK) >> INACTIVE_SIMDS_SHIFT; + rdev->config.cayman.num_simds_per_se = r600_count_pipe_bits(tmp); + tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; + rdev->config.cayman.num_backends_per_se = r600_count_pipe_bits(tmp); + tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; + rdev->config.cayman.backend_disable_mask_per_asic = + cayman_get_disable_mask_per_asic(rdev, tmp, CAYMAN_MAX_BACKENDS_PER_SE_MASK, + rdev->config.cayman.num_shader_engines); + rdev->config.cayman.backend_map = + cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, + rdev->config.cayman.num_backends_per_se * + rdev->config.cayman.num_shader_engines, + &rdev->config.cayman.backend_disable_mask_per_asic, + rdev->config.cayman.num_shader_engines); + tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT; + rdev->config.cayman.num_texture_channel_caches = r600_count_pipe_bits(tmp); + tmp = (mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT; + rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; + if (rdev->config.cayman.mem_max_burst_length_bytes > 512) + rdev->config.cayman.mem_max_burst_length_bytes = 512; tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; if (rdev->config.cayman.mem_row_size_in_kb > 4) @@ -532,6 +748,73 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.num_gpus = 1; rdev->config.cayman.multi_gpu_tile_size = 64; + //gb_addr_config = 0x02011003 +#if 0 + gb_addr_config = RREG32(GB_ADDR_CONFIG); +#else + gb_addr_config = 0; + switch (rdev->config.cayman.num_tile_pipes) { + case 1: + default: + gb_addr_config |= NUM_PIPES(0); + break; + case 2: + gb_addr_config |= NUM_PIPES(1); + break; + case 4: + gb_addr_config |= NUM_PIPES(2); + break; + case 8: + gb_addr_config |= NUM_PIPES(3); + break; + } + + tmp = (rdev->config.cayman.mem_max_burst_length_bytes / 256) - 1; + gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp); + gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.cayman.num_shader_engines - 1); + tmp = (rdev->config.cayman.shader_engine_tile_size / 16) - 1; + gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp); + switch (rdev->config.cayman.num_gpus) { + case 1: + default: + gb_addr_config |= NUM_GPUS(0); + break; + case 2: + gb_addr_config |= NUM_GPUS(1); + break; + case 4: + gb_addr_config |= NUM_GPUS(2); + break; + } + switch (rdev->config.cayman.multi_gpu_tile_size) { + case 16: + gb_addr_config |= MULTI_GPU_TILE_SIZE(0); + break; + case 32: + default: + gb_addr_config |= MULTI_GPU_TILE_SIZE(1); + break; + case 64: + gb_addr_config |= MULTI_GPU_TILE_SIZE(2); + break; + case 128: + gb_addr_config |= MULTI_GPU_TILE_SIZE(3); + break; + } + switch (rdev->config.cayman.mem_row_size_in_kb) { + case 1: + default: + gb_addr_config |= ROW_SIZE(0); + break; + case 2: + gb_addr_config |= ROW_SIZE(1); + break; + case 4: + gb_addr_config |= ROW_SIZE(2); + break; + } +#endif + tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; rdev->config.cayman.num_tile_pipes = (1 << tmp); tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; @@ -545,7 +828,17 @@ static void cayman_gpu_init(struct radeon_device *rdev) tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; rdev->config.cayman.mem_row_size_in_kb = 1 << tmp; - + //gb_backend_map = 0x76541032; +#if 0 + gb_backend_map = RREG32(GB_BACKEND_MAP); +#else + gb_backend_map = + cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, + rdev->config.cayman.num_backends_per_se * + rdev->config.cayman.num_shader_engines, + &rdev->config.cayman.backend_disable_mask_per_asic, + rdev->config.cayman.num_shader_engines); +#endif /* setup tiling info dword. gb_addr_config is not adequate since it does * not have bank info, so create a custom tiling dword. * bits 3:0 num_pipes @@ -573,49 +866,33 @@ static void cayman_gpu_init(struct radeon_device *rdev) /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ if (rdev->flags & RADEON_IS_IGP) rdev->config.cayman.tile_config |= 1 << 4; - else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.cayman.tile_config |= 1 << 4; - else - rdev->config.cayman.tile_config |= 0 << 4; - } + else + rdev->config.cayman.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; rdev->config.cayman.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; rdev->config.cayman.tile_config |= ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; - tmp = 0; - for (i = (rdev->config.cayman.max_shader_engines - 1); i >= 0; i--) { - u32 rb_disable_bitmap; - - WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); - WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); - rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16; - tmp <<= 4; - tmp |= rb_disable_bitmap; - } - /* enabled rb are just the one not disabled :) */ - disabled_rb_mask = tmp; - - WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); - WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); - + rdev->config.cayman.backend_map = gb_backend_map; + WREG32(GB_BACKEND_MAP, gb_backend_map); WREG32(GB_ADDR_CONFIG, gb_addr_config); WREG32(DMIF_ADDR_CONFIG, gb_addr_config); WREG32(HDP_ADDR_CONFIG, gb_addr_config); - tmp = gb_addr_config & NUM_PIPES_MASK; - tmp = r6xx_remap_render_backend(rdev, tmp, - rdev->config.cayman.max_backends_per_se * - rdev->config.cayman.max_shader_engines, - CAYMAN_MAX_BACKENDS, disabled_rb_mask); - WREG32(GB_BACKEND_MAP, tmp); + /* primary versions */ + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); - cgts_tcc_disable = 0xffff0000; - for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++) - cgts_tcc_disable &= ~(1 << (16 + i)); WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable); + + /* user versions */ + WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable); WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); diff --git a/trunk/drivers/gpu/drm/radeon/nid.h b/trunk/drivers/gpu/drm/radeon/nid.h index a0b98066e207..2aa7046ada56 100644 --- a/trunk/drivers/gpu/drm/radeon/nid.h +++ b/trunk/drivers/gpu/drm/radeon/nid.h @@ -41,9 +41,6 @@ #define CAYMAN_MAX_TCC 16 #define CAYMAN_MAX_TCC_MASK 0xFF -#define CAYMAN_GB_ADDR_CONFIG_GOLDEN 0x02011003 -#define ARUBA_GB_ADDR_CONFIG_GOLDEN 0x12010001 - #define DMIF_ADDR_CONFIG 0xBD4 #define SRBM_GFX_CNTL 0x0E44 #define RINGID(x) (((x) & 0x3) << 0) @@ -151,8 +148,6 @@ #define CGTS_SYS_TCC_DISABLE 0x3F90 #define CGTS_USER_SYS_TCC_DISABLE 0x3F94 -#define RLC_GFX_INDEX 0x3FC4 - #define CONFIG_MEMSIZE 0x5428 #define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 @@ -217,12 +212,6 @@ #define SOFT_RESET_VGT (1 << 14) #define SOFT_RESET_IA (1 << 15) -#define GRBM_GFX_INDEX 0x802C -#define INSTANCE_INDEX(x) ((x) << 0) -#define SE_INDEX(x) ((x) << 16) -#define INSTANCE_BROADCAST_WRITES (1 << 30) -#define SE_BROADCAST_WRITES (1 << 31) - #define SCRATCH_REG0 0x8500 #define SCRATCH_REG1 0x8504 #define SCRATCH_REG2 0x8508 diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index f30dc95f83b1..f388a1d73b63 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -1376,51 +1376,113 @@ int r600_asic_reset(struct radeon_device *rdev) return r600_gpu_soft_reset(rdev); } -u32 r6xx_remap_render_backend(struct radeon_device *rdev, - u32 tiling_pipe_num, - u32 max_rb_num, - u32 total_max_rb_num, - u32 disabled_rb_mask) -{ - u32 rendering_pipe_num, rb_num_width, req_rb_num; - u32 pipe_rb_ratio, pipe_rb_remain; - u32 data = 0, mask = 1 << (max_rb_num - 1); - unsigned i, j; - - /* mask out the RBs that don't exist on that asic */ - disabled_rb_mask |= (0xff << max_rb_num) & 0xff; - - rendering_pipe_num = 1 << tiling_pipe_num; - req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask); - BUG_ON(rendering_pipe_num < req_rb_num); - - pipe_rb_ratio = rendering_pipe_num / req_rb_num; - pipe_rb_remain = rendering_pipe_num - pipe_rb_ratio * req_rb_num; - - if (rdev->family <= CHIP_RV740) { - /* r6xx/r7xx */ - rb_num_width = 2; - } else { - /* eg+ */ - rb_num_width = 4; - } +static u32 r600_get_tile_pipe_to_backend_map(u32 num_tile_pipes, + u32 num_backends, + u32 backend_disable_mask) +{ + u32 backend_map = 0; + u32 enabled_backends_mask; + u32 enabled_backends_count; + u32 cur_pipe; + u32 swizzle_pipe[R6XX_MAX_PIPES]; + u32 cur_backend; + u32 i; - for (i = 0; i < max_rb_num; i++) { - if (!(mask & disabled_rb_mask)) { - for (j = 0; j < pipe_rb_ratio; j++) { - data <<= rb_num_width; - data |= max_rb_num - i - 1; - } - if (pipe_rb_remain) { - data <<= rb_num_width; - data |= max_rb_num - i - 1; - pipe_rb_remain--; - } + if (num_tile_pipes > R6XX_MAX_PIPES) + num_tile_pipes = R6XX_MAX_PIPES; + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_backends > R6XX_MAX_BACKENDS) + num_backends = R6XX_MAX_BACKENDS; + if (num_backends < 1) + num_backends = 1; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + for (i = 0; i < R6XX_MAX_BACKENDS; ++i) { + if (((backend_disable_mask >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; } - mask >>= 1; + if (enabled_backends_count == num_backends) + break; + } + + if (enabled_backends_count == 0) { + enabled_backends_mask = 1; + enabled_backends_count = 1; + } + + if (enabled_backends_count != num_backends) + num_backends = enabled_backends_count; + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R6XX_MAX_PIPES); + switch (num_tile_pipes) { + case 1: + swizzle_pipe[0] = 0; + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 3: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + break; + case 4: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + break; + case 5: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + break; + case 6: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 5; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + break; + case 7: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + break; + case 8: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + break; + } + + cur_backend = 0; + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS; + + backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); + + cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS; } - return data; + return backend_map; } int r600_count_pipe_bits(uint32_t val) @@ -1438,6 +1500,7 @@ void r600_gpu_init(struct radeon_device *rdev) { u32 tiling_config; u32 ramcfg; + u32 backend_map; u32 cc_rb_backend_disable; u32 cc_gc_shader_pipe_config; u32 tmp; @@ -1448,9 +1511,8 @@ void r600_gpu_init(struct radeon_device *rdev) u32 sq_thread_resource_mgmt = 0; u32 sq_stack_resource_mgmt_1 = 0; u32 sq_stack_resource_mgmt_2 = 0; - u32 disabled_rb_mask; - rdev->config.r600.tiling_group_size = 256; + /* FIXME: implement */ switch (rdev->family) { case CHIP_R600: rdev->config.r600.max_pipes = 4; @@ -1554,7 +1616,10 @@ void r600_gpu_init(struct radeon_device *rdev) rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); tiling_config |= GROUP_SIZE((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); - + if ((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) + rdev->config.r600.tiling_group_size = 512; + else + rdev->config.r600.tiling_group_size = 256; tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT; if (tmp > 3) { tiling_config |= ROW_TILING(3); @@ -1566,36 +1631,32 @@ void r600_gpu_init(struct radeon_device *rdev) tiling_config |= BANK_SWAPS(1); cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; - tmp = R6XX_MAX_BACKENDS - - r600_count_pipe_bits((cc_rb_backend_disable >> 16) & R6XX_MAX_BACKENDS_MASK); - if (tmp < rdev->config.r600.max_backends) { - rdev->config.r600.max_backends = tmp; - } - - cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0x00ffff00; - tmp = R6XX_MAX_PIPES - - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R6XX_MAX_PIPES_MASK); - if (tmp < rdev->config.r600.max_pipes) { - rdev->config.r600.max_pipes = tmp; - } - tmp = R6XX_MAX_SIMDS - - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK); - if (tmp < rdev->config.r600.max_simds) { - rdev->config.r600.max_simds = tmp; - } - - disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R6XX_MAX_BACKENDS_MASK; - tmp = (tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; - tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.r600.max_backends, - R6XX_MAX_BACKENDS, disabled_rb_mask); - tiling_config |= tmp << 16; - rdev->config.r600.backend_map = tmp; - + cc_rb_backend_disable |= + BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << rdev->config.r600.max_backends) & R6XX_MAX_BACKENDS_MASK); + + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; + cc_gc_shader_pipe_config |= + INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << rdev->config.r600.max_pipes) & R6XX_MAX_PIPES_MASK); + cc_gc_shader_pipe_config |= + INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << rdev->config.r600.max_simds) & R6XX_MAX_SIMDS_MASK); + + backend_map = r600_get_tile_pipe_to_backend_map(rdev->config.r600.max_tile_pipes, + (R6XX_MAX_BACKENDS - + r600_count_pipe_bits((cc_rb_backend_disable & + R6XX_MAX_BACKENDS_MASK) >> 16)), + (cc_rb_backend_disable >> 16)); rdev->config.r600.tile_config = tiling_config; + rdev->config.r600.backend_map = backend_map; + tiling_config |= BACKEND_MAP(backend_map); WREG32(GB_TILING_CONFIG, tiling_config); WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff); WREG32(HDP_TILING_CONFIG, tiling_config & 0xffff); + /* Setup pipes */ + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + tmp = R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); WREG32(VGT_OUT_DEALLOC_CNTL, (tmp * 4) & DEALLOC_DIST_MASK); WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((tmp * 4) - 2) & VTX_REUSE_DEPTH_MASK); @@ -2426,12 +2487,6 @@ int r600_startup(struct radeon_device *rdev) if (r) return r; - r = r600_audio_init(rdev); - if (r) { - DRM_ERROR("radeon: audio init failed\n"); - return r; - } - return 0; } @@ -2468,6 +2523,12 @@ int r600_resume(struct radeon_device *rdev) return r; } + r = r600_audio_init(rdev); + if (r) { + DRM_ERROR("radeon: audio resume failed\n"); + return r; + } + return r; } @@ -2577,6 +2638,9 @@ int r600_init(struct radeon_device *rdev) rdev->accel_working = false; } + r = r600_audio_init(rdev); + if (r) + return r; /* TODO error handling */ return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/r600_audio.c b/trunk/drivers/gpu/drm/radeon/r600_audio.c index 7479a5c503e4..7c4fa77f018f 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_audio.c +++ b/trunk/drivers/gpu/drm/radeon/r600_audio.c @@ -192,7 +192,6 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); int base_rate = 48000; switch (radeon_encoder->encoder_id) { @@ -218,8 +217,8 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); - /* Select DTO source */ - WREG32(0x5ac, radeon_crtc->crtc_id); + /* Some magic trigger or src sel? */ + WREG32_P(0x5ac, 0x01, ~0x77); } else { switch (dig->dig_encoder) { case 0: diff --git a/trunk/drivers/gpu/drm/radeon/r600_hdmi.c b/trunk/drivers/gpu/drm/radeon/r600_hdmi.c index 969c27529dfe..226379e00ac1 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/trunk/drivers/gpu/drm/radeon/r600_hdmi.c @@ -348,6 +348,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ + HDMI0_AUDIO_SEND_MAX_PACKETS | /* send NULL packets if no audio is available */ HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ } diff --git a/trunk/drivers/gpu/drm/radeon/r600d.h b/trunk/drivers/gpu/drm/radeon/r600d.h index a0dbf1fe6a40..15bd3b216243 100644 --- a/trunk/drivers/gpu/drm/radeon/r600d.h +++ b/trunk/drivers/gpu/drm/radeon/r600d.h @@ -219,8 +219,6 @@ #define BACKEND_MAP(x) ((x) << 16) #define GB_TILING_CONFIG 0x98F0 -#define PIPE_TILING__SHIFT 1 -#define PIPE_TILING__MASK 0x0000000e #define GC_USER_SHADER_PIPE_CONFIG 0x8954 #define INACTIVE_QD_PIPES(x) ((x) << 8) diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index fefcca55c1eb..492654f8ee74 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -346,9 +346,6 @@ struct radeon_bo { /* Constant after initialization */ struct radeon_device *rdev; struct drm_gem_object gem_base; - - struct ttm_bo_kmap_obj dma_buf_vmap; - int vmapping_count; }; #define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base) @@ -1374,9 +1371,9 @@ struct cayman_asic { struct si_asic { unsigned max_shader_engines; + unsigned max_pipes_per_simd; unsigned max_tile_pipes; - unsigned max_cu_per_sh; - unsigned max_sh_per_se; + unsigned max_simds_per_se; unsigned max_backends_per_se; unsigned max_texture_channel_caches; unsigned max_gprs; @@ -1387,6 +1384,7 @@ struct si_asic { unsigned sc_hiz_tile_fifo_size; unsigned sc_earlyz_tile_fifo_size; + unsigned num_shader_engines; unsigned num_tile_pipes; unsigned num_backends_per_se; unsigned backend_disable_mask_per_asic; @@ -1847,11 +1845,6 @@ extern struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock); extern void r600_hdmi_enable(struct drm_encoder *encoder); extern void r600_hdmi_disable(struct drm_encoder *encoder); extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode); -extern u32 r6xx_remap_render_backend(struct radeon_device *rdev, - u32 tiling_pipe_num, - u32 max_rb_num, - u32 total_max_rb_num, - u32 enabled_rb_mask); /* * evergreen functions used by radeon_encoder.c diff --git a/trunk/drivers/gpu/drm/radeon/radeon_cs.c b/trunk/drivers/gpu/drm/radeon/radeon_cs.c index 142f89462aa4..0137689ed461 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_cs.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_cs.c @@ -147,7 +147,6 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p) sync_to_ring, p->ring); } -/* XXX: note that this is called from the legacy UMS CS ioctl as well */ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) { struct drm_radeon_cs *cs = data; @@ -246,25 +245,23 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) } } - /* these are KMS only */ - if (p->rdev) { - if ((p->cs_flags & RADEON_CS_USE_VM) && - !p->rdev->vm_manager.enabled) { - DRM_ERROR("VM not active on asic!\n"); - return -EINVAL; - } - - /* we only support VM on SI+ */ - if ((p->rdev->family >= CHIP_TAHITI) && - ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { - DRM_ERROR("VM required on SI+!\n"); - return -EINVAL; - } + if ((p->cs_flags & RADEON_CS_USE_VM) && + !p->rdev->vm_manager.enabled) { + DRM_ERROR("VM not active on asic!\n"); + return -EINVAL; + } - if (radeon_cs_get_ring(p, ring, priority)) - return -EINVAL; + /* we only support VM on SI+ */ + if ((p->rdev->family >= CHIP_TAHITI) && + ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { + DRM_ERROR("VM required on SI+!\n"); + return -EINVAL; } + if (radeon_cs_get_ring(p, ring, priority)) + return -EINVAL; + + /* deal with non-vm */ if ((p->chunk_ib_idx != -1) && ((p->cs_flags & RADEON_CS_USE_VM) == 0) && diff --git a/trunk/drivers/gpu/drm/radeon/radeon_drv.c b/trunk/drivers/gpu/drm/radeon/radeon_drv.c index 03e5f5df40f1..f0bb2b543b13 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_drv.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_drv.c @@ -57,10 +57,9 @@ * 2.13.0 - virtual memory support, streamout * 2.14.0 - add evergreen tiling informations * 2.15.0 - add max_pipes query - * 2.16.0 - fix evergreen 2D tiled surface calculation */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 16 +#define KMS_DRIVER_MINOR 15 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_gart.c b/trunk/drivers/gpu/drm/radeon/radeon_gart.c index 59d44937dd9f..79db56e6c2ac 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_gart.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_gart.c @@ -476,18 +476,12 @@ int radeon_vm_bo_add(struct radeon_device *rdev, mutex_lock(&vm->mutex); if (last_pfn > vm->last_pfn) { - /* release mutex and lock in right order */ - mutex_unlock(&vm->mutex); + /* grow va space 32M by 32M */ + unsigned align = ((32 << 20) >> 12) - 1; radeon_mutex_lock(&rdev->cs_mutex); - mutex_lock(&vm->mutex); - /* and check again */ - if (last_pfn > vm->last_pfn) { - /* grow va space 32M by 32M */ - unsigned align = ((32 << 20) >> 12) - 1; - radeon_vm_unbind_locked(rdev, vm); - vm->last_pfn = (last_pfn + align) & ~align; - } + radeon_vm_unbind_locked(rdev, vm); radeon_mutex_unlock(&rdev->cs_mutex); + vm->last_pfn = (last_pfn + align) & ~align; } head = &vm->va; last_offset = 0; @@ -601,8 +595,8 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, if (bo_va == NULL) return 0; - radeon_mutex_lock(&rdev->cs_mutex); mutex_lock(&vm->mutex); + radeon_mutex_lock(&rdev->cs_mutex); radeon_vm_bo_update_pte(rdev, vm, bo, NULL); radeon_mutex_unlock(&rdev->cs_mutex); list_del(&bo_va->vm_list); @@ -647,8 +641,9 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) struct radeon_bo_va *bo_va, *tmp; int r; - radeon_mutex_lock(&rdev->cs_mutex); mutex_lock(&vm->mutex); + + radeon_mutex_lock(&rdev->cs_mutex); radeon_vm_unbind_locked(rdev, vm); radeon_mutex_unlock(&rdev->cs_mutex); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_kms.c b/trunk/drivers/gpu/drm/radeon/radeon_kms.c index 5c58d7d90cb2..f1016a5820d1 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_kms.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_kms.c @@ -273,7 +273,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) break; case RADEON_INFO_MAX_PIPES: if (rdev->family >= CHIP_TAHITI) - value = rdev->config.si.max_cu_per_sh; + value = rdev->config.si.max_pipes_per_simd; else if (rdev->family >= CHIP_CAYMAN) value = rdev->config.cayman.max_pipes_per_simd; else if (rdev->family >= CHIP_CEDAR) diff --git a/trunk/drivers/gpu/drm/radeon/radeon_prime.c b/trunk/drivers/gpu/drm/radeon/radeon_prime.c index 8ddab4c76710..b8f835d8ecb4 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_prime.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_prime.c @@ -85,47 +85,6 @@ static void radeon_gem_kunmap(struct dma_buf *dma_buf, unsigned long page_num, v } -static int radeon_gem_prime_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) -{ - return -EINVAL; -} - -static void *radeon_gem_prime_vmap(struct dma_buf *dma_buf) -{ - struct radeon_bo *bo = dma_buf->priv; - struct drm_device *dev = bo->rdev->ddev; - int ret; - - mutex_lock(&dev->struct_mutex); - if (bo->vmapping_count) { - bo->vmapping_count++; - goto out_unlock; - } - - ret = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, - &bo->dma_buf_vmap); - if (ret) { - mutex_unlock(&dev->struct_mutex); - return ERR_PTR(ret); - } - bo->vmapping_count = 1; -out_unlock: - mutex_unlock(&dev->struct_mutex); - return bo->dma_buf_vmap.virtual; -} - -static void radeon_gem_prime_vunmap(struct dma_buf *dma_buf, void *vaddr) -{ - struct radeon_bo *bo = dma_buf->priv; - struct drm_device *dev = bo->rdev->ddev; - - mutex_lock(&dev->struct_mutex); - bo->vmapping_count--; - if (bo->vmapping_count == 0) { - ttm_bo_kunmap(&bo->dma_buf_vmap); - } - mutex_unlock(&dev->struct_mutex); -} const static struct dma_buf_ops radeon_dmabuf_ops = { .map_dma_buf = radeon_gem_map_dma_buf, .unmap_dma_buf = radeon_gem_unmap_dma_buf, @@ -134,9 +93,6 @@ const static struct dma_buf_ops radeon_dmabuf_ops = { .kmap_atomic = radeon_gem_kmap_atomic, .kunmap = radeon_gem_kunmap, .kunmap_atomic = radeon_gem_kunmap_atomic, - .mmap = radeon_gem_prime_mmap, - .vmap = radeon_gem_prime_vmap, - .vunmap = radeon_gem_prime_vunmap, }; static int radeon_prime_create(struct drm_device *dev, diff --git a/trunk/drivers/gpu/drm/radeon/rs600.c b/trunk/drivers/gpu/drm/radeon/rs600.c index e95c5e61d4e2..25f9eef12c42 100644 --- a/trunk/drivers/gpu/drm/radeon/rs600.c +++ b/trunk/drivers/gpu/drm/radeon/rs600.c @@ -908,6 +908,12 @@ static int rs600_startup(struct radeon_device *rdev) return r; } + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "failed initializing audio\n"); + return r; + } + r = radeon_ib_pool_start(rdev); if (r) return r; @@ -916,12 +922,6 @@ static int rs600_startup(struct radeon_device *rdev) if (r) return r; - r = r600_audio_init(rdev); - if (r) { - dev_err(rdev->dev, "failed initializing audio\n"); - return r; - } - return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/rs690.c b/trunk/drivers/gpu/drm/radeon/rs690.c index 159b6a43fda0..3277ddecfe9f 100644 --- a/trunk/drivers/gpu/drm/radeon/rs690.c +++ b/trunk/drivers/gpu/drm/radeon/rs690.c @@ -637,6 +637,12 @@ static int rs690_startup(struct radeon_device *rdev) return r; } + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "failed initializing audio\n"); + return r; + } + r = radeon_ib_pool_start(rdev); if (r) return r; @@ -645,12 +651,6 @@ static int rs690_startup(struct radeon_device *rdev) if (r) return r; - r = r600_audio_init(rdev); - if (r) { - dev_err(rdev->dev, "failed initializing audio\n"); - return r; - } - return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index 4ad0281fdc37..c2f473bc13b8 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770.c +++ b/trunk/drivers/gpu/drm/radeon/rv770.c @@ -151,8 +151,6 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); - if (rdev->family == CHIP_RV740) - WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); @@ -365,6 +363,180 @@ void r700_cp_fini(struct radeon_device *rdev) /* * Core functions */ +static u32 r700_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + u32 num_tile_pipes, + u32 num_backends, + u32 backend_disable_mask) +{ + u32 backend_map = 0; + u32 enabled_backends_mask; + u32 enabled_backends_count; + u32 cur_pipe; + u32 swizzle_pipe[R7XX_MAX_PIPES]; + u32 cur_backend; + u32 i; + bool force_no_swizzle; + + if (num_tile_pipes > R7XX_MAX_PIPES) + num_tile_pipes = R7XX_MAX_PIPES; + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_backends > R7XX_MAX_BACKENDS) + num_backends = R7XX_MAX_BACKENDS; + if (num_backends < 1) + num_backends = 1; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + for (i = 0; i < R7XX_MAX_BACKENDS; ++i) { + if (((backend_disable_mask >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends) + break; + } + + if (enabled_backends_count == 0) { + enabled_backends_mask = 1; + enabled_backends_count = 1; + } + + if (enabled_backends_count != num_backends) + num_backends = enabled_backends_count; + + switch (rdev->family) { + case CHIP_RV770: + case CHIP_RV730: + force_no_swizzle = false; + break; + case CHIP_RV710: + case CHIP_RV740: + default: + force_no_swizzle = true; + break; + } + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES); + switch (num_tile_pipes) { + case 1: + swizzle_pipe[0] = 0; + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 3: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + } + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 3; + swizzle_pipe[3] = 1; + } + break; + case 5: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 5; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + } + break; + case 7: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + swizzle_pipe[6] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 1; + swizzle_pipe[6] = 7; + swizzle_pipe[7] = 5; + } + break; + } + + cur_backend = 0; + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; + + backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); + + cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; + } + + return backend_map; +} + static void rv770_gpu_init(struct radeon_device *rdev) { int i, j, num_qd_pipes; @@ -380,17 +552,14 @@ static void rv770_gpu_init(struct radeon_device *rdev) u32 sq_thread_resource_mgmt; u32 hdp_host_path_cntl; u32 sq_dyn_gpr_size_simd_ab_0; + u32 backend_map; u32 gb_tiling_config = 0; u32 cc_rb_backend_disable = 0; u32 cc_gc_shader_pipe_config = 0; u32 mc_arb_ramcfg; - u32 db_debug4, tmp; - u32 inactive_pipes, shader_pipe_config; - u32 disabled_rb_mask; - unsigned active_number; + u32 db_debug4; /* setup chip specs */ - rdev->config.rv770.tiling_group_size = 256; switch (rdev->family) { case CHIP_RV770: rdev->config.rv770.max_pipes = 4; @@ -501,70 +670,33 @@ static void rv770_gpu_init(struct radeon_device *rdev) /* setup tiling, simd, pipe config */ mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); - shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); - inactive_pipes = (shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; - for (i = 0, tmp = 1, active_number = 0; i < R7XX_MAX_PIPES; i++) { - if (!(inactive_pipes & tmp)) { - active_number++; - } - tmp <<= 1; - } - if (active_number == 1) { - WREG32(SPI_CONFIG_CNTL, DISABLE_INTERP_1); - } else { - WREG32(SPI_CONFIG_CNTL, 0); - } - - cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; - tmp = R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_rb_backend_disable >> 16); - if (tmp < rdev->config.rv770.max_backends) { - rdev->config.rv770.max_backends = tmp; - } - - cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; - tmp = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R7XX_MAX_PIPES_MASK); - if (tmp < rdev->config.rv770.max_pipes) { - rdev->config.rv770.max_pipes = tmp; - } - tmp = R7XX_MAX_SIMDS - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK); - if (tmp < rdev->config.rv770.max_simds) { - rdev->config.rv770.max_simds = tmp; - } - switch (rdev->config.rv770.max_tile_pipes) { case 1: default: - gb_tiling_config = PIPE_TILING(0); + gb_tiling_config |= PIPE_TILING(0); break; case 2: - gb_tiling_config = PIPE_TILING(1); + gb_tiling_config |= PIPE_TILING(1); break; case 4: - gb_tiling_config = PIPE_TILING(2); + gb_tiling_config |= PIPE_TILING(2); break; case 8: - gb_tiling_config = PIPE_TILING(3); + gb_tiling_config |= PIPE_TILING(3); break; } rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes; - disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R7XX_MAX_BACKENDS_MASK; - tmp = (gb_tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; - tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.rv770.max_backends, - R7XX_MAX_BACKENDS, disabled_rb_mask); - gb_tiling_config |= tmp << 16; - rdev->config.rv770.backend_map = tmp; - if (rdev->family == CHIP_RV770) gb_tiling_config |= BANK_TILING(1); - else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - gb_tiling_config |= BANK_TILING(1); - else - gb_tiling_config |= BANK_TILING(0); - } + else + gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3); gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); + if ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) + rdev->config.rv770.tiling_group_size = 512; + else + rdev->config.rv770.tiling_group_size = 256; if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) { gb_tiling_config |= ROW_TILING(3); gb_tiling_config |= SAMPLE_SPLIT(3); @@ -576,19 +708,47 @@ static void rv770_gpu_init(struct radeon_device *rdev) } gb_tiling_config |= BANK_SWAPS(1); + + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; + cc_rb_backend_disable |= + BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK); + + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; + cc_gc_shader_pipe_config |= + INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << rdev->config.rv770.max_pipes) & R7XX_MAX_PIPES_MASK); + cc_gc_shader_pipe_config |= + INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << rdev->config.rv770.max_simds) & R7XX_MAX_SIMDS_MASK); + + if (rdev->family == CHIP_RV740) + backend_map = 0x28; + else + backend_map = r700_get_tile_pipe_to_backend_map(rdev, + rdev->config.rv770.max_tile_pipes, + (R7XX_MAX_BACKENDS - + r600_count_pipe_bits((cc_rb_backend_disable & + R7XX_MAX_BACKENDS_MASK) >> 16)), + (cc_rb_backend_disable >> 16)); + rdev->config.rv770.tile_config = gb_tiling_config; + rdev->config.rv770.backend_map = backend_map; + gb_tiling_config |= BACKEND_MAP(backend_map); WREG32(GB_TILING_CONFIG, gb_tiling_config); WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); + WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CGTS_SYS_TCC_DISABLE, 0); WREG32(CGTS_TCC_DISABLE, 0); WREG32(CGTS_USER_SYS_TCC_DISABLE, 0); WREG32(CGTS_USER_TCC_DISABLE, 0); - - num_qd_pipes = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); + num_qd_pipes = + R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK); WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK); @@ -649,6 +809,8 @@ static void rv770_gpu_init(struct radeon_device *rdev) WREG32(VGT_NUM_INSTANCES, 1); + WREG32(SPI_CONFIG_CNTL, GPR_WRITE_PRIORITY(0)); + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4)); WREG32(CP_PERFMON_CNTL, 0); @@ -956,12 +1118,6 @@ static int rv770_startup(struct radeon_device *rdev) if (r) return r; - r = r600_audio_init(rdev); - if (r) { - DRM_ERROR("radeon: audio init failed\n"); - return r; - } - return 0; } @@ -984,6 +1140,12 @@ int rv770_resume(struct radeon_device *rdev) return r; } + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "radeon: audio init failed\n"); + return r; + } + return r; } @@ -1092,6 +1254,12 @@ int rv770_init(struct radeon_device *rdev) rdev->accel_working = false; } + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "radeon: audio init failed\n"); + return r; + } + return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/rv770d.h b/trunk/drivers/gpu/drm/radeon/rv770d.h index fdc089896011..9c549f702f2f 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770d.h +++ b/trunk/drivers/gpu/drm/radeon/rv770d.h @@ -106,13 +106,10 @@ #define BACKEND_MAP(x) ((x) << 16) #define GB_TILING_CONFIG 0x98F0 -#define PIPE_TILING__SHIFT 1 -#define PIPE_TILING__MASK 0x0000000e #define GC_USER_SHADER_PIPE_CONFIG 0x8954 #define INACTIVE_QD_PIPES(x) ((x) << 8) #define INACTIVE_QD_PIPES_MASK 0x0000FF00 -#define INACTIVE_QD_PIPES_SHIFT 8 #define INACTIVE_SIMDS(x) ((x) << 16) #define INACTIVE_SIMDS_MASK 0x00FF0000 @@ -177,7 +174,6 @@ #define MC_VM_MD_L1_TLB0_CNTL 0x2654 #define MC_VM_MD_L1_TLB1_CNTL 0x2658 #define MC_VM_MD_L1_TLB2_CNTL 0x265C -#define MC_VM_MD_L1_TLB3_CNTL 0x2698 #define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C #define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 #define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 diff --git a/trunk/drivers/gpu/drm/radeon/si.c b/trunk/drivers/gpu/drm/radeon/si.c index c7b61f16ecfd..549732e56ca9 100644 --- a/trunk/drivers/gpu/drm/radeon/si.c +++ b/trunk/drivers/gpu/drm/radeon/si.c @@ -867,6 +867,200 @@ void dce6_bandwidth_update(struct radeon_device *rdev) /* * Core functions */ +static u32 si_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + u32 num_tile_pipes, + u32 num_backends_per_asic, + u32 *backend_disable_mask_per_asic, + u32 num_shader_engines) +{ + u32 backend_map = 0; + u32 enabled_backends_mask = 0; + u32 enabled_backends_count = 0; + u32 num_backends_per_se; + u32 cur_pipe; + u32 swizzle_pipe[SI_MAX_PIPES]; + u32 cur_backend = 0; + u32 i; + bool force_no_swizzle; + + /* force legal values */ + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_tile_pipes > rdev->config.si.max_tile_pipes) + num_tile_pipes = rdev->config.si.max_tile_pipes; + if (num_shader_engines < 1) + num_shader_engines = 1; + if (num_shader_engines > rdev->config.si.max_shader_engines) + num_shader_engines = rdev->config.si.max_shader_engines; + if (num_backends_per_asic < num_shader_engines) + num_backends_per_asic = num_shader_engines; + if (num_backends_per_asic > (rdev->config.si.max_backends_per_se * num_shader_engines)) + num_backends_per_asic = rdev->config.si.max_backends_per_se * num_shader_engines; + + /* make sure we have the same number of backends per se */ + num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines); + /* set up the number of backends per se */ + num_backends_per_se = num_backends_per_asic / num_shader_engines; + if (num_backends_per_se > rdev->config.si.max_backends_per_se) { + num_backends_per_se = rdev->config.si.max_backends_per_se; + num_backends_per_asic = num_backends_per_se * num_shader_engines; + } + + /* create enable mask and count for enabled backends */ + for (i = 0; i < SI_MAX_BACKENDS; ++i) { + if (((*backend_disable_mask_per_asic >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends_per_asic) + break; + } + + /* force the backends mask to match the current number of backends */ + if (enabled_backends_count != num_backends_per_asic) { + u32 this_backend_enabled; + u32 shader_engine; + u32 backend_per_se; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + *backend_disable_mask_per_asic = SI_MAX_BACKENDS_MASK; + for (i = 0; i < SI_MAX_BACKENDS; ++i) { + /* calc the current se */ + shader_engine = i / rdev->config.si.max_backends_per_se; + /* calc the backend per se */ + backend_per_se = i % rdev->config.si.max_backends_per_se; + /* default to not enabled */ + this_backend_enabled = 0; + if ((shader_engine < num_shader_engines) && + (backend_per_se < num_backends_per_se)) + this_backend_enabled = 1; + if (this_backend_enabled) { + enabled_backends_mask |= (1 << i); + *backend_disable_mask_per_asic &= ~(1 << i); + ++enabled_backends_count; + } + } + } + + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * SI_MAX_PIPES); + switch (rdev->family) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + force_no_swizzle = true; + break; + default: + force_no_swizzle = false; + break; + } + if (force_no_swizzle) { + bool last_backend_enabled = false; + + force_no_swizzle = false; + for (i = 0; i < SI_MAX_BACKENDS; ++i) { + if (((enabled_backends_mask >> i) & 1) == 1) { + if (last_backend_enabled) + force_no_swizzle = true; + last_backend_enabled = true; + } else + last_backend_enabled = false; + } + } + + switch (num_tile_pipes) { + case 1: + case 3: + case 5: + case 7: + DRM_ERROR("odd number of pipes!\n"); + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + swizzle_pipe[3] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + } + break; + } + + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % SI_MAX_BACKENDS; + + backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); + + cur_backend = (cur_backend + 1) % SI_MAX_BACKENDS; + } + + return backend_map; +} + +static u32 si_get_disable_mask_per_asic(struct radeon_device *rdev, + u32 disable_mask_per_se, + u32 max_disable_mask_per_se, + u32 num_shader_engines) +{ + u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se); + u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se; + + if (num_shader_engines == 1) + return disable_mask_per_asic; + else if (num_shader_engines == 2) + return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se); + else + return 0xffffffff; +} + static void si_tiling_mode_table_init(struct radeon_device *rdev) { const u32 num_tile_mode_states = 32; @@ -1368,151 +1562,18 @@ static void si_tiling_mode_table_init(struct radeon_device *rdev) DRM_ERROR("unknown asic: 0x%x\n", rdev->family); } -static void si_select_se_sh(struct radeon_device *rdev, - u32 se_num, u32 sh_num) -{ - u32 data = INSTANCE_BROADCAST_WRITES; - - if ((se_num == 0xffffffff) && (sh_num == 0xffffffff)) - data = SH_BROADCAST_WRITES | SE_BROADCAST_WRITES; - else if (se_num == 0xffffffff) - data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num); - else if (sh_num == 0xffffffff) - data |= SH_BROADCAST_WRITES | SE_INDEX(se_num); - else - data |= SH_INDEX(sh_num) | SE_INDEX(se_num); - WREG32(GRBM_GFX_INDEX, data); -} - -static u32 si_create_bitmask(u32 bit_width) -{ - u32 i, mask = 0; - - for (i = 0; i < bit_width; i++) { - mask <<= 1; - mask |= 1; - } - return mask; -} - -static u32 si_get_cu_enabled(struct radeon_device *rdev, u32 cu_per_sh) -{ - u32 data, mask; - - data = RREG32(CC_GC_SHADER_ARRAY_CONFIG); - if (data & 1) - data &= INACTIVE_CUS_MASK; - else - data = 0; - data |= RREG32(GC_USER_SHADER_ARRAY_CONFIG); - - data >>= INACTIVE_CUS_SHIFT; - - mask = si_create_bitmask(cu_per_sh); - - return ~data & mask; -} - -static void si_setup_spi(struct radeon_device *rdev, - u32 se_num, u32 sh_per_se, - u32 cu_per_sh) -{ - int i, j, k; - u32 data, mask, active_cu; - - for (i = 0; i < se_num; i++) { - for (j = 0; j < sh_per_se; j++) { - si_select_se_sh(rdev, i, j); - data = RREG32(SPI_STATIC_THREAD_MGMT_3); - active_cu = si_get_cu_enabled(rdev, cu_per_sh); - - mask = 1; - for (k = 0; k < 16; k++) { - mask <<= k; - if (active_cu & mask) { - data &= ~mask; - WREG32(SPI_STATIC_THREAD_MGMT_3, data); - break; - } - } - } - } - si_select_se_sh(rdev, 0xffffffff, 0xffffffff); -} - -static u32 si_get_rb_disabled(struct radeon_device *rdev, - u32 max_rb_num, u32 se_num, - u32 sh_per_se) -{ - u32 data, mask; - - data = RREG32(CC_RB_BACKEND_DISABLE); - if (data & 1) - data &= BACKEND_DISABLE_MASK; - else - data = 0; - data |= RREG32(GC_USER_RB_BACKEND_DISABLE); - - data >>= BACKEND_DISABLE_SHIFT; - - mask = si_create_bitmask(max_rb_num / se_num / sh_per_se); - - return data & mask; -} - -static void si_setup_rb(struct radeon_device *rdev, - u32 se_num, u32 sh_per_se, - u32 max_rb_num) -{ - int i, j; - u32 data, mask; - u32 disabled_rbs = 0; - u32 enabled_rbs = 0; - - for (i = 0; i < se_num; i++) { - for (j = 0; j < sh_per_se; j++) { - si_select_se_sh(rdev, i, j); - data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se); - disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH); - } - } - si_select_se_sh(rdev, 0xffffffff, 0xffffffff); - - mask = 1; - for (i = 0; i < max_rb_num; i++) { - if (!(disabled_rbs & mask)) - enabled_rbs |= mask; - mask <<= 1; - } - - for (i = 0; i < se_num; i++) { - si_select_se_sh(rdev, i, 0xffffffff); - data = 0; - for (j = 0; j < sh_per_se; j++) { - switch (enabled_rbs & 3) { - case 1: - data |= (RASTER_CONFIG_RB_MAP_0 << (i * sh_per_se + j) * 2); - break; - case 2: - data |= (RASTER_CONFIG_RB_MAP_3 << (i * sh_per_se + j) * 2); - break; - case 3: - default: - data |= (RASTER_CONFIG_RB_MAP_2 << (i * sh_per_se + j) * 2); - break; - } - enabled_rbs >>= 2; - } - WREG32(PA_SC_RASTER_CONFIG, data); - } - si_select_se_sh(rdev, 0xffffffff, 0xffffffff); -} - static void si_gpu_init(struct radeon_device *rdev) { + u32 cc_rb_backend_disable = 0; + u32 cc_gc_shader_array_config; u32 gb_addr_config = 0; u32 mc_shared_chmap, mc_arb_ramcfg; + u32 gb_backend_map; + u32 cgts_tcc_disable; u32 sx_debug_1; + u32 gc_user_shader_array_config; + u32 gc_user_rb_backend_disable; + u32 cgts_user_tcc_disable; u32 hdp_host_path_cntl; u32 tmp; int i, j; @@ -1520,9 +1581,9 @@ static void si_gpu_init(struct radeon_device *rdev) switch (rdev->family) { case CHIP_TAHITI: rdev->config.si.max_shader_engines = 2; + rdev->config.si.max_pipes_per_simd = 4; rdev->config.si.max_tile_pipes = 12; - rdev->config.si.max_cu_per_sh = 8; - rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_simds_per_se = 8; rdev->config.si.max_backends_per_se = 4; rdev->config.si.max_texture_channel_caches = 12; rdev->config.si.max_gprs = 256; @@ -1533,13 +1594,12 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.sc_prim_fifo_size_backend = 0x100; rdev->config.si.sc_hiz_tile_fifo_size = 0x30; rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_PITCAIRN: rdev->config.si.max_shader_engines = 2; + rdev->config.si.max_pipes_per_simd = 4; rdev->config.si.max_tile_pipes = 8; - rdev->config.si.max_cu_per_sh = 5; - rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_simds_per_se = 5; rdev->config.si.max_backends_per_se = 4; rdev->config.si.max_texture_channel_caches = 8; rdev->config.si.max_gprs = 256; @@ -1550,14 +1610,13 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.sc_prim_fifo_size_backend = 0x100; rdev->config.si.sc_hiz_tile_fifo_size = 0x30; rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_VERDE: default: rdev->config.si.max_shader_engines = 1; + rdev->config.si.max_pipes_per_simd = 4; rdev->config.si.max_tile_pipes = 4; - rdev->config.si.max_cu_per_sh = 2; - rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_simds_per_se = 2; rdev->config.si.max_backends_per_se = 4; rdev->config.si.max_texture_channel_caches = 4; rdev->config.si.max_gprs = 256; @@ -1568,7 +1627,6 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.sc_prim_fifo_size_backend = 0x40; rdev->config.si.sc_hiz_tile_fifo_size = 0x30; rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = VERDE_GB_ADDR_CONFIG_GOLDEN; break; } @@ -1590,7 +1648,31 @@ static void si_gpu_init(struct radeon_device *rdev) mc_shared_chmap = RREG32(MC_SHARED_CHMAP); mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); + cc_gc_shader_array_config = RREG32(CC_GC_SHADER_ARRAY_CONFIG); + cgts_tcc_disable = 0xffff0000; + for (i = 0; i < rdev->config.si.max_texture_channel_caches; i++) + cgts_tcc_disable &= ~(1 << (16 + i)); + gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); + gc_user_shader_array_config = RREG32(GC_USER_SHADER_ARRAY_CONFIG); + cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); + + rdev->config.si.num_shader_engines = rdev->config.si.max_shader_engines; rdev->config.si.num_tile_pipes = rdev->config.si.max_tile_pipes; + tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; + rdev->config.si.num_backends_per_se = r600_count_pipe_bits(tmp); + tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; + rdev->config.si.backend_disable_mask_per_asic = + si_get_disable_mask_per_asic(rdev, tmp, SI_MAX_BACKENDS_PER_SE_MASK, + rdev->config.si.num_shader_engines); + rdev->config.si.backend_map = + si_get_tile_pipe_to_backend_map(rdev, rdev->config.si.num_tile_pipes, + rdev->config.si.num_backends_per_se * + rdev->config.si.num_shader_engines, + &rdev->config.si.backend_disable_mask_per_asic, + rdev->config.si.num_shader_engines); + tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT; + rdev->config.si.num_texture_channel_caches = r600_count_pipe_bits(tmp); rdev->config.si.mem_max_burst_length_bytes = 256; tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; rdev->config.si.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; @@ -1601,8 +1683,55 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.num_gpus = 1; rdev->config.si.multi_gpu_tile_size = 64; - /* fix up row size */ - gb_addr_config &= ~ROW_SIZE_MASK; + gb_addr_config = 0; + switch (rdev->config.si.num_tile_pipes) { + case 1: + gb_addr_config |= NUM_PIPES(0); + break; + case 2: + gb_addr_config |= NUM_PIPES(1); + break; + case 4: + gb_addr_config |= NUM_PIPES(2); + break; + case 8: + default: + gb_addr_config |= NUM_PIPES(3); + break; + } + + tmp = (rdev->config.si.mem_max_burst_length_bytes / 256) - 1; + gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp); + gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.si.num_shader_engines - 1); + tmp = (rdev->config.si.shader_engine_tile_size / 16) - 1; + gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp); + switch (rdev->config.si.num_gpus) { + case 1: + default: + gb_addr_config |= NUM_GPUS(0); + break; + case 2: + gb_addr_config |= NUM_GPUS(1); + break; + case 4: + gb_addr_config |= NUM_GPUS(2); + break; + } + switch (rdev->config.si.multi_gpu_tile_size) { + case 16: + gb_addr_config |= MULTI_GPU_TILE_SIZE(0); + break; + case 32: + default: + gb_addr_config |= MULTI_GPU_TILE_SIZE(1); + break; + case 64: + gb_addr_config |= MULTI_GPU_TILE_SIZE(2); + break; + case 128: + gb_addr_config |= MULTI_GPU_TILE_SIZE(3); + break; + } switch (rdev->config.si.mem_row_size_in_kb) { case 1: default: @@ -1616,6 +1745,26 @@ static void si_gpu_init(struct radeon_device *rdev) break; } + tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; + rdev->config.si.num_tile_pipes = (1 << tmp); + tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; + rdev->config.si.mem_max_burst_length_bytes = (tmp + 1) * 256; + tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT; + rdev->config.si.num_shader_engines = tmp + 1; + tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT; + rdev->config.si.num_gpus = tmp + 1; + tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT; + rdev->config.si.multi_gpu_tile_size = 1 << tmp; + tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; + rdev->config.si.mem_row_size_in_kb = 1 << tmp; + + gb_backend_map = + si_get_tile_pipe_to_backend_map(rdev, rdev->config.si.num_tile_pipes, + rdev->config.si.num_backends_per_se * + rdev->config.si.num_shader_engines, + &rdev->config.si.backend_disable_mask_per_asic, + rdev->config.si.num_shader_engines); + /* setup tiling info dword. gb_addr_config is not adequate since it does * not have bank info, so create a custom tiling dword. * bits 3:0 num_pipes @@ -1640,29 +1789,33 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.tile_config |= (3 << 0); break; } - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.si.tile_config |= 1 << 4; - else - rdev->config.si.tile_config |= 0 << 4; + rdev->config.si.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; rdev->config.si.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; rdev->config.si.tile_config |= ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; + rdev->config.si.backend_map = gb_backend_map; WREG32(GB_ADDR_CONFIG, gb_addr_config); WREG32(DMIF_ADDR_CONFIG, gb_addr_config); WREG32(HDP_ADDR_CONFIG, gb_addr_config); - si_tiling_mode_table_init(rdev); + /* primary versions */ + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_GC_SHADER_ARRAY_CONFIG, cc_gc_shader_array_config); - si_setup_rb(rdev, rdev->config.si.max_shader_engines, - rdev->config.si.max_sh_per_se, - rdev->config.si.max_backends_per_se); + WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); - si_setup_spi(rdev, rdev->config.si.max_shader_engines, - rdev->config.si.max_sh_per_se, - rdev->config.si.max_cu_per_sh); + /* user versions */ + WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(GC_USER_SHADER_ARRAY_CONFIG, cc_gc_shader_array_config); + WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); + + si_tiling_mode_table_init(rdev); /* set HW defaults for 3D engine */ WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | diff --git a/trunk/drivers/gpu/drm/radeon/sid.h b/trunk/drivers/gpu/drm/radeon/sid.h index db4067962868..53ea2c42dbd6 100644 --- a/trunk/drivers/gpu/drm/radeon/sid.h +++ b/trunk/drivers/gpu/drm/radeon/sid.h @@ -24,11 +24,6 @@ #ifndef SI_H #define SI_H -#define TAHITI_RB_BITMAP_WIDTH_PER_SH 2 - -#define TAHITI_GB_ADDR_CONFIG_GOLDEN 0x12011003 -#define VERDE_GB_ADDR_CONFIG_GOLDEN 0x12010002 - #define CG_MULT_THERMAL_STATUS 0x714 #define ASIC_MAX_TEMP(x) ((x) << 0) #define ASIC_MAX_TEMP_MASK 0x000001ff @@ -413,12 +408,6 @@ #define SOFT_RESET_IA (1 << 15) #define GRBM_GFX_INDEX 0x802C -#define INSTANCE_INDEX(x) ((x) << 0) -#define SH_INDEX(x) ((x) << 8) -#define SE_INDEX(x) ((x) << 16) -#define SH_BROADCAST_WRITES (1 << 29) -#define INSTANCE_BROADCAST_WRITES (1 << 30) -#define SE_BROADCAST_WRITES (1 << 31) #define GRBM_INT_CNTL 0x8060 # define RDERR_INT_ENABLE (1 << 0) @@ -491,8 +480,6 @@ #define VGT_TF_MEMORY_BASE 0x89B8 #define CC_GC_SHADER_ARRAY_CONFIG 0x89bc -#define INACTIVE_CUS_MASK 0xFFFF0000 -#define INACTIVE_CUS_SHIFT 16 #define GC_USER_SHADER_ARRAY_CONFIG 0x89c0 #define PA_CL_ENHANCE 0x8A14 @@ -701,12 +688,6 @@ #define RLC_MC_CNTL 0xC344 #define RLC_UCODE_CNTL 0xC348 -#define PA_SC_RASTER_CONFIG 0x28350 -# define RASTER_CONFIG_RB_MAP_0 0 -# define RASTER_CONFIG_RB_MAP_1 1 -# define RASTER_CONFIG_RB_MAP_2 2 -# define RASTER_CONFIG_RB_MAP_3 3 - #define VGT_EVENT_INITIATOR 0x28a90 # define SAMPLE_STREAMOUTSTATS1 (1 << 0) # define SAMPLE_STREAMOUTSTATS2 (2 << 0) diff --git a/trunk/drivers/gpu/drm/ttm/ttm_bo.c b/trunk/drivers/gpu/drm/ttm/ttm_bo.c index 36f4b28c1b90..36792bd4da77 100644 --- a/trunk/drivers/gpu/drm/ttm/ttm_bo.c +++ b/trunk/drivers/gpu/drm/ttm/ttm_bo.c @@ -1204,7 +1204,6 @@ int ttm_bo_init(struct ttm_bo_device *bdev, (*destroy)(bo); else kfree(bo); - ttm_mem_global_free(mem_glob, acc_size); return -EINVAL; } bo->destroy = destroy; @@ -1308,14 +1307,22 @@ int ttm_bo_create(struct ttm_bo_device *bdev, struct ttm_buffer_object **p_bo) { struct ttm_buffer_object *bo; + struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; size_t acc_size; int ret; + acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); + ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); + if (unlikely(ret != 0)) + return ret; + bo = kzalloc(sizeof(*bo), GFP_KERNEL); - if (unlikely(bo == NULL)) + + if (unlikely(bo == NULL)) { + ttm_mem_global_free(mem_glob, acc_size); return -ENOMEM; + } - acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, buffer_start, interruptible, persistent_swap_storage, acc_size, NULL, NULL); @@ -1827,7 +1834,6 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) spin_unlock(&glob->lru_lock); (void) ttm_bo_cleanup_refs(bo, false, false, false); kref_put(&bo->list_kref, ttm_bo_release_list); - spin_lock(&glob->lru_lock); continue; } diff --git a/trunk/drivers/gpu/drm/udl/udl_fb.c b/trunk/drivers/gpu/drm/udl/udl_fb.c index ce9a61179925..a029ee39b0c5 100644 --- a/trunk/drivers/gpu/drm/udl/udl_fb.c +++ b/trunk/drivers/gpu/drm/udl/udl_fb.c @@ -156,17 +156,8 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, if (!fb->active_16) return 0; - if (!fb->obj->vmapping) { - ret = udl_gem_vmap(fb->obj); - if (ret == -ENOMEM) { - DRM_ERROR("failed to vmap fb\n"); - return 0; - } - if (!fb->obj->vmapping) { - DRM_ERROR("failed to vmapping\n"); - return 0; - } - } + if (!fb->obj->vmapping) + udl_gem_vmap(fb->obj); start_cycles = get_cycles(); diff --git a/trunk/drivers/gpu/drm/udl/udl_gem.c b/trunk/drivers/gpu/drm/udl/udl_gem.c index 7bd65bdd15a8..97acc9c6c95b 100644 --- a/trunk/drivers/gpu/drm/udl/udl_gem.c +++ b/trunk/drivers/gpu/drm/udl/udl_gem.c @@ -180,18 +180,6 @@ int udl_gem_vmap(struct udl_gem_object *obj) int page_count = obj->base.size / PAGE_SIZE; int ret; - if (obj->base.import_attach) { - ret = dma_buf_begin_cpu_access(obj->base.import_attach->dmabuf, - 0, obj->base.size, DMA_BIDIRECTIONAL); - if (ret) - return -EINVAL; - - obj->vmapping = dma_buf_vmap(obj->base.import_attach->dmabuf); - if (!obj->vmapping) - return -ENOMEM; - return 0; - } - ret = udl_gem_get_pages(obj, GFP_KERNEL); if (ret) return ret; @@ -204,13 +192,6 @@ int udl_gem_vmap(struct udl_gem_object *obj) void udl_gem_vunmap(struct udl_gem_object *obj) { - if (obj->base.import_attach) { - dma_buf_vunmap(obj->base.import_attach->dmabuf, obj->vmapping); - dma_buf_end_cpu_access(obj->base.import_attach->dmabuf, 0, - obj->base.size, DMA_BIDIRECTIONAL); - return; - } - if (obj->vmapping) vunmap(obj->vmapping); @@ -221,12 +202,12 @@ void udl_gem_free_object(struct drm_gem_object *gem_obj) { struct udl_gem_object *obj = to_udl_bo(gem_obj); - if (obj->vmapping) - udl_gem_vunmap(obj); - if (gem_obj->import_attach) drm_prime_gem_destroy(gem_obj, obj->sg); + if (obj->vmapping) + udl_gem_vunmap(obj); + if (obj->pages) udl_gem_put_pages(obj); diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index 21ee78226560..51c9ba5cd2fb 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c @@ -66,7 +66,7 @@ static int vmw_gmr2_bind(struct vmw_private *dev_priv, cmd += sizeof(remap_cmd) / sizeof(uint32); for (i = 0; i < num_pages; ++i) { - if (VMW_PPN_SIZE <= 4) + if (VMW_PPN_SIZE > 4) *cmd = page_to_pfn(*pages++); else *((uint64_t *)cmd) = page_to_pfn(*pages++); diff --git a/trunk/drivers/gpu/vga/vga_switcheroo.c b/trunk/drivers/gpu/vga/vga_switcheroo.c index 5b3c7d135dc9..38f9534ac513 100644 --- a/trunk/drivers/gpu/vga/vga_switcheroo.c +++ b/trunk/drivers/gpu/vga/vga_switcheroo.c @@ -190,19 +190,6 @@ find_active_client(struct list_head *head) return NULL; } -int vga_switcheroo_get_client_state(struct pci_dev *pdev) -{ - struct vga_switcheroo_client *client; - - client = find_client_from_pci(&vgasr_priv.clients, pdev); - if (!client) - return VGA_SWITCHEROO_NOT_FOUND; - if (!vgasr_priv.active) - return VGA_SWITCHEROO_INIT; - return client->pwr_state; -} -EXPORT_SYMBOL(vga_switcheroo_get_client_state); - void vga_switcheroo_unregister_client(struct pci_dev *pdev) { struct vga_switcheroo_client *client; @@ -304,6 +291,8 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) vga_switchon(new_client); vga_set_default_device(new_client->pdev); + set_audio_state(new_client->id, VGA_SWITCHEROO_ON); + return 0; } @@ -319,8 +308,6 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) active->active = false; - set_audio_state(active->id, VGA_SWITCHEROO_OFF); - if (new_client->fb_info) { struct fb_event event; event.info = new_client->fb_info; @@ -334,11 +321,11 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) if (new_client->ops->reprobe) new_client->ops->reprobe(new_client->pdev); + set_audio_state(active->id, VGA_SWITCHEROO_OFF); + if (active->pwr_state == VGA_SWITCHEROO_ON) vga_switchoff(active); - set_audio_state(new_client->id, VGA_SWITCHEROO_ON); - new_client->active = true; return 0; } @@ -384,9 +371,8 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, /* pwr off the device not in use */ if (strncmp(usercmd, "OFF", 3) == 0) { list_for_each_entry(client, &vgasr_priv.clients, list) { - if (client->active || client_is_audio(client)) + if (client->active) continue; - set_audio_state(client->id, VGA_SWITCHEROO_OFF); if (client->pwr_state == VGA_SWITCHEROO_ON) vga_switchoff(client); } @@ -395,11 +381,10 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, /* pwr on the device not in use */ if (strncmp(usercmd, "ON", 2) == 0) { list_for_each_entry(client, &vgasr_priv.clients, list) { - if (client->active || client_is_audio(client)) + if (client->active) continue; if (client->pwr_state == VGA_SWITCHEROO_OFF) vga_switchon(client); - set_audio_state(client->id, VGA_SWITCHEROO_ON); } goto out; } diff --git a/trunk/drivers/i2c/muxes/Kconfig b/trunk/drivers/i2c/muxes/Kconfig index a0edd9854218..beb2491db274 100644 --- a/trunk/drivers/i2c/muxes/Kconfig +++ b/trunk/drivers/i2c/muxes/Kconfig @@ -37,16 +37,4 @@ config I2C_MUX_PCA954x This driver can also be built as a module. If so, the module will be called i2c-mux-pca954x. -config I2C_MUX_PINCTRL - tristate "pinctrl-based I2C multiplexer" - depends on PINCTRL - help - If you say yes to this option, support will be included for an I2C - multiplexer that uses the pinctrl subsystem, i.e. pin multiplexing. - This is useful for SoCs whose I2C module's signals can be routed to - different sets of pins at run-time. - - This driver can also be built as a module. If so, the module will be - called pinctrl-i2cmux. - endmenu diff --git a/trunk/drivers/i2c/muxes/Makefile b/trunk/drivers/i2c/muxes/Makefile index 76da8692afff..5826249b29ca 100644 --- a/trunk/drivers/i2c/muxes/Makefile +++ b/trunk/drivers/i2c/muxes/Makefile @@ -4,6 +4,5 @@ obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o -obj-$(CONFIG_I2C_MUX_PINCTRL) += i2c-mux-pinctrl.o ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/trunk/drivers/i2c/muxes/i2c-mux-pinctrl.c b/trunk/drivers/i2c/muxes/i2c-mux-pinctrl.c deleted file mode 100644 index 46a669763476..000000000000 --- a/trunk/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * I2C multiplexer using pinctrl API - * - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct i2c_mux_pinctrl { - struct device *dev; - struct i2c_mux_pinctrl_platform_data *pdata; - struct pinctrl *pinctrl; - struct pinctrl_state **states; - struct pinctrl_state *state_idle; - struct i2c_adapter *parent; - struct i2c_adapter **busses; -}; - -static int i2c_mux_pinctrl_select(struct i2c_adapter *adap, void *data, - u32 chan) -{ - struct i2c_mux_pinctrl *mux = data; - - return pinctrl_select_state(mux->pinctrl, mux->states[chan]); -} - -static int i2c_mux_pinctrl_deselect(struct i2c_adapter *adap, void *data, - u32 chan) -{ - struct i2c_mux_pinctrl *mux = data; - - return pinctrl_select_state(mux->pinctrl, mux->state_idle); -} - -#ifdef CONFIG_OF -static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, - struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - int num_names, i, ret; - struct device_node *adapter_np; - struct i2c_adapter *adapter; - - if (!np) - return 0; - - mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL); - if (!mux->pdata) { - dev_err(mux->dev, - "Cannot allocate i2c_mux_pinctrl_platform_data\n"); - return -ENOMEM; - } - - num_names = of_property_count_strings(np, "pinctrl-names"); - if (num_names < 0) { - dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n", - num_names); - return num_names; - } - - mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev, - sizeof(*mux->pdata->pinctrl_states) * num_names, - GFP_KERNEL); - if (!mux->pdata->pinctrl_states) { - dev_err(mux->dev, "Cannot allocate pinctrl_states\n"); - return -ENOMEM; - } - - for (i = 0; i < num_names; i++) { - ret = of_property_read_string_index(np, "pinctrl-names", i, - &mux->pdata->pinctrl_states[mux->pdata->bus_count]); - if (ret < 0) { - dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n", - ret); - return ret; - } - if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count], - "idle")) { - if (i != num_names - 1) { - dev_err(mux->dev, "idle state must be last\n"); - return -EINVAL; - } - mux->pdata->pinctrl_state_idle = "idle"; - } else { - mux->pdata->bus_count++; - } - } - - adapter_np = of_parse_phandle(np, "i2c-parent", 0); - if (!adapter_np) { - dev_err(mux->dev, "Cannot parse i2c-parent\n"); - return -ENODEV; - } - adapter = of_find_i2c_adapter_by_node(adapter_np); - if (!adapter) { - dev_err(mux->dev, "Cannot find parent bus\n"); - return -ENODEV; - } - mux->pdata->parent_bus_num = i2c_adapter_id(adapter); - put_device(&adapter->dev); - - return 0; -} -#else -static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, - struct platform_device *pdev) -{ - return 0; -} -#endif - -static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev) -{ - struct i2c_mux_pinctrl *mux; - int (*deselect)(struct i2c_adapter *, void *, u32); - int i, ret; - - mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); - if (!mux) { - dev_err(&pdev->dev, "Cannot allocate i2c_mux_pinctrl\n"); - ret = -ENOMEM; - goto err; - } - platform_set_drvdata(pdev, mux); - - mux->dev = &pdev->dev; - - mux->pdata = pdev->dev.platform_data; - if (!mux->pdata) { - ret = i2c_mux_pinctrl_parse_dt(mux, pdev); - if (ret < 0) - goto err; - } - if (!mux->pdata) { - dev_err(&pdev->dev, "Missing platform data\n"); - ret = -ENODEV; - goto err; - } - - mux->states = devm_kzalloc(&pdev->dev, - sizeof(*mux->states) * mux->pdata->bus_count, - GFP_KERNEL); - if (!mux->states) { - dev_err(&pdev->dev, "Cannot allocate states\n"); - ret = -ENOMEM; - goto err; - } - - mux->busses = devm_kzalloc(&pdev->dev, - sizeof(mux->busses) * mux->pdata->bus_count, - GFP_KERNEL); - if (!mux->states) { - dev_err(&pdev->dev, "Cannot allocate busses\n"); - ret = -ENOMEM; - goto err; - } - - mux->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(mux->pinctrl)) { - ret = PTR_ERR(mux->pinctrl); - dev_err(&pdev->dev, "Cannot get pinctrl: %d\n", ret); - goto err; - } - for (i = 0; i < mux->pdata->bus_count; i++) { - mux->states[i] = pinctrl_lookup_state(mux->pinctrl, - mux->pdata->pinctrl_states[i]); - if (IS_ERR(mux->states[i])) { - ret = PTR_ERR(mux->states[i]); - dev_err(&pdev->dev, - "Cannot look up pinctrl state %s: %d\n", - mux->pdata->pinctrl_states[i], ret); - goto err; - } - } - if (mux->pdata->pinctrl_state_idle) { - mux->state_idle = pinctrl_lookup_state(mux->pinctrl, - mux->pdata->pinctrl_state_idle); - if (IS_ERR(mux->state_idle)) { - ret = PTR_ERR(mux->state_idle); - dev_err(&pdev->dev, - "Cannot look up pinctrl state %s: %d\n", - mux->pdata->pinctrl_state_idle, ret); - goto err; - } - - deselect = i2c_mux_pinctrl_deselect; - } else { - deselect = NULL; - } - - mux->parent = i2c_get_adapter(mux->pdata->parent_bus_num); - if (!mux->parent) { - dev_err(&pdev->dev, "Parent adapter (%d) not found\n", - mux->pdata->parent_bus_num); - ret = -ENODEV; - goto err; - } - - for (i = 0; i < mux->pdata->bus_count; i++) { - u32 bus = mux->pdata->base_bus_num ? - (mux->pdata->base_bus_num + i) : 0; - - mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, - mux, bus, i, - i2c_mux_pinctrl_select, - deselect); - if (!mux->busses[i]) { - ret = -ENODEV; - dev_err(&pdev->dev, "Failed to add adapter %d\n", i); - goto err_del_adapter; - } - } - - return 0; - -err_del_adapter: - for (; i > 0; i--) - i2c_del_mux_adapter(mux->busses[i - 1]); - i2c_put_adapter(mux->parent); -err: - return ret; -} - -static int __devexit i2c_mux_pinctrl_remove(struct platform_device *pdev) -{ - struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < mux->pdata->bus_count; i++) - i2c_del_mux_adapter(mux->busses[i]); - - i2c_put_adapter(mux->parent); - - return 0; -} - -#ifdef CONFIG_OF -static const struct of_device_id i2c_mux_pinctrl_of_match[] __devinitconst = { - { .compatible = "i2c-mux-pinctrl", }, - {}, -}; -MODULE_DEVICE_TABLE(of, i2c_mux_pinctrl_of_match); -#endif - -static struct platform_driver i2c_mux_pinctrl_driver = { - .driver = { - .name = "i2c-mux-pinctrl", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(i2c_mux_pinctrl_of_match), - }, - .probe = i2c_mux_pinctrl_probe, - .remove = __devexit_p(i2c_mux_pinctrl_remove), -}; -module_platform_driver(i2c_mux_pinctrl_driver); - -MODULE_DESCRIPTION("pinctrl-based I2C multiplexer driver"); -MODULE_AUTHOR("Stephen Warren "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:i2c-mux-pinctrl"); diff --git a/trunk/drivers/ide/icside.c b/trunk/drivers/ide/icside.c index bcb507b0cfd4..8716066a2f2b 100644 --- a/trunk/drivers/ide/icside.c +++ b/trunk/drivers/ide/icside.c @@ -236,7 +236,7 @@ static const struct ide_port_ops icside_v6_no_dma_port_ops = { */ static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) { - unsigned long cycle_time = 0; + unsigned long cycle_time; int use_dma_info = 0; const u8 xfer_mode = drive->dma_mode; @@ -271,9 +271,9 @@ static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) ide_set_drivedata(drive, (void *)cycle_time); - printk(KERN_INFO "%s: %s selected (peak %luMB/s)\n", - drive->name, ide_xfer_verbose(xfer_mode), - 2000 / (cycle_time ? cycle_time : (unsigned long) -1)); + printk("%s: %s selected (peak %dMB/s)\n", drive->name, + ide_xfer_verbose(xfer_mode), + 2000 / (unsigned long)ide_get_drivedata(drive)); } static const struct ide_port_ops icside_v6_port_ops = { @@ -375,6 +375,8 @@ static const struct ide_dma_ops icside_v6_dma_ops = { .dma_test_irq = icside_dma_test_irq, .dma_lost_irq = ide_dma_lost_irq, }; +#else +#define icside_v6_dma_ops NULL #endif static int icside_dma_off_init(ide_hwif_t *hwif, const struct ide_port_info *d) @@ -454,6 +456,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) static const struct ide_port_info icside_v6_port_info __initdata = { .init_dma = icside_dma_off_init, .port_ops = &icside_v6_no_dma_port_ops, + .dma_ops = &icside_v6_dma_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, .mwdma_mask = ATA_MWDMA2, .swdma_mask = ATA_SWDMA2, @@ -515,13 +518,11 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) ecard_set_drvdata(ec, state); -#ifdef CONFIG_BLK_DEV_IDEDMA_ICS if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { d.init_dma = icside_dma_init; d.port_ops = &icside_v6_port_ops; - d.dma_ops = &icside_v6_dma_ops; - } -#endif + } else + d.dma_ops = NULL; ret = ide_host_register(host, &d, hws); if (ret) diff --git a/trunk/drivers/ide/ide-cs.c b/trunk/drivers/ide/ide-cs.c index f1e922e2479a..28e344ea514c 100644 --- a/trunk/drivers/ide/ide-cs.c +++ b/trunk/drivers/ide/ide-cs.c @@ -167,8 +167,7 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data) { int *is_kme = priv_data; - if ((pdev->resource[0]->flags & IO_DATA_PATH_WIDTH) - != IO_DATA_PATH_WIDTH_8) { + if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) { pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; } diff --git a/trunk/drivers/infiniband/hw/cxgb4/cm.c b/trunk/drivers/infiniband/hw/cxgb4/cm.c index b18870c455ad..55ab284e22f2 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/cm.c +++ b/trunk/drivers/infiniband/hw/cxgb4/cm.c @@ -1593,10 +1593,6 @@ static int import_ep(struct c4iw_ep *ep, __be32 peer_ip, struct dst_entry *dst, struct net_device *pdev; pdev = ip_dev_find(&init_net, peer_ip); - if (!pdev) { - err = -ENODEV; - goto out; - } ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, n, pdev, 0); if (!ep->l2t) diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c index 3530c41fcd1f..ee1c577238f7 100644 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ b/trunk/drivers/infiniband/hw/mlx4/main.c @@ -140,7 +140,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, props->max_mr_size = ~0ull; props->page_size_cap = dev->dev->caps.page_size_cap; props->max_qp = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps; - props->max_qp_wr = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE; + props->max_qp_wr = dev->dev->caps.max_wqes; props->max_sge = min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg); props->max_cq = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs; @@ -1084,9 +1084,12 @@ static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) int total_eqs = 0; int i, j, eq; - /* Legacy mode or comp_pool is not large enough */ - if (dev->caps.comp_pool == 0 || - dev->caps.num_ports > dev->caps.comp_pool) + /* Init eq table */ + ibdev->eq_table = NULL; + ibdev->eq_added = 0; + + /* Legacy mode? */ + if (dev->caps.comp_pool == 0) return; eq_per_port = rounddown_pow_of_two(dev->caps.comp_pool/ @@ -1132,10 +1135,7 @@ static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) { int i; - - /* no additional eqs were added */ - if (!ibdev->eq_table) - return; + int total_eqs; /* Reset the advertised EQ number */ ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors; @@ -1148,7 +1148,12 @@ static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) mlx4_release_eq(dev, ibdev->eq_table[i]); } + total_eqs = dev->caps.num_comp_vectors + ibdev->eq_added; + memset(ibdev->eq_table, 0, total_eqs * sizeof(int)); kfree(ibdev->eq_table); + + ibdev->eq_table = NULL; + ibdev->eq_added = 0; } static void *mlx4_ib_add(struct mlx4_dev *dev) diff --git a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h index ff36655d23d3..e62297cc77cc 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -44,14 +44,6 @@ #include #include -enum { - MLX4_IB_SQ_MIN_WQE_SHIFT = 6, - MLX4_IB_MAX_HEADROOM = 2048 -}; - -#define MLX4_IB_SQ_HEADROOM(shift) ((MLX4_IB_MAX_HEADROOM >> (shift)) + 1) -#define MLX4_IB_SQ_MAX_SPARE (MLX4_IB_SQ_HEADROOM(MLX4_IB_SQ_MIN_WQE_SHIFT)) - struct mlx4_ib_ucontext { struct ib_ucontext ibucontext; struct mlx4_uar uar; diff --git a/trunk/drivers/infiniband/hw/mlx4/qp.c b/trunk/drivers/infiniband/hw/mlx4/qp.c index 8d4ed24aef93..ceb33327091a 100644 --- a/trunk/drivers/infiniband/hw/mlx4/qp.c +++ b/trunk/drivers/infiniband/hw/mlx4/qp.c @@ -310,8 +310,8 @@ static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, int is_user, int has_rq, struct mlx4_ib_qp *qp) { /* Sanity check RQ size before proceeding */ - if (cap->max_recv_wr > dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE || - cap->max_recv_sge > min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg)) + if (cap->max_recv_wr > dev->dev->caps.max_wqes || + cap->max_recv_sge > dev->dev->caps.max_rq_sg) return -EINVAL; if (!has_rq) { @@ -329,17 +329,8 @@ static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, qp->rq.wqe_shift = ilog2(qp->rq.max_gs * sizeof (struct mlx4_wqe_data_seg)); } - /* leave userspace return values as they were, so as not to break ABI */ - if (is_user) { - cap->max_recv_wr = qp->rq.max_post = qp->rq.wqe_cnt; - cap->max_recv_sge = qp->rq.max_gs; - } else { - cap->max_recv_wr = qp->rq.max_post = - min(dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE, qp->rq.wqe_cnt); - cap->max_recv_sge = min(qp->rq.max_gs, - min(dev->dev->caps.max_sq_sg, - dev->dev->caps.max_rq_sg)); - } + cap->max_recv_wr = qp->rq.max_post = qp->rq.wqe_cnt; + cap->max_recv_sge = qp->rq.max_gs; return 0; } @@ -350,8 +341,8 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, int s; /* Sanity check SQ size before proceeding */ - if (cap->max_send_wr > (dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE) || - cap->max_send_sge > min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg) || + if (cap->max_send_wr > dev->dev->caps.max_wqes || + cap->max_send_sge > dev->dev->caps.max_sq_sg || cap->max_inline_data + send_wqe_overhead(type, qp->flags) + sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz) return -EINVAL; diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma.h b/trunk/drivers/infiniband/hw/ocrdma/ocrdma.h index 037f5cea85bd..85a69c958559 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -231,6 +231,7 @@ struct ocrdma_qp_hwq_info { u32 entry_size; u32 max_cnt; u32 max_wqe_idx; + u32 free_delta; u16 dbid; /* qid, where to ring the doorbell. */ u32 len; dma_addr_t pa; diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_abi.h b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_abi.h index 517ab20b727c..a411a4e3193d 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_abi.h +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_abi.h @@ -101,6 +101,8 @@ struct ocrdma_create_qp_uresp { u32 rsvd1; u32 num_wqe_allocated; u32 num_rqe_allocated; + u32 free_wqe_delta; + u32 free_rqe_delta; u32 db_sq_offset; u32 db_rq_offset; u32 db_shift; @@ -124,7 +126,8 @@ struct ocrdma_create_srq_uresp { u32 db_rq_offset; u32 db_shift; - u64 rsvd2; + u32 free_rqe_delta; + u32 rsvd2; u64 rsvd3; } __packed; diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 9343a1522977..9b204b1ba336 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -732,7 +732,7 @@ static void ocrdma_dispatch_ibevent(struct ocrdma_dev *dev, break; case OCRDMA_SRQ_LIMIT_EVENT: ib_evt.element.srq = &qp->srq->ibsrq; - ib_evt.event = IB_EVENT_SRQ_LIMIT_REACHED; + ib_evt.event = IB_EVENT_QP_LAST_WQE_REACHED; srq_event = 1; qp_event = 0; break; @@ -1990,12 +1990,19 @@ static void ocrdma_get_create_qp_rsp(struct ocrdma_create_qp_rsp *rsp, max_wqe_allocated = 1 << max_wqe_allocated; max_rqe_allocated = 1 << ((u16)rsp->max_wqe_rqe); + if (qp->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) { + qp->sq.free_delta = 0; + qp->rq.free_delta = 1; + } else + qp->sq.free_delta = 1; + qp->sq.max_cnt = max_wqe_allocated; qp->sq.max_wqe_idx = max_wqe_allocated - 1; if (!attrs->srq) { qp->rq.max_cnt = max_rqe_allocated; qp->rq.max_wqe_idx = max_rqe_allocated - 1; + qp->rq.free_delta = 1; } } diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 04fef3de6d75..a20d16eaae71 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -26,6 +26,7 @@ *******************************************************************/ #include +#include #include #include #include diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index d16d172b6b6b..e9f74d1b48f6 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -940,6 +940,8 @@ static int ocrdma_copy_qp_uresp(struct ocrdma_qp *qp, uresp.db_rq_offset = OCRDMA_DB_RQ_OFFSET; uresp.db_shift = 16; } + uresp.free_wqe_delta = qp->sq.free_delta; + uresp.free_rqe_delta = qp->rq.free_delta; if (qp->dpp_enabled) { uresp.dpp_credit = dpp_credit_lmt; @@ -1305,6 +1307,8 @@ static int ocrdma_hwq_free_cnt(struct ocrdma_qp_hwq_info *q) free_cnt = (q->max_cnt - q->head) + q->tail; else free_cnt = q->tail - q->head; + if (q->free_delta) + free_cnt -= q->free_delta; return free_cnt; } @@ -1497,6 +1501,7 @@ static int ocrdma_copy_srq_uresp(struct ocrdma_srq *srq, struct ib_udata *udata) (srq->pd->id * srq->dev->nic_info.db_page_size); uresp.db_page_size = srq->dev->nic_info.db_page_size; uresp.num_rqe_allocated = srq->rq.max_cnt; + uresp.free_rqe_delta = 1; if (srq->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) { uresp.db_rq_offset = OCRDMA_DB_GEN2_RQ1_OFFSET; uresp.db_shift = 24; diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h index 633f03d80274..e6483439f25f 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h @@ -28,6 +28,7 @@ #ifndef __OCRDMA_VERBS_H__ #define __OCRDMA_VERBS_H__ +#include int ocrdma_post_send(struct ib_qp *, struct ib_send_wr *, struct ib_send_wr **bad_wr); int ocrdma_post_recv(struct ib_qp *, struct ib_recv_wr *, diff --git a/trunk/drivers/iommu/amd_iommu.c b/trunk/drivers/iommu/amd_iommu.c index a2e418cba0ff..d90a421e9cac 100644 --- a/trunk/drivers/iommu/amd_iommu.c +++ b/trunk/drivers/iommu/amd_iommu.c @@ -547,12 +547,26 @@ static void iommu_poll_events(struct amd_iommu *iommu) spin_unlock_irqrestore(&iommu->lock, flags); } -static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw) +static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u32 head) { struct amd_iommu_fault fault; + volatile u64 *raw; + int i; INC_STATS_COUNTER(pri_requests); + raw = (u64 *)(iommu->ppr_log + head); + + /* + * Hardware bug: Interrupt may arrive before the entry is written to + * memory. If this happens we need to wait for the entry to arrive. + */ + for (i = 0; i < LOOP_TIMEOUT; ++i) { + if (PPR_REQ_TYPE(raw[0]) != 0) + break; + udelay(1); + } + if (PPR_REQ_TYPE(raw[0]) != PPR_REQ_FAULT) { pr_err_ratelimited("AMD-Vi: Unknown PPR request received\n"); return; @@ -564,6 +578,12 @@ static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw) fault.tag = PPR_TAG(raw[0]); fault.flags = PPR_FLAGS(raw[0]); + /* + * To detect the hardware bug we need to clear the entry + * to back to zero. + */ + raw[0] = raw[1] = 0; + atomic_notifier_call_chain(&ppr_notifier, 0, &fault); } @@ -575,62 +595,25 @@ static void iommu_poll_ppr_log(struct amd_iommu *iommu) if (iommu->ppr_log == NULL) return; - /* enable ppr interrupts again */ - writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); - spin_lock_irqsave(&iommu->lock, flags); head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); while (head != tail) { - volatile u64 *raw; - u64 entry[2]; - int i; - - raw = (u64 *)(iommu->ppr_log + head); - - /* - * Hardware bug: Interrupt may arrive before the entry is - * written to memory. If this happens we need to wait for the - * entry to arrive. - */ - for (i = 0; i < LOOP_TIMEOUT; ++i) { - if (PPR_REQ_TYPE(raw[0]) != 0) - break; - udelay(1); - } - - /* Avoid memcpy function-call overhead */ - entry[0] = raw[0]; - entry[1] = raw[1]; - /* - * To detect the hardware bug we need to clear the entry - * back to zero. - */ - raw[0] = raw[1] = 0UL; + /* Handle PPR entry */ + iommu_handle_ppr_entry(iommu, head); - /* Update head pointer of hardware ring-buffer */ + /* Update and refresh ring-buffer state*/ head = (head + PPR_ENTRY_SIZE) % PPR_LOG_SIZE; writel(head, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); - - /* - * Release iommu->lock because ppr-handling might need to - * re-aquire it - */ - spin_unlock_irqrestore(&iommu->lock, flags); - - /* Handle PPR entry */ - iommu_handle_ppr_entry(iommu, entry); - - spin_lock_irqsave(&iommu->lock, flags); - - /* Refresh ring-buffer information */ - head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); } + /* enable ppr interrupts again */ + writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); + spin_unlock_irqrestore(&iommu->lock, flags); } diff --git a/trunk/drivers/iommu/amd_iommu_init.c b/trunk/drivers/iommu/amd_iommu_init.c index 542024ba6dba..c56790375e0f 100644 --- a/trunk/drivers/iommu/amd_iommu_init.c +++ b/trunk/drivers/iommu/amd_iommu_init.c @@ -1029,9 +1029,6 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (!iommu->dev) return 1; - iommu->root_pdev = pci_get_bus_and_slot(iommu->dev->bus->number, - PCI_DEVFN(0, 0)); - iommu->cap_ptr = h->cap_ptr; iommu->pci_seg = h->pci_seg; iommu->mmio_phys = h->mmio_phys; @@ -1326,16 +1323,20 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) { int i, j; u32 ioc_feature_control; - struct pci_dev *pdev = iommu->root_pdev; + struct pci_dev *pdev = NULL; /* RD890 BIOSes may not have completely reconfigured the iommu */ - if (!is_rd890_iommu(iommu->dev) || !pdev) + if (!is_rd890_iommu(iommu->dev)) return; /* * First, we need to ensure that the iommu is enabled. This is * controlled by a register in the northbridge */ + pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0)); + + if (!pdev) + return; /* Select Northbridge indirect register 0x75 and enable writing */ pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7)); @@ -1345,6 +1346,8 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) if (!(ioc_feature_control & 0x1)) pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1); + pci_dev_put(pdev); + /* Restore the iommu BAR */ pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4, iommu->stored_addr_lo); diff --git a/trunk/drivers/iommu/amd_iommu_types.h b/trunk/drivers/iommu/amd_iommu_types.h index 24355559a2ad..2452f3b71736 100644 --- a/trunk/drivers/iommu/amd_iommu_types.h +++ b/trunk/drivers/iommu/amd_iommu_types.h @@ -481,9 +481,6 @@ struct amd_iommu { /* Pointer to PCI device of this IOMMU */ struct pci_dev *dev; - /* Cache pdev to root device for resume quirks */ - struct pci_dev *root_pdev; - /* physical address of MMIO space */ u64 mmio_phys; /* virtual address of MMIO space */ diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index 12b2b55c519e..04cb8c88d74b 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -379,7 +379,7 @@ config LEDS_NETXBIG config LEDS_ASIC3 bool "LED support for the HTC ASIC3" - depends on LEDS_CLASS=y + depends on LEDS_CLASS depends on MFD_ASIC3 default y help @@ -390,7 +390,7 @@ config LEDS_ASIC3 config LEDS_RENESAS_TPU bool "LED support for Renesas TPU" - depends on LEDS_CLASS=y && HAVE_CLK && GENERIC_GPIO + depends on LEDS_CLASS && HAVE_CLK && GENERIC_GPIO help This option enables build of the LED TPU platform driver, suitable to drive any TPU channel on newer Renesas SoCs. diff --git a/trunk/drivers/leds/led-class.c b/trunk/drivers/leds/led-class.c index e663e6f413e9..8ee92c81aec2 100644 --- a/trunk/drivers/leds/led-class.c +++ b/trunk/drivers/leds/led-class.c @@ -29,7 +29,7 @@ static void led_update_brightness(struct led_classdev *led_cdev) led_cdev->brightness = led_cdev->brightness_get(led_cdev); } -static ssize_t led_brightness_show(struct device *dev, +static ssize_t led_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *led_cdev = dev_get_drvdata(dev); diff --git a/trunk/drivers/leds/led-core.c b/trunk/drivers/leds/led-core.c index d65353d8d3fc..d6860043f6f9 100644 --- a/trunk/drivers/leds/led-core.c +++ b/trunk/drivers/leds/led-core.c @@ -44,6 +44,13 @@ static void led_set_software_blink(struct led_classdev *led_cdev, if (!led_cdev->blink_brightness) led_cdev->blink_brightness = led_cdev->max_brightness; + if (led_get_trigger_data(led_cdev) && + delay_on == led_cdev->blink_delay_on && + delay_off == led_cdev->blink_delay_off) + return; + + led_stop_software_blink(led_cdev); + led_cdev->blink_delay_on = delay_on; led_cdev->blink_delay_off = delay_off; diff --git a/trunk/drivers/md/dm-mpath.c b/trunk/drivers/md/dm-mpath.c index 638dae048b4f..754f38f8a692 100644 --- a/trunk/drivers/md/dm-mpath.c +++ b/trunk/drivers/md/dm-mpath.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -62,11 +61,11 @@ struct multipath { struct list_head list; struct dm_target *ti; + spinlock_t lock; + const char *hw_handler_name; char *hw_handler_params; - spinlock_t lock; - unsigned nr_priority_groups; struct list_head priority_groups; @@ -82,17 +81,16 @@ struct multipath { struct priority_group *next_pg; /* Switch to this PG if set */ unsigned repeat_count; /* I/Os left before calling PS again */ - unsigned queue_io:1; /* Must we queue all I/O? */ - unsigned queue_if_no_path:1; /* Queue I/O if last path fails? */ - unsigned saved_queue_if_no_path:1; /* Saved state during suspension */ - + unsigned queue_io; /* Must we queue all I/O? */ + unsigned queue_if_no_path; /* Queue I/O if last path fails? */ + unsigned saved_queue_if_no_path;/* Saved state during suspension */ unsigned pg_init_retries; /* Number of times to retry pg_init */ unsigned pg_init_count; /* Number of times pg_init called */ unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */ - unsigned queue_size; struct work_struct process_queued_ios; struct list_head queued_ios; + unsigned queue_size; struct work_struct trigger_event; @@ -330,18 +328,14 @@ static void __choose_pgpath(struct multipath *m, size_t nr_bytes) /* * Loop through priority groups until we find a valid path. * First time we skip PGs marked 'bypassed'. - * Second time we only try the ones we skipped, but set - * pg_init_delay_retry so we do not hammer controllers. + * Second time we only try the ones we skipped. */ do { list_for_each_entry(pg, &m->priority_groups, list) { if (pg->bypassed == bypassed) continue; - if (!__choose_path_in_pg(m, pg, nr_bytes)) { - if (!bypassed) - m->pg_init_delay_retry = 1; + if (!__choose_path_in_pg(m, pg, nr_bytes)) return; - } } } while (bypassed--); @@ -487,6 +481,9 @@ static void process_queued_ios(struct work_struct *work) spin_lock_irqsave(&m->lock, flags); + if (!m->queue_size) + goto out; + if (!m->current_pgpath) __choose_pgpath(m, 0); @@ -499,6 +496,7 @@ static void process_queued_ios(struct work_struct *work) if (m->pg_init_required && !m->pg_init_in_progress && pgpath) __pg_init_all_paths(m); +out: spin_unlock_irqrestore(&m->lock, flags); if (!must_queue) dispatch_queued_ios(m); @@ -1519,16 +1517,11 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) { - struct multipath *m = ti->private; - struct block_device *bdev; - fmode_t mode; + struct multipath *m = (struct multipath *) ti->private; + struct block_device *bdev = NULL; + fmode_t mode = 0; unsigned long flags; - int r; - -again: - bdev = NULL; - mode = 0; - r = 0; + int r = 0; spin_lock_irqsave(&m->lock, flags); @@ -1553,12 +1546,6 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) r = scsi_verify_blk_ioctl(NULL, cmd); - if (r == -EAGAIN && !fatal_signal_pending(current)) { - queue_work(kmultipathd, &m->process_queued_ios); - msleep(10); - goto again; - } - return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); } @@ -1656,7 +1643,7 @@ static int multipath_busy(struct dm_target *ti) *---------------------------------------------------------------*/ static struct target_type multipath_target = { .name = "multipath", - .version = {1, 4, 0}, + .version = {1, 3, 0}, .module = THIS_MODULE, .ctr = multipath_ctr, .dtr = multipath_dtr, diff --git a/trunk/drivers/md/dm-thin-metadata.c b/trunk/drivers/md/dm-thin-metadata.c index 3e2907f0bc46..737d38865b69 100644 --- a/trunk/drivers/md/dm-thin-metadata.c +++ b/trunk/drivers/md/dm-thin-metadata.c @@ -1082,155 +1082,31 @@ int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd, return 0; } -static int __reserve_metadata_snap(struct dm_pool_metadata *pmd) -{ - int r, inc; - struct thin_disk_superblock *disk_super; - struct dm_block *copy, *sblock; - dm_block_t held_root; - - /* - * Copy the superblock. - */ - dm_sm_inc_block(pmd->metadata_sm, THIN_SUPERBLOCK_LOCATION); - r = dm_tm_shadow_block(pmd->tm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, ©, &inc); - if (r) - return r; - - BUG_ON(!inc); - - held_root = dm_block_location(copy); - disk_super = dm_block_data(copy); - - if (le64_to_cpu(disk_super->held_root)) { - DMWARN("Pool metadata snapshot already exists: release this before taking another."); - - dm_tm_dec(pmd->tm, held_root); - dm_tm_unlock(pmd->tm, copy); - pmd->need_commit = 1; - - return -EBUSY; - } - - /* - * Wipe the spacemap since we're not publishing this. - */ - memset(&disk_super->data_space_map_root, 0, - sizeof(disk_super->data_space_map_root)); - memset(&disk_super->metadata_space_map_root, 0, - sizeof(disk_super->metadata_space_map_root)); - - /* - * Increment the data structures that need to be preserved. - */ - dm_tm_inc(pmd->tm, le64_to_cpu(disk_super->data_mapping_root)); - dm_tm_inc(pmd->tm, le64_to_cpu(disk_super->device_details_root)); - dm_tm_unlock(pmd->tm, copy); - - /* - * Write the held root into the superblock. - */ - r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, &sblock); - if (r) { - dm_tm_dec(pmd->tm, held_root); - pmd->need_commit = 1; - return r; - } - - disk_super = dm_block_data(sblock); - disk_super->held_root = cpu_to_le64(held_root); - dm_bm_unlock(sblock); - - pmd->need_commit = 1; - - return 0; -} - -int dm_pool_reserve_metadata_snap(struct dm_pool_metadata *pmd) -{ - int r; - - down_write(&pmd->root_lock); - r = __reserve_metadata_snap(pmd); - up_write(&pmd->root_lock); - - return r; -} - -static int __release_metadata_snap(struct dm_pool_metadata *pmd) +static int __get_held_metadata_root(struct dm_pool_metadata *pmd, + dm_block_t *result) { int r; struct thin_disk_superblock *disk_super; - struct dm_block *sblock, *copy; - dm_block_t held_root; + struct dm_block *sblock; r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, &sb_validator, &sblock); if (r) return r; - disk_super = dm_block_data(sblock); - held_root = le64_to_cpu(disk_super->held_root); - disk_super->held_root = cpu_to_le64(0); - pmd->need_commit = 1; - - dm_bm_unlock(sblock); - - if (!held_root) { - DMWARN("No pool metadata snapshot found: nothing to release."); - return -EINVAL; - } - - r = dm_tm_read_lock(pmd->tm, held_root, &sb_validator, ©); - if (r) - return r; - - disk_super = dm_block_data(copy); - dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->data_mapping_root)); - dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->device_details_root)); - dm_sm_dec_block(pmd->metadata_sm, held_root); - - return dm_tm_unlock(pmd->tm, copy); -} - -int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd) -{ - int r; - - down_write(&pmd->root_lock); - r = __release_metadata_snap(pmd); - up_write(&pmd->root_lock); - - return r; -} - -static int __get_metadata_snap(struct dm_pool_metadata *pmd, - dm_block_t *result) -{ - int r; - struct thin_disk_superblock *disk_super; - struct dm_block *sblock; - - r = dm_bm_read_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, &sblock); - if (r) - return r; - disk_super = dm_block_data(sblock); *result = le64_to_cpu(disk_super->held_root); return dm_bm_unlock(sblock); } -int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd, - dm_block_t *result) +int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd, + dm_block_t *result) { int r; down_read(&pmd->root_lock); - r = __get_metadata_snap(pmd, result); + r = __get_held_metadata_root(pmd, result); up_read(&pmd->root_lock); return r; diff --git a/trunk/drivers/md/dm-thin-metadata.h b/trunk/drivers/md/dm-thin-metadata.h index b88918ccdaf6..ed4725e67c96 100644 --- a/trunk/drivers/md/dm-thin-metadata.h +++ b/trunk/drivers/md/dm-thin-metadata.h @@ -90,18 +90,11 @@ int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd, /* * Hold/get root for userspace transaction. - * - * The metadata snapshot is a copy of the current superblock (minus the - * space maps). Userland can access the data structures for READ - * operations only. A small performance hit is incurred by providing this - * copy of the metadata to userland due to extra copy-on-write operations - * on the metadata nodes. Release this as soon as you finish with it. */ -int dm_pool_reserve_metadata_snap(struct dm_pool_metadata *pmd); -int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd); +int dm_pool_hold_metadata_root(struct dm_pool_metadata *pmd); -int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd, - dm_block_t *result); +int dm_pool_get_held_metadata_root(struct dm_pool_metadata *pmd, + dm_block_t *result); /* * Actions on a single virtual device. diff --git a/trunk/drivers/md/dm-thin.c b/trunk/drivers/md/dm-thin.c index 37fdaf81bd1f..eb3d138ff55a 100644 --- a/trunk/drivers/md/dm-thin.c +++ b/trunk/drivers/md/dm-thin.c @@ -111,7 +111,7 @@ struct cell_key { dm_block_t block; }; -struct dm_bio_prison_cell { +struct cell { struct hlist_node list; struct bio_prison *prison; struct cell_key key; @@ -141,8 +141,6 @@ static uint32_t calc_nr_buckets(unsigned nr_cells) return n; } -static struct kmem_cache *_cell_cache; - /* * @nr_cells should be the number of cells you want in use _concurrently_. * Don't confuse it with the number of distinct keys. @@ -159,7 +157,8 @@ static struct bio_prison *prison_create(unsigned nr_cells) return NULL; spin_lock_init(&prison->lock); - prison->cell_pool = mempool_create_slab_pool(nr_cells, _cell_cache); + prison->cell_pool = mempool_create_kmalloc_pool(nr_cells, + sizeof(struct cell)); if (!prison->cell_pool) { kfree(prison); return NULL; @@ -195,10 +194,10 @@ static int keys_equal(struct cell_key *lhs, struct cell_key *rhs) (lhs->block == rhs->block); } -static struct dm_bio_prison_cell *__search_bucket(struct hlist_head *bucket, - struct cell_key *key) +static struct cell *__search_bucket(struct hlist_head *bucket, + struct cell_key *key) { - struct dm_bio_prison_cell *cell; + struct cell *cell; struct hlist_node *tmp; hlist_for_each_entry(cell, tmp, bucket, list) @@ -215,12 +214,12 @@ static struct dm_bio_prison_cell *__search_bucket(struct hlist_head *bucket, * Returns 1 if the cell was already held, 0 if @inmate is the new holder. */ static int bio_detain(struct bio_prison *prison, struct cell_key *key, - struct bio *inmate, struct dm_bio_prison_cell **ref) + struct bio *inmate, struct cell **ref) { int r = 1; unsigned long flags; uint32_t hash = hash_key(prison, key); - struct dm_bio_prison_cell *cell, *cell2; + struct cell *cell, *cell2; BUG_ON(hash > prison->nr_buckets); @@ -274,7 +273,7 @@ static int bio_detain(struct bio_prison *prison, struct cell_key *key, /* * @inmates must have been initialised prior to this call */ -static void __cell_release(struct dm_bio_prison_cell *cell, struct bio_list *inmates) +static void __cell_release(struct cell *cell, struct bio_list *inmates) { struct bio_prison *prison = cell->prison; @@ -288,7 +287,7 @@ static void __cell_release(struct dm_bio_prison_cell *cell, struct bio_list *inm mempool_free(cell, prison->cell_pool); } -static void cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios) +static void cell_release(struct cell *cell, struct bio_list *bios) { unsigned long flags; struct bio_prison *prison = cell->prison; @@ -304,7 +303,7 @@ static void cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios) * bio may be in the cell. This function releases the cell, and also does * a sanity check. */ -static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) +static void __cell_release_singleton(struct cell *cell, struct bio *bio) { BUG_ON(cell->holder != bio); BUG_ON(!bio_list_empty(&cell->bios)); @@ -312,7 +311,7 @@ static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio __cell_release(cell, NULL); } -static void cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) +static void cell_release_singleton(struct cell *cell, struct bio *bio) { unsigned long flags; struct bio_prison *prison = cell->prison; @@ -325,8 +324,7 @@ static void cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio * /* * Sometimes we don't want the holder, just the additional bios. */ -static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, - struct bio_list *inmates) +static void __cell_release_no_holder(struct cell *cell, struct bio_list *inmates) { struct bio_prison *prison = cell->prison; @@ -336,8 +334,7 @@ static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, mempool_free(cell, prison->cell_pool); } -static void cell_release_no_holder(struct dm_bio_prison_cell *cell, - struct bio_list *inmates) +static void cell_release_no_holder(struct cell *cell, struct bio_list *inmates) { unsigned long flags; struct bio_prison *prison = cell->prison; @@ -347,7 +344,7 @@ static void cell_release_no_holder(struct dm_bio_prison_cell *cell, spin_unlock_irqrestore(&prison->lock, flags); } -static void cell_error(struct dm_bio_prison_cell *cell) +static void cell_error(struct cell *cell) { struct bio_prison *prison = cell->prison; struct bio_list bios; @@ -494,7 +491,7 @@ static void build_virtual_key(struct dm_thin_device *td, dm_block_t b, * also provides the interface for creating and destroying internal * devices. */ -struct dm_thin_new_mapping; +struct new_mapping; struct pool_features { unsigned zero_new_blocks:1; @@ -540,7 +537,7 @@ struct pool { struct deferred_set shared_read_ds; struct deferred_set all_io_ds; - struct dm_thin_new_mapping *next_mapping; + struct new_mapping *next_mapping; mempool_t *mapping_pool; mempool_t *endio_hook_pool; }; @@ -633,11 +630,11 @@ static struct pool *__pool_table_lookup_metadata_dev(struct block_device *md_dev /*----------------------------------------------------------------*/ -struct dm_thin_endio_hook { +struct endio_hook { struct thin_c *tc; struct deferred_entry *shared_read_entry; struct deferred_entry *all_io_entry; - struct dm_thin_new_mapping *overwrite_mapping; + struct new_mapping *overwrite_mapping; }; static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) @@ -650,8 +647,7 @@ static void __requeue_bio_list(struct thin_c *tc, struct bio_list *master) bio_list_init(master); while ((bio = bio_list_pop(&bios))) { - struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; - + struct endio_hook *h = dm_get_mapinfo(bio)->ptr; if (h->tc == tc) bio_endio(bio, DM_ENDIO_REQUEUE); else @@ -740,7 +736,7 @@ static void wake_worker(struct pool *pool) /* * Bio endio functions. */ -struct dm_thin_new_mapping { +struct new_mapping { struct list_head list; unsigned quiesced:1; @@ -750,7 +746,7 @@ struct dm_thin_new_mapping { struct thin_c *tc; dm_block_t virt_block; dm_block_t data_block; - struct dm_bio_prison_cell *cell, *cell2; + struct cell *cell, *cell2; int err; /* @@ -763,7 +759,7 @@ struct dm_thin_new_mapping { bio_end_io_t *saved_bi_end_io; }; -static void __maybe_add_mapping(struct dm_thin_new_mapping *m) +static void __maybe_add_mapping(struct new_mapping *m) { struct pool *pool = m->tc->pool; @@ -776,7 +772,7 @@ static void __maybe_add_mapping(struct dm_thin_new_mapping *m) static void copy_complete(int read_err, unsigned long write_err, void *context) { unsigned long flags; - struct dm_thin_new_mapping *m = context; + struct new_mapping *m = context; struct pool *pool = m->tc->pool; m->err = read_err || write_err ? -EIO : 0; @@ -790,8 +786,8 @@ static void copy_complete(int read_err, unsigned long write_err, void *context) static void overwrite_endio(struct bio *bio, int err) { unsigned long flags; - struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; - struct dm_thin_new_mapping *m = h->overwrite_mapping; + struct endio_hook *h = dm_get_mapinfo(bio)->ptr; + struct new_mapping *m = h->overwrite_mapping; struct pool *pool = m->tc->pool; m->err = err; @@ -815,7 +811,7 @@ static void overwrite_endio(struct bio *bio, int err) /* * This sends the bios in the cell back to the deferred_bios list. */ -static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell, +static void cell_defer(struct thin_c *tc, struct cell *cell, dm_block_t data_block) { struct pool *pool = tc->pool; @@ -832,7 +828,7 @@ static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell, * Same as cell_defer above, except it omits one particular detainee, * a write bio that covers the block and has already been processed. */ -static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell) +static void cell_defer_except(struct thin_c *tc, struct cell *cell) { struct bio_list bios; struct pool *pool = tc->pool; @@ -847,7 +843,7 @@ static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell wake_worker(pool); } -static void process_prepared_mapping(struct dm_thin_new_mapping *m) +static void process_prepared_mapping(struct new_mapping *m) { struct thin_c *tc = m->tc; struct bio *bio; @@ -890,7 +886,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) mempool_free(m, tc->pool->mapping_pool); } -static void process_prepared_discard(struct dm_thin_new_mapping *m) +static void process_prepared_discard(struct new_mapping *m) { int r; struct thin_c *tc = m->tc; @@ -913,11 +909,11 @@ static void process_prepared_discard(struct dm_thin_new_mapping *m) } static void process_prepared(struct pool *pool, struct list_head *head, - void (*fn)(struct dm_thin_new_mapping *)) + void (*fn)(struct new_mapping *)) { unsigned long flags; struct list_head maps; - struct dm_thin_new_mapping *m, *tmp; + struct new_mapping *m, *tmp; INIT_LIST_HEAD(&maps); spin_lock_irqsave(&pool->lock, flags); @@ -961,9 +957,9 @@ static int ensure_next_mapping(struct pool *pool) return pool->next_mapping ? 0 : -ENOMEM; } -static struct dm_thin_new_mapping *get_next_mapping(struct pool *pool) +static struct new_mapping *get_next_mapping(struct pool *pool) { - struct dm_thin_new_mapping *r = pool->next_mapping; + struct new_mapping *r = pool->next_mapping; BUG_ON(!pool->next_mapping); @@ -975,11 +971,11 @@ static struct dm_thin_new_mapping *get_next_mapping(struct pool *pool) static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, struct dm_dev *origin, dm_block_t data_origin, dm_block_t data_dest, - struct dm_bio_prison_cell *cell, struct bio *bio) + struct cell *cell, struct bio *bio) { int r; struct pool *pool = tc->pool; - struct dm_thin_new_mapping *m = get_next_mapping(pool); + struct new_mapping *m = get_next_mapping(pool); INIT_LIST_HEAD(&m->list); m->quiesced = 0; @@ -1001,8 +997,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, * bio immediately. Otherwise we use kcopyd to clone the data first. */ if (io_overwrites_block(pool, bio)) { - struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; - + struct endio_hook *h = dm_get_mapinfo(bio)->ptr; h->overwrite_mapping = m; m->bio = bio; save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); @@ -1030,7 +1025,7 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block, static void schedule_internal_copy(struct thin_c *tc, dm_block_t virt_block, dm_block_t data_origin, dm_block_t data_dest, - struct dm_bio_prison_cell *cell, struct bio *bio) + struct cell *cell, struct bio *bio) { schedule_copy(tc, virt_block, tc->pool_dev, data_origin, data_dest, cell, bio); @@ -1038,18 +1033,18 @@ static void schedule_internal_copy(struct thin_c *tc, dm_block_t virt_block, static void schedule_external_copy(struct thin_c *tc, dm_block_t virt_block, dm_block_t data_dest, - struct dm_bio_prison_cell *cell, struct bio *bio) + struct cell *cell, struct bio *bio) { schedule_copy(tc, virt_block, tc->origin_dev, virt_block, data_dest, cell, bio); } static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, - dm_block_t data_block, struct dm_bio_prison_cell *cell, + dm_block_t data_block, struct cell *cell, struct bio *bio) { struct pool *pool = tc->pool; - struct dm_thin_new_mapping *m = get_next_mapping(pool); + struct new_mapping *m = get_next_mapping(pool); INIT_LIST_HEAD(&m->list); m->quiesced = 1; @@ -1070,12 +1065,12 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, process_prepared_mapping(m); else if (io_overwrites_block(pool, bio)) { - struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; - + struct endio_hook *h = dm_get_mapinfo(bio)->ptr; h->overwrite_mapping = m; m->bio = bio; save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); remap_and_issue(tc, bio, data_block); + } else { int r; struct dm_io_region to; @@ -1160,7 +1155,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) */ static void retry_on_resume(struct bio *bio) { - struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; + struct endio_hook *h = dm_get_mapinfo(bio)->ptr; struct thin_c *tc = h->tc; struct pool *pool = tc->pool; unsigned long flags; @@ -1170,7 +1165,7 @@ static void retry_on_resume(struct bio *bio) spin_unlock_irqrestore(&pool->lock, flags); } -static void no_space(struct dm_bio_prison_cell *cell) +static void no_space(struct cell *cell) { struct bio *bio; struct bio_list bios; @@ -1187,11 +1182,11 @@ static void process_discard(struct thin_c *tc, struct bio *bio) int r; unsigned long flags; struct pool *pool = tc->pool; - struct dm_bio_prison_cell *cell, *cell2; + struct cell *cell, *cell2; struct cell_key key, key2; dm_block_t block = get_bio_block(tc, bio); struct dm_thin_lookup_result lookup_result; - struct dm_thin_new_mapping *m; + struct new_mapping *m; build_virtual_key(tc->td, block, &key); if (bio_detain(tc->pool->prison, &key, bio, &cell)) @@ -1268,7 +1263,7 @@ static void process_discard(struct thin_c *tc, struct bio *bio) static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block, struct cell_key *key, struct dm_thin_lookup_result *lookup_result, - struct dm_bio_prison_cell *cell) + struct cell *cell) { int r; dm_block_t data_block; @@ -1295,7 +1290,7 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio, dm_block_t block, struct dm_thin_lookup_result *lookup_result) { - struct dm_bio_prison_cell *cell; + struct cell *cell; struct pool *pool = tc->pool; struct cell_key key; @@ -1310,7 +1305,7 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio, if (bio_data_dir(bio) == WRITE) break_sharing(tc, bio, block, &key, lookup_result, cell); else { - struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; + struct endio_hook *h = dm_get_mapinfo(bio)->ptr; h->shared_read_entry = ds_inc(&pool->shared_read_ds); @@ -1320,7 +1315,7 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio, } static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block, - struct dm_bio_prison_cell *cell) + struct cell *cell) { int r; dm_block_t data_block; @@ -1368,7 +1363,7 @@ static void process_bio(struct thin_c *tc, struct bio *bio) { int r; dm_block_t block = get_bio_block(tc, bio); - struct dm_bio_prison_cell *cell; + struct cell *cell; struct cell_key key; struct dm_thin_lookup_result lookup_result; @@ -1437,7 +1432,7 @@ static void process_deferred_bios(struct pool *pool) spin_unlock_irqrestore(&pool->lock, flags); while ((bio = bio_list_pop(&bios))) { - struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; + struct endio_hook *h = dm_get_mapinfo(bio)->ptr; struct thin_c *tc = h->tc; /* @@ -1527,10 +1522,10 @@ static void thin_defer_bio(struct thin_c *tc, struct bio *bio) wake_worker(pool); } -static struct dm_thin_endio_hook *thin_hook_bio(struct thin_c *tc, struct bio *bio) +static struct endio_hook *thin_hook_bio(struct thin_c *tc, struct bio *bio) { struct pool *pool = tc->pool; - struct dm_thin_endio_hook *h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO); + struct endio_hook *h = mempool_alloc(pool->endio_hook_pool, GFP_NOIO); h->tc = tc; h->shared_read_entry = NULL; @@ -1692,9 +1687,6 @@ static void __pool_destroy(struct pool *pool) kfree(pool); } -static struct kmem_cache *_new_mapping_cache; -static struct kmem_cache *_endio_hook_cache; - static struct pool *pool_create(struct mapped_device *pool_md, struct block_device *metadata_dev, unsigned long block_size, char **error) @@ -1763,16 +1755,16 @@ static struct pool *pool_create(struct mapped_device *pool_md, ds_init(&pool->all_io_ds); pool->next_mapping = NULL; - pool->mapping_pool = mempool_create_slab_pool(MAPPING_POOL_SIZE, - _new_mapping_cache); + pool->mapping_pool = + mempool_create_kmalloc_pool(MAPPING_POOL_SIZE, sizeof(struct new_mapping)); if (!pool->mapping_pool) { *error = "Error creating pool's mapping mempool"; err_p = ERR_PTR(-ENOMEM); goto bad_mapping_pool; } - pool->endio_hook_pool = mempool_create_slab_pool(ENDIO_HOOK_POOL_SIZE, - _endio_hook_cache); + pool->endio_hook_pool = + mempool_create_kmalloc_pool(ENDIO_HOOK_POOL_SIZE, sizeof(struct endio_hook)); if (!pool->endio_hook_pool) { *error = "Error creating pool's endio_hook mempool"; err_p = ERR_PTR(-ENOMEM); @@ -2284,36 +2276,6 @@ static int process_set_transaction_id_mesg(unsigned argc, char **argv, struct po return 0; } -static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct pool *pool) -{ - int r; - - r = check_arg_count(argc, 1); - if (r) - return r; - - r = dm_pool_reserve_metadata_snap(pool->pmd); - if (r) - DMWARN("reserve_metadata_snap message failed."); - - return r; -} - -static int process_release_metadata_snap_mesg(unsigned argc, char **argv, struct pool *pool) -{ - int r; - - r = check_arg_count(argc, 1); - if (r) - return r; - - r = dm_pool_release_metadata_snap(pool->pmd); - if (r) - DMWARN("release_metadata_snap message failed."); - - return r; -} - /* * Messages supported: * create_thin @@ -2321,8 +2283,6 @@ static int process_release_metadata_snap_mesg(unsigned argc, char **argv, struct * delete * trim * set_transaction_id - * reserve_metadata_snap - * release_metadata_snap */ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) { @@ -2342,12 +2302,6 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) else if (!strcasecmp(argv[0], "set_transaction_id")) r = process_set_transaction_id_mesg(argc, argv, pool); - else if (!strcasecmp(argv[0], "reserve_metadata_snap")) - r = process_reserve_metadata_snap_mesg(argc, argv, pool); - - else if (!strcasecmp(argv[0], "release_metadata_snap")) - r = process_release_metadata_snap_mesg(argc, argv, pool); - else DMWARN("Unrecognised thin pool target message received: %s", argv[0]); @@ -2407,7 +2361,7 @@ static int pool_status(struct dm_target *ti, status_type_t type, if (r) return r; - r = dm_pool_get_metadata_snap(pool->pmd, &held_root); + r = dm_pool_get_held_metadata_root(pool->pmd, &held_root); if (r) return r; @@ -2503,7 +2457,7 @@ static struct target_type pool_target = { .name = "thin-pool", .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | DM_TARGET_IMMUTABLE, - .version = {1, 2, 0}, + .version = {1, 1, 0}, .module = THIS_MODULE, .ctr = pool_ctr, .dtr = pool_dtr, @@ -2659,9 +2613,9 @@ static int thin_endio(struct dm_target *ti, union map_info *map_context) { unsigned long flags; - struct dm_thin_endio_hook *h = map_context->ptr; + struct endio_hook *h = map_context->ptr; struct list_head work; - struct dm_thin_new_mapping *m, *tmp; + struct new_mapping *m, *tmp; struct pool *pool = h->tc->pool; if (h->shared_read_entry) { @@ -2801,32 +2755,7 @@ static int __init dm_thin_init(void) r = dm_register_target(&pool_target); if (r) - goto bad_pool_target; - - r = -ENOMEM; - - _cell_cache = KMEM_CACHE(dm_bio_prison_cell, 0); - if (!_cell_cache) - goto bad_cell_cache; - - _new_mapping_cache = KMEM_CACHE(dm_thin_new_mapping, 0); - if (!_new_mapping_cache) - goto bad_new_mapping_cache; - - _endio_hook_cache = KMEM_CACHE(dm_thin_endio_hook, 0); - if (!_endio_hook_cache) - goto bad_endio_hook_cache; - - return 0; - -bad_endio_hook_cache: - kmem_cache_destroy(_new_mapping_cache); -bad_new_mapping_cache: - kmem_cache_destroy(_cell_cache); -bad_cell_cache: - dm_unregister_target(&pool_target); -bad_pool_target: - dm_unregister_target(&thin_target); + dm_unregister_target(&thin_target); return r; } @@ -2835,10 +2764,6 @@ static void dm_thin_exit(void) { dm_unregister_target(&thin_target); dm_unregister_target(&pool_target); - - kmem_cache_destroy(_cell_cache); - kmem_cache_destroy(_new_mapping_cache); - kmem_cache_destroy(_endio_hook_cache); } module_init(dm_thin_init); diff --git a/trunk/drivers/md/persistent-data/dm-transaction-manager.c b/trunk/drivers/md/persistent-data/dm-transaction-manager.c index 400fe144c0cd..6f8d38747d7f 100644 --- a/trunk/drivers/md/persistent-data/dm-transaction-manager.c +++ b/trunk/drivers/md/persistent-data/dm-transaction-manager.c @@ -249,7 +249,6 @@ int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig, return r; } -EXPORT_SYMBOL_GPL(dm_tm_shadow_block); int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, struct dm_block_validator *v, @@ -260,7 +259,6 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, return dm_bm_read_lock(tm->bm, b, v, blk); } -EXPORT_SYMBOL_GPL(dm_tm_read_lock); int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b) { diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index a9c7981ddd24..835de7168cd3 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -2550,7 +2550,6 @@ static struct r1conf *setup_conf(struct mddev *mddev) err = -EINVAL; spin_lock_init(&conf->device_lock); rdev_for_each(rdev, mddev) { - struct request_queue *q; int disk_idx = rdev->raid_disk; if (disk_idx >= mddev->raid_disks || disk_idx < 0) @@ -2563,9 +2562,6 @@ static struct r1conf *setup_conf(struct mddev *mddev) if (disk->rdev) goto abort; disk->rdev = rdev; - q = bdev_get_queue(rdev->bdev); - if (q->merge_bvec_fn) - mddev->merge_check_needed = 1; disk->head_position = 0; } diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 99ae6068e456..987db37cb875 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -3475,7 +3475,6 @@ static int run(struct mddev *mddev) rdev_for_each(rdev, mddev) { long long diff; - struct request_queue *q; disk_idx = rdev->raid_disk; if (disk_idx < 0) @@ -3494,9 +3493,6 @@ static int run(struct mddev *mddev) goto out_free_conf; disk->rdev = rdev; } - q = bdev_get_queue(rdev->bdev); - if (q->merge_bvec_fn) - mddev->merge_check_needed = 1; diff = (rdev->new_data_offset - rdev->data_offset); if (!mddev->reshape_backwards) diff = -diff; diff --git a/trunk/drivers/message/fusion/mptbase.c b/trunk/drivers/message/fusion/mptbase.c index d99db5623acf..a5c591ffe395 100644 --- a/trunk/drivers/message/fusion/mptbase.c +++ b/trunk/drivers/message/fusion/mptbase.c @@ -1653,6 +1653,7 @@ mpt_mapresources(MPT_ADAPTER *ioc) unsigned long port; u32 msize; u32 psize; + u8 revision; int r = -ENODEV; struct pci_dev *pdev; @@ -1669,6 +1670,8 @@ mpt_mapresources(MPT_ADAPTER *ioc) return r; } + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + if (sizeof(dma_addr_t) > 4) { const uint64_t required_mask = dma_get_required_mask (&pdev->dev); @@ -1776,6 +1779,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) MPT_ADAPTER *ioc; u8 cb_idx; int r = -ENODEV; + u8 revision; u8 pcixcmd; static int mpt_ids = 0; #ifdef CONFIG_PROC_FS @@ -1883,8 +1887,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n", ioc->name, &ioc->facts, &ioc->pfacts[0])); - mpt_get_product_name(pdev->vendor, pdev->device, pdev->revision, - ioc->prod_name); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name); switch (pdev->device) { @@ -1899,7 +1903,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) break; case MPI_MANUFACTPAGE_DEVICEID_FC929X: - if (pdev->revision < XL_929) { + if (revision < XL_929) { /* 929X Chip Fix. Set Split transactions level * for PCIX. Set MOST bits to zero. */ @@ -1930,7 +1934,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* 1030 Chip Fix. Disable Split transactions * for PCIX. Set MOST bits to zero if Rev < C0( = 8). */ - if (pdev->revision < C0_1030) { + if (revision < C0_1030) { pci_read_config_byte(pdev, 0x6a, &pcixcmd); pcixcmd &= 0x8F; pci_write_config_byte(pdev, 0x6a, pcixcmd); @@ -6479,7 +6483,6 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) printk(MYIOC_s_INFO_FMT "%s: host reset in" " progress mpt_config timed out.!!\n", __func__, ioc->name); - mutex_unlock(&ioc->mptbase_cmds.mutex); return -EFAULT; } spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); diff --git a/trunk/drivers/message/fusion/mptctl.c b/trunk/drivers/message/fusion/mptctl.c index b383b6961e59..6e6e16aab9da 100644 --- a/trunk/drivers/message/fusion/mptctl.c +++ b/trunk/drivers/message/fusion/mptctl.c @@ -1250,6 +1250,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) int iocnum; unsigned int port; int cim_rev; + u8 revision; struct scsi_device *sdev; VirtDevice *vdevice; @@ -1323,7 +1324,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) pdev = (struct pci_dev *) ioc->pcidev; karg->pciId = pdev->device; - karg->hwRev = pdev->revision; + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + karg->hwRev = revision; karg->subSystemDevice = pdev->subsystem_device; karg->subSystemVendor = pdev->subsystem_vendor; diff --git a/trunk/drivers/mfd/db8500-prcmu.c b/trunk/drivers/mfd/db8500-prcmu.c index 50e83dc5dc49..671c8bc14bbc 100644 --- a/trunk/drivers/mfd/db8500-prcmu.c +++ b/trunk/drivers/mfd/db8500-prcmu.c @@ -2735,7 +2735,6 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = { REGULATOR_SUPPLY("vcore", "uart2"), REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"), - REGULATOR_SUPPLY("vddvario", "smsc911x.0"), }; static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { diff --git a/trunk/drivers/mtd/Kconfig b/trunk/drivers/mtd/Kconfig index 27143e042af5..5760c1a4b3f6 100644 --- a/trunk/drivers/mtd/Kconfig +++ b/trunk/drivers/mtd/Kconfig @@ -128,7 +128,7 @@ config MTD_AFS_PARTS config MTD_OF_PARTS tristate "OpenFirmware partitioning information support" - default y + default Y depends on OF help This provides a partition parsing function which derives diff --git a/trunk/drivers/mtd/bcm63xxpart.c b/trunk/drivers/mtd/bcm63xxpart.c index 63d2a64331f7..608321ee056e 100644 --- a/trunk/drivers/mtd/bcm63xxpart.c +++ b/trunk/drivers/mtd/bcm63xxpart.c @@ -4,7 +4,7 @@ * Copyright © 2006-2008 Florian Fainelli * Mike Albon * Copyright © 2009-2010 Daniel Dickinson - * Copyright © 2011-2012 Jonas Gorski + * Copyright © 2011 Jonas Gorski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -82,7 +82,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, int namelen = 0; int i; u32 computed_crc; - bool rootfs_first = false; if (bcm63xx_detect_cfe(master)) return -EINVAL; @@ -110,7 +109,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, char *boardid = &(buf->board_id[0]); char *tagversion = &(buf->tag_version[0]); - sscanf(buf->flash_image_start, "%u", &rootfsaddr); sscanf(buf->kernel_address, "%u", &kerneladdr); sscanf(buf->kernel_length, "%u", &kernellen); sscanf(buf->total_length, "%u", &totallen); @@ -119,19 +117,10 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, tagversion, boardid); kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; - rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE; + rootfsaddr = kerneladdr + kernellen; spareaddr = roundup(totallen, master->erasesize) + cfelen; sparelen = master->size - spareaddr - nvramlen; - - if (rootfsaddr < kerneladdr) { - /* default Broadcom layout */ - rootfslen = kerneladdr - rootfsaddr; - rootfs_first = true; - } else { - /* OpenWrt layout */ - rootfsaddr = kerneladdr + kernellen; - rootfslen = spareaddr - rootfsaddr; - } + rootfslen = spareaddr - rootfsaddr; } else { pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n", buf->header_crc, computed_crc); @@ -167,26 +156,18 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, curpart++; if (kernellen > 0) { - int kernelpart = curpart; - - if (rootfslen > 0 && rootfs_first) - kernelpart++; - parts[kernelpart].name = "kernel"; - parts[kernelpart].offset = kerneladdr; - parts[kernelpart].size = kernellen; + parts[curpart].name = "kernel"; + parts[curpart].offset = kerneladdr; + parts[curpart].size = kernellen; curpart++; } if (rootfslen > 0) { - int rootfspart = curpart; - - if (kernellen > 0 && rootfs_first) - rootfspart--; - parts[rootfspart].name = "rootfs"; - parts[rootfspart].offset = rootfsaddr; - parts[rootfspart].size = rootfslen; - if (sparelen > 0 && !rootfs_first) - parts[rootfspart].size += sparelen; + parts[curpart].name = "rootfs"; + parts[curpart].offset = rootfsaddr; + parts[curpart].size = rootfslen; + if (sparelen > 0) + parts[curpart].size += sparelen; curpart++; } diff --git a/trunk/drivers/mtd/chips/cfi_cmdset_0002.c b/trunk/drivers/mtd/chips/cfi_cmdset_0002.c index 22d0493a026f..d02592e6a0f0 100644 --- a/trunk/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/trunk/drivers/mtd/chips/cfi_cmdset_0002.c @@ -317,7 +317,7 @@ static void fixup_s29gl064n_sectors(struct mtd_info *mtd) if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) { cfi->cfiq->EraseRegionInfo[0] |= 0x0040; - pr_warning("%s: Bad S29GL064N CFI data; adjust from 64 to 128 sectors\n", mtd->name); + pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name); } } @@ -328,23 +328,10 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd) if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) { cfi->cfiq->EraseRegionInfo[1] &= ~0x0040; - pr_warning("%s: Bad S29GL032N CFI data; adjust from 127 to 63 sectors\n", mtd->name); + pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name); } } -static void fixup_s29ns512p_sectors(struct mtd_info *mtd) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - - /* - * S29NS512P flash uses more than 8bits to report number of sectors, - * which is not permitted by CFI. - */ - cfi->cfiq->EraseRegionInfo[0] = 0x020001ff; - pr_warning("%s: Bad S29NS512P CFI data; adjust to 512 sectors\n", mtd->name); -} - /* Used to fix CFI-Tables of chips without Extended Query Tables */ static struct cfi_fixup cfi_nopri_fixup_table[] = { { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ @@ -375,7 +362,6 @@ static struct cfi_fixup cfi_fixup_table[] = { { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, - { CFI_MFR_AMD, 0x3f00, fixup_s29ns512p_sectors }, { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */ { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */ { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */ diff --git a/trunk/drivers/mtd/cmdlinepart.c b/trunk/drivers/mtd/cmdlinepart.c index 4558e0f4d07f..ddf9ec6d9168 100644 --- a/trunk/drivers/mtd/cmdlinepart.c +++ b/trunk/drivers/mtd/cmdlinepart.c @@ -70,7 +70,7 @@ struct cmdline_mtd_partition { /* mtdpart_setup() parses into here */ static struct cmdline_mtd_partition *partitions; -/* the command line passed to mtdpart_setup() */ +/* the command line passed to mtdpart_setupd() */ static char *cmdline; static int cmdline_parsed = 0; diff --git a/trunk/drivers/mtd/devices/block2mtd.c b/trunk/drivers/mtd/devices/block2mtd.c index 681e2ee0f2d6..a4a80b742e65 100644 --- a/trunk/drivers/mtd/devices/block2mtd.c +++ b/trunk/drivers/mtd/devices/block2mtd.c @@ -52,6 +52,8 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) while (pages) { page = page_read(mapping, index); + if (!page) + return -ENOMEM; if (IS_ERR(page)) return PTR_ERR(page); @@ -110,6 +112,8 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len, len = len - cpylen; page = page_read(dev->blkdev->bd_inode->i_mapping, index); + if (!page) + return -ENOMEM; if (IS_ERR(page)) return PTR_ERR(page); @@ -144,6 +148,8 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, len = len - cpylen; page = page_read(mapping, index); + if (!page) + return -ENOMEM; if (IS_ERR(page)) return PTR_ERR(page); @@ -265,6 +271,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) dev->mtd.flags = MTD_CAP_RAM; dev->mtd._erase = block2mtd_erase; dev->mtd._write = block2mtd_write; + dev->mtd._writev = mtd_writev; dev->mtd._sync = block2mtd_sync; dev->mtd._read = block2mtd_read; dev->mtd.priv = dev; diff --git a/trunk/drivers/mtd/devices/docg3.c b/trunk/drivers/mtd/devices/docg3.c index f70854d728fe..50aa90aa7a7f 100644 --- a/trunk/drivers/mtd/devices/docg3.c +++ b/trunk/drivers/mtd/devices/docg3.c @@ -227,7 +227,7 @@ static void doc_read_data_area(struct docg3 *docg3, void *buf, int len, u8 data8, *dst8; doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len); - cdr = len & 0x1; + cdr = len & 0x3; len4 = len - cdr; if (first) @@ -732,24 +732,12 @@ static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1, * @len: the number of bytes to be read (must be a multiple of 4) * @buf: the buffer to be filled in (or NULL is forget bytes) * @first: 1 if first time read, DOC_READADDRESS should be set - * @last_odd: 1 if last read ended up on an odd byte - * - * Reads bytes from a prepared page. There is a trickery here : if the last read - * ended up on an odd offset in the 1024 bytes double page, ie. between the 2 - * planes, the first byte must be read apart. If a word (16bit) read was used, - * the read would return the byte of plane 2 as low *and* high endian, which - * will mess the read. * */ static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf, - int first, int last_odd) + int first) { - if (last_odd && len > 0) { - doc_read_data_area(docg3, buf, 1, first); - doc_read_data_area(docg3, buf ? buf + 1 : buf, len - 1, 0); - } else { - doc_read_data_area(docg3, buf, len, first); - } + doc_read_data_area(docg3, buf, len, first); doc_delay(docg3, 2); return len; } @@ -862,7 +850,6 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, u8 *buf = ops->datbuf; size_t len, ooblen, nbdata, nboob; u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1; - int max_bitflips = 0; if (buf) len = ops->len; @@ -889,7 +876,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, ret = 0; skip = from % DOC_LAYOUT_PAGE_SIZE; mutex_lock(&docg3->cascade->lock); - while (ret >= 0 && (len > 0 || ooblen > 0)) { + while (!ret && (len > 0 || ooblen > 0)) { calc_block_sector(from - skip, &block0, &block1, &page, &ofs, docg3->reliable); nbdata = min_t(size_t, len, DOC_LAYOUT_PAGE_SIZE - skip); @@ -900,20 +887,20 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES); if (ret < 0) goto err_in_read; - ret = doc_read_page_getbytes(docg3, skip, NULL, 1, 0); + ret = doc_read_page_getbytes(docg3, skip, NULL, 1); if (ret < skip) goto err_in_read; - ret = doc_read_page_getbytes(docg3, nbdata, buf, 0, skip % 2); + ret = doc_read_page_getbytes(docg3, nbdata, buf, 0); if (ret < nbdata) goto err_in_read; doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE - nbdata - skip, - NULL, 0, (skip + nbdata) % 2); - ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0, 0); + NULL, 0); + ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0); if (ret < nboob) goto err_in_read; doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE - nboob, - NULL, 0, nboob % 2); + NULL, 0); doc_get_bch_hw_ecc(docg3, hwecc); eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1); @@ -949,8 +936,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t from, } if (ret > 0) { mtd->ecc_stats.corrected += ret; - max_bitflips = max(max_bitflips, ret); - ret = max_bitflips; + ret = -EUCLEAN; } } @@ -1018,7 +1004,7 @@ static int doc_reload_bbt(struct docg3 *docg3) DOC_LAYOUT_PAGE_SIZE); if (!ret) doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE, - buf, 1, 0); + buf, 1); buf += DOC_LAYOUT_PAGE_SIZE; } doc_read_page_finish(docg3); @@ -1078,10 +1064,10 @@ static int doc_get_erase_count(struct docg3 *docg3, loff_t from) ret = doc_reset_seq(docg3); if (!ret) ret = doc_read_page_prepare(docg3, block0, block1, page, - ofs + DOC_LAYOUT_WEAR_OFFSET, 0); + ofs + DOC_LAYOUT_WEAR_OFFSET); if (!ret) ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE, - buf, 1, 0); + buf, 1); doc_read_page_finish(docg3); if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK)) diff --git a/trunk/drivers/mtd/devices/m25p80.c b/trunk/drivers/mtd/devices/m25p80.c index 5d0d68c3fe27..1924d247c1cb 100644 --- a/trunk/drivers/mtd/devices/m25p80.c +++ b/trunk/drivers/mtd/devices/m25p80.c @@ -639,16 +639,12 @@ static const struct spi_device_id m25p_ids[] = { { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, - /* Everspin */ - { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) }, - /* Intel/Numonyx -- xxxs33b */ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, /* Macronix */ - { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, @@ -732,7 +728,6 @@ static const struct spi_device_id m25p_ids[] = { { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, - { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, /* Catalyst / On Semiconductor -- non-JEDEC */ { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, diff --git a/trunk/drivers/mtd/devices/spear_smi.c b/trunk/drivers/mtd/devices/spear_smi.c index 67960362681e..797d43cd3550 100644 --- a/trunk/drivers/mtd/devices/spear_smi.c +++ b/trunk/drivers/mtd/devices/spear_smi.c @@ -990,9 +990,9 @@ static int __devinit spear_smi_probe(struct platform_device *pdev) goto err_clk; } - ret = clk_prepare_enable(dev->clk); + ret = clk_enable(dev->clk); if (ret) - goto err_clk_prepare_enable; + goto err_clk_enable; ret = request_irq(irq, spear_smi_int_handler, 0, pdev->name, dev); if (ret) { @@ -1020,8 +1020,8 @@ static int __devinit spear_smi_probe(struct platform_device *pdev) free_irq(irq, dev); platform_set_drvdata(pdev, NULL); err_irq: - clk_disable_unprepare(dev->clk); -err_clk_prepare_enable: + clk_disable(dev->clk); +err_clk_enable: clk_put(dev->clk); err_clk: iounmap(dev->io_base); @@ -1074,7 +1074,7 @@ static int __devexit spear_smi_remove(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); free_irq(irq, dev); - clk_disable_unprepare(dev->clk); + clk_disable(dev->clk); clk_put(dev->clk); iounmap(dev->io_base); kfree(dev); @@ -1091,7 +1091,7 @@ int spear_smi_suspend(struct platform_device *pdev, pm_message_t state) struct spear_smi *dev = platform_get_drvdata(pdev); if (dev && dev->clk) - clk_disable_unprepare(dev->clk); + clk_disable(dev->clk); return 0; } @@ -1102,7 +1102,7 @@ int spear_smi_resume(struct platform_device *pdev) int ret = -EPERM; if (dev && dev->clk) - ret = clk_prepare_enable(dev->clk); + ret = clk_enable(dev->clk); if (!ret) spear_smi_hw_init(dev); diff --git a/trunk/drivers/mtd/lpddr/qinfo_probe.c b/trunk/drivers/mtd/lpddr/qinfo_probe.c index 45abed67f1ef..dbfe17baf046 100644 --- a/trunk/drivers/mtd/lpddr/qinfo_probe.c +++ b/trunk/drivers/mtd/lpddr/qinfo_probe.c @@ -57,7 +57,7 @@ static struct qinfo_query_info qinfo_array[] = { static long lpddr_get_qinforec_pos(struct map_info *map, char *id_str) { - int qinfo_lines = ARRAY_SIZE(qinfo_array); + int qinfo_lines = sizeof(qinfo_array)/sizeof(struct qinfo_query_info); int i; int bankwidth = map_bankwidth(map) * 8; int major, minor; diff --git a/trunk/drivers/mtd/maps/Kconfig b/trunk/drivers/mtd/maps/Kconfig index 5ba2458e799a..8af67cfd671a 100644 --- a/trunk/drivers/mtd/maps/Kconfig +++ b/trunk/drivers/mtd/maps/Kconfig @@ -224,7 +224,7 @@ config MTD_CK804XROM config MTD_SCB2_FLASH tristate "BIOS flash chip on Intel SCB2 boards" - depends on X86 && MTD_JEDECPROBE && PCI + depends on X86 && MTD_JEDECPROBE help Support for treating the BIOS flash chip on Intel SCB2 boards as an MTD device - with this you can reprogram your BIOS. diff --git a/trunk/drivers/mtd/maps/intel_vr_nor.c b/trunk/drivers/mtd/maps/intel_vr_nor.c index 93f03175c82d..92e1f41634c7 100644 --- a/trunk/drivers/mtd/maps/intel_vr_nor.c +++ b/trunk/drivers/mtd/maps/intel_vr_nor.c @@ -260,7 +260,18 @@ static struct pci_driver vr_nor_pci_driver = { .id_table = vr_nor_pci_ids, }; -module_pci_driver(vr_nor_pci_driver); +static int __init vr_nor_mtd_init(void) +{ + return pci_register_driver(&vr_nor_pci_driver); +} + +static void __exit vr_nor_mtd_exit(void) +{ + pci_unregister_driver(&vr_nor_pci_driver); +} + +module_init(vr_nor_mtd_init); +module_exit(vr_nor_mtd_exit); MODULE_AUTHOR("Andy Lowe"); MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range"); diff --git a/trunk/drivers/mtd/maps/pci.c b/trunk/drivers/mtd/maps/pci.c index f14ce0af763f..1d005a3e9b41 100644 --- a/trunk/drivers/mtd/maps/pci.c +++ b/trunk/drivers/mtd/maps/pci.c @@ -352,7 +352,18 @@ static struct pci_driver mtd_pci_driver = { .id_table = mtd_pci_ids, }; -module_pci_driver(mtd_pci_driver); +static int __init mtd_pci_maps_init(void) +{ + return pci_register_driver(&mtd_pci_driver); +} + +static void __exit mtd_pci_maps_exit(void) +{ + pci_unregister_driver(&mtd_pci_driver); +} + +module_init(mtd_pci_maps_init); +module_exit(mtd_pci_maps_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Russell King "); diff --git a/trunk/drivers/mtd/maps/scb2_flash.c b/trunk/drivers/mtd/maps/scb2_flash.c index 9dcbc684abdb..934a72c80078 100644 --- a/trunk/drivers/mtd/maps/scb2_flash.c +++ b/trunk/drivers/mtd/maps/scb2_flash.c @@ -234,7 +234,20 @@ static struct pci_driver scb2_flash_driver = { .remove = __devexit_p(scb2_flash_remove), }; -module_pci_driver(scb2_flash_driver); +static int __init +scb2_flash_init(void) +{ + return pci_register_driver(&scb2_flash_driver); +} + +static void __exit +scb2_flash_exit(void) +{ + pci_unregister_driver(&scb2_flash_driver); +} + +module_init(scb2_flash_init); +module_exit(scb2_flash_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tim Hockin "); diff --git a/trunk/drivers/mtd/maps/wr_sbc82xx_flash.c b/trunk/drivers/mtd/maps/wr_sbc82xx_flash.c index e7534c82f93a..71b0ba797912 100644 --- a/trunk/drivers/mtd/maps/wr_sbc82xx_flash.c +++ b/trunk/drivers/mtd/maps/wr_sbc82xx_flash.c @@ -59,7 +59,7 @@ static struct mtd_partition bigflash_parts[] = { } }; -static const char *part_probes[] __initconst = {"cmdlinepart", "RedBoot", NULL}; +static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL}; #define init_sbc82xx_one_flash(map, br, or) \ do { \ diff --git a/trunk/drivers/mtd/mtdcore.c b/trunk/drivers/mtd/mtdcore.c index 575730744fdb..c837507dfb1c 100644 --- a/trunk/drivers/mtd/mtdcore.c +++ b/trunk/drivers/mtd/mtdcore.c @@ -250,43 +250,6 @@ static ssize_t mtd_name_show(struct device *dev, } static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL); -static ssize_t mtd_ecc_strength_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mtd_info *mtd = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_strength); -} -static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL); - -static ssize_t mtd_bitflip_threshold_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct mtd_info *mtd = dev_get_drvdata(dev); - - return snprintf(buf, PAGE_SIZE, "%u\n", mtd->bitflip_threshold); -} - -static ssize_t mtd_bitflip_threshold_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct mtd_info *mtd = dev_get_drvdata(dev); - unsigned int bitflip_threshold; - int retval; - - retval = kstrtouint(buf, 0, &bitflip_threshold); - if (retval) - return retval; - - mtd->bitflip_threshold = bitflip_threshold; - return count; -} -static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR, - mtd_bitflip_threshold_show, - mtd_bitflip_threshold_store); - static struct attribute *mtd_attrs[] = { &dev_attr_type.attr, &dev_attr_flags.attr, @@ -297,8 +260,6 @@ static struct attribute *mtd_attrs[] = { &dev_attr_oobsize.attr, &dev_attr_numeraseregions.attr, &dev_attr_name.attr, - &dev_attr_ecc_strength.attr, - &dev_attr_bitflip_threshold.attr, NULL, }; @@ -361,10 +322,6 @@ int add_mtd_device(struct mtd_info *mtd) mtd->index = i; mtd->usecount = 0; - /* default value if not set by driver */ - if (mtd->bitflip_threshold == 0) - mtd->bitflip_threshold = mtd->ecc_strength; - if (is_power_of_2(mtd->erasesize)) mtd->erasesize_shift = ffs(mtd->erasesize) - 1; else @@ -800,24 +757,12 @@ EXPORT_SYMBOL_GPL(mtd_get_unmapped_area); int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - int ret_code; *retlen = 0; if (from < 0 || from > mtd->size || len > mtd->size - from) return -EINVAL; if (!len) return 0; - - /* - * In the absence of an error, drivers return a non-negative integer - * representing the maximum number of bitflips that were corrected on - * any one ecc region (if applicable; zero otherwise). - */ - ret_code = mtd->_read(mtd, from, len, retlen, buf); - if (unlikely(ret_code < 0)) - return ret_code; - if (mtd->ecc_strength == 0) - return 0; /* device lacks ecc */ - return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; + return mtd->_read(mtd, from, len, retlen, buf); } EXPORT_SYMBOL_GPL(mtd_read); diff --git a/trunk/drivers/mtd/mtdpart.c b/trunk/drivers/mtd/mtdpart.c index d518e4db8a0b..9651c06de0a9 100644 --- a/trunk/drivers/mtd/mtdpart.c +++ b/trunk/drivers/mtd/mtdpart.c @@ -67,12 +67,12 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len, stats = part->master->ecc_stats; res = part->master->_read(part->master, from + part->offset, len, retlen, buf); - if (unlikely(mtd_is_eccerr(res))) - mtd->ecc_stats.failed += - part->master->ecc_stats.failed - stats.failed; - else - mtd->ecc_stats.corrected += - part->master->ecc_stats.corrected - stats.corrected; + if (unlikely(res)) { + if (mtd_is_bitflip(res)) + mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; + if (mtd_is_eccerr(res)) + mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; + } return res; } @@ -517,8 +517,6 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, slave->mtd.ecclayout = master->ecclayout; slave->mtd.ecc_strength = master->ecc_strength; - slave->mtd.bitflip_threshold = master->bitflip_threshold; - if (master->_block_isbad) { uint64_t offs = 0; diff --git a/trunk/drivers/mtd/nand/Kconfig b/trunk/drivers/mtd/nand/Kconfig index 31bb7e5b504a..7d17cecad69d 100644 --- a/trunk/drivers/mtd/nand/Kconfig +++ b/trunk/drivers/mtd/nand/Kconfig @@ -115,46 +115,6 @@ config MTD_NAND_OMAP2 Support for NAND flash on Texas Instruments OMAP2, OMAP3 and OMAP4 platforms. -config MTD_NAND_OMAP_BCH - depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3 - bool "Enable support for hardware BCH error correction" - default n - select BCH - select BCH_CONST_PARAMS - help - Support for hardware BCH error correction. - -choice - prompt "BCH error correction capability" - depends on MTD_NAND_OMAP_BCH - -config MTD_NAND_OMAP_BCH8 - bool "8 bits / 512 bytes (recommended)" - help - Support correcting up to 8 bitflips per 512-byte block. - This will use 13 bytes of spare area per 512 bytes of page data. - This is the recommended mode, as 4-bit mode does not work - on some OMAP3 revisions, due to a hardware bug. - -config MTD_NAND_OMAP_BCH4 - bool "4 bits / 512 bytes" - help - Support correcting up to 4 bitflips per 512-byte block. - This will use 7 bytes of spare area per 512 bytes of page data. - Note that this mode does not work on some OMAP3 revisions, due to a - hardware bug. Please check your OMAP datasheet before selecting this - mode. - -endchoice - -if MTD_NAND_OMAP_BCH -config BCH_CONST_M - default 13 -config BCH_CONST_T - default 4 if MTD_NAND_OMAP_BCH4 - default 8 if MTD_NAND_OMAP_BCH8 -endif - config MTD_NAND_IDS tristate @@ -480,7 +440,7 @@ config MTD_NAND_NANDSIM config MTD_NAND_GPMI_NAND bool "GPMI NAND Flash Controller driver" - depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q) + depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28) help Enables NAND Flash support for IMX23 or IMX28. The GPMI controller is very powerful, with the help of BCH diff --git a/trunk/drivers/mtd/nand/alauda.c b/trunk/drivers/mtd/nand/alauda.c index 60a0dfdb0808..4f20e1d8bef1 100644 --- a/trunk/drivers/mtd/nand/alauda.c +++ b/trunk/drivers/mtd/nand/alauda.c @@ -414,7 +414,7 @@ static int alauda_bounce_read(struct mtd_info *mtd, loff_t from, size_t len, } err = 0; if (corrected) - err = 1; /* return max_bitflips per ecc step */ + err = -EUCLEAN; if (uncorrected) err = -EBADMSG; out: @@ -446,7 +446,7 @@ static int alauda_read(struct mtd_info *mtd, loff_t from, size_t len, } err = 0; if (corrected) - err = 1; /* return max_bitflips per ecc step */ + err = -EUCLEAN; if (uncorrected) err = -EBADMSG; return err; diff --git a/trunk/drivers/mtd/nand/atmel_nand.c b/trunk/drivers/mtd/nand/atmel_nand.c index 97ac6712bb19..2165576a1c67 100644 --- a/trunk/drivers/mtd/nand/atmel_nand.c +++ b/trunk/drivers/mtd/nand/atmel_nand.c @@ -324,10 +324,9 @@ static int atmel_nand_calculate(struct mtd_info *mtd, * mtd: mtd info structure * chip: nand chip info structure * buf: buffer to store read data - * oob_required: caller expects OOB data read to chip->oob_poi */ -static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int atmel_nand_read_page(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -336,7 +335,6 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *oob = chip->oob_poi; uint8_t *ecc_pos; int stat; - unsigned int max_bitflips = 0; /* * Errata: ALE is incorrectly wired up to the ECC controller @@ -373,12 +371,10 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, /* check if there's an error */ stat = chip->ecc.correct(mtd, p, oob, NULL); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } /* get back to oob start (end of page) */ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); @@ -386,7 +382,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, /* read the oob */ chip->read_buf(mtd, oob, mtd->oobsize); - return max_bitflips; + return 0; } /* diff --git a/trunk/drivers/mtd/nand/au1550nd.c b/trunk/drivers/mtd/nand/au1550nd.c index 9f609d2dcf62..73abbc3e093e 100644 --- a/trunk/drivers/mtd/nand/au1550nd.c +++ b/trunk/drivers/mtd/nand/au1550nd.c @@ -508,6 +508,8 @@ static int __devinit au1550nd_probe(struct platform_device *pdev) this->chip_delay = 30; this->ecc.mode = NAND_ECC_SOFT; + this->options = NAND_NO_AUTOINCR; + if (pd->devwidth) this->options |= NAND_BUSWIDTH_16; diff --git a/trunk/drivers/mtd/nand/bcm_umi_bch.c b/trunk/drivers/mtd/nand/bcm_umi_bch.c index 5914bb32e001..a930666d0687 100644 --- a/trunk/drivers/mtd/nand/bcm_umi_bch.c +++ b/trunk/drivers/mtd/nand/bcm_umi_bch.c @@ -22,9 +22,9 @@ /* ---- Private Function Prototypes -------------------------------------- */ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, int page); + struct nand_chip *chip, uint8_t *buf, int page); static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, int oob_required); + struct nand_chip *chip, const uint8_t *buf); /* ---- Private Variables ------------------------------------------------ */ @@ -103,12 +103,11 @@ static struct nand_ecclayout nand_hw_eccoob_4096 = { * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data -* @oob_required: caller expects OOB data read to chip->oob_poi * ***************************************************************************/ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, - int oob_required, int page) + int page) { int sectorIdx = 0; int eccsize = chip->ecc.size; @@ -117,7 +116,6 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, uint8_t eccCalc[NAND_ECC_NUM_BYTES]; int sectorOobSize = mtd->oobsize / eccsteps; int stat; - unsigned int max_bitflips = 0; for (sectorIdx = 0; sectorIdx < eccsteps; sectorIdx++, datap += eccsize) { @@ -179,10 +177,9 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, } #endif mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); } } - return max_bitflips; + return 0; } /**************************************************************************** @@ -191,11 +188,10 @@ static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer -* @oob_required: must write chip->oob_poi to OOB * ***************************************************************************/ static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, int oob_required) + struct nand_chip *chip, const uint8_t *buf) { int sectorIdx = 0; int eccsize = chip->ecc.size; diff --git a/trunk/drivers/mtd/nand/bcm_umi_nand.c b/trunk/drivers/mtd/nand/bcm_umi_nand.c index c855e7cd337b..6908cdde3065 100644 --- a/trunk/drivers/mtd/nand/bcm_umi_nand.c +++ b/trunk/drivers/mtd/nand/bcm_umi_nand.c @@ -341,7 +341,7 @@ static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf, * for MLC parts which may have permanently stuck bits. */ struct nand_chip *chip = mtd->priv; - int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0, 0); + int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0); if (ret < 0) return -EFAULT; else { @@ -476,7 +476,12 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev) this->badblock_pattern = &largepage_bbt; } - this->ecc.strength = 8; + /* + * FIXME: ecc strength value of 6 bits per 512 bytes of data is a + * conservative guess, given 13 ecc bytes and using bch alg. + * (Assume Galois field order m=15 to allow a margin of error.) + */ + this->ecc.strength = 6; #endif diff --git a/trunk/drivers/mtd/nand/bf5xx_nand.c b/trunk/drivers/mtd/nand/bf5xx_nand.c index 3f1c18599cbd..d7b86b925de5 100644 --- a/trunk/drivers/mtd/nand/bf5xx_nand.c +++ b/trunk/drivers/mtd/nand/bf5xx_nand.c @@ -558,7 +558,7 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, } static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { bf5xx_nand_read_buf(mtd, buf, mtd->writesize); bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -567,7 +567,7 @@ static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip } static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { bf5xx_nand_write_buf(mtd, buf, mtd->writesize); bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); diff --git a/trunk/drivers/mtd/nand/cafe_nand.c b/trunk/drivers/mtd/nand/cafe_nand.c index 41371ba1a811..2a96e1a12062 100644 --- a/trunk/drivers/mtd/nand/cafe_nand.c +++ b/trunk/drivers/mtd/nand/cafe_nand.c @@ -364,27 +364,25 @@ static int cafe_nand_write_oob(struct mtd_info *mtd, /* Don't use -- use nand_read_oob_std for now */ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - return 0; + return 1; } /** * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller expects OOB data read to chip->oob_poi * * The hw generator calculates the error syndrome automatically. Therefor * we need a special oob layout and handling. */ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { struct cafe_priv *cafe = mtd->priv; - unsigned int max_bitflips = 0; cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n", cafe_readl(cafe, NAND_ECC_RESULT), @@ -451,11 +449,10 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, } else { dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n); mtd->ecc_stats.corrected += n; - max_bitflips = max_t(unsigned int, max_bitflips, n); } } - return max_bitflips; + return 0; } static struct nand_ecclayout cafe_oobinfo_2048 = { @@ -521,8 +518,7 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = { static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf, int oob_required) + struct nand_chip *chip, const uint8_t *buf) { struct cafe_priv *cafe = mtd->priv; @@ -534,17 +530,16 @@ static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, } static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page, - int cached, int raw) + const uint8_t *buf, int page, int cached, int raw) { int status; chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); if (unlikely(raw)) - chip->ecc.write_page_raw(mtd, chip, buf, oob_required); + chip->ecc.write_page_raw(mtd, chip, buf); else - chip->ecc.write_page(mtd, chip, buf, oob_required); + chip->ecc.write_page(mtd, chip, buf); /* * Cached progamming disabled for now, Not sure if its worth the @@ -690,7 +685,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, /* Enable the following for a flash based bad block table */ cafe->nand.bbt_options = NAND_BBT_USE_FLASH; - cafe->nand.options = NAND_OWN_BUFFERS; + cafe->nand.options = NAND_NO_AUTOINCR | NAND_OWN_BUFFERS; if (skipbbt) { cafe->nand.options |= NAND_SKIP_BBTSCAN; @@ -893,7 +888,17 @@ static struct pci_driver cafe_nand_pci_driver = { .resume = cafe_nand_resume, }; -module_pci_driver(cafe_nand_pci_driver); +static int __init cafe_nand_init(void) +{ + return pci_register_driver(&cafe_nand_pci_driver); +} + +static void __exit cafe_nand_exit(void) +{ + pci_unregister_driver(&cafe_nand_pci_driver); +} +module_init(cafe_nand_init); +module_exit(cafe_nand_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse "); diff --git a/trunk/drivers/mtd/nand/cs553x_nand.c b/trunk/drivers/mtd/nand/cs553x_nand.c index adb6c3ef37fb..821c34c62500 100644 --- a/trunk/drivers/mtd/nand/cs553x_nand.c +++ b/trunk/drivers/mtd/nand/cs553x_nand.c @@ -240,6 +240,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) /* Enable the following for a flash based bad block table */ this->bbt_options = NAND_BBT_USE_FLASH; + this->options = NAND_NO_AUTOINCR; /* Scan to find existence of the device */ if (nand_scan(new_mtd, 1)) { diff --git a/trunk/drivers/mtd/nand/denali.c b/trunk/drivers/mtd/nand/denali.c index 0650aafa0dd2..a9e57d686297 100644 --- a/trunk/drivers/mtd/nand/denali.c +++ b/trunk/drivers/mtd/nand/denali.c @@ -924,10 +924,9 @@ bool is_erased(uint8_t *buf, int len) #define ECC_LAST_ERR(x) ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO) static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, - uint32_t irq_status, unsigned int *max_bitflips) + uint32_t irq_status) { bool check_erased_page = false; - unsigned int bitflips = 0; if (irq_status & INTR_STATUS__ECC_ERR) { /* read the ECC errors. we'll ignore them for now */ @@ -966,7 +965,6 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, /* correct the ECC error */ buf[offset] ^= err_correction_value; denali->mtd.ecc_stats.corrected++; - bitflips++; } } else { /* if the error is not correctable, need to @@ -986,7 +984,6 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, clear_interrupts(denali); denali_set_intr_modes(denali, true); } - *max_bitflips = bitflips; return check_erased_page; } @@ -1087,7 +1084,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip, * by write_page above. * */ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { /* for regular page writes, we let HW handle all the ECC * data written to the device. */ @@ -1099,7 +1096,7 @@ static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, * write_page() function above. */ static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { /* for raw page writes, we want to disable ECC and simply write whatever data is in the buffer. */ @@ -1113,17 +1110,17 @@ static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, } static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { read_oob_data(mtd, chip->oob_poi, page); - return 0; + return 0; /* notify NAND core to send command to + NAND device. */ } static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { - unsigned int max_bitflips; struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; @@ -1156,7 +1153,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, memcpy(buf, denali->buf.buf, mtd->writesize); - check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips); + check_erased_page = handle_ecc(denali, buf, irq_status); denali_enable_dma(denali, false); if (check_erased_page) { @@ -1170,11 +1167,11 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, denali->mtd.ecc_stats.failed++; } } - return max_bitflips; + return 0; } static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); @@ -1705,4 +1702,17 @@ static struct pci_driver denali_pci_driver = { .remove = denali_pci_remove, }; -module_pci_driver(denali_pci_driver); +static int __devinit denali_init(void) +{ + printk(KERN_INFO "Spectra MTD driver\n"); + return pci_register_driver(&denali_pci_driver); +} + +/* Free memory */ +static void __devexit denali_exit(void) +{ + pci_unregister_driver(&denali_pci_driver); +} + +module_init(denali_init); +module_exit(denali_exit); diff --git a/trunk/drivers/mtd/nand/docg4.c b/trunk/drivers/mtd/nand/docg4.c index a225e49a5623..b08202664543 100644 --- a/trunk/drivers/mtd/nand/docg4.c +++ b/trunk/drivers/mtd/nand/docg4.c @@ -720,7 +720,6 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; uint16_t status, edc_err, *buf16; - int bits_corrected = 0; dev_dbg(doc->dev, "%s: page %08x\n", __func__, page); @@ -773,7 +772,7 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, /* If bitflips are reported, attempt to correct with ecc */ if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) { - bits_corrected = correct_data(mtd, buf, page); + int bits_corrected = correct_data(mtd, buf, page); if (bits_corrected == -EBADMSG) mtd->ecc_stats.failed++; else @@ -782,24 +781,24 @@ static int read_page(struct mtd_info *mtd, struct nand_chip *nand, } writew(0, docptr + DOC_DATAEND); - return bits_corrected; + return 0; } static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { return read_page(mtd, nand, buf, page, false); } static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { return read_page(mtd, nand, buf, page, true); } static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, - int page) + int page, int sndcmd) { struct docg4_priv *doc = nand->priv; void __iomem *docptr = doc->virtadr; @@ -953,13 +952,13 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *nand, } static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { return write_page(mtd, nand, buf, false); } static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { return write_page(mtd, nand, buf, true); } @@ -1003,7 +1002,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd) return -ENOMEM; read_page_prologue(mtd, g4_addr); - status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE); + status = docg4_read_page(mtd, nand, buf, DOCG4_FACTORY_BBT_PAGE); if (status) goto exit; @@ -1080,7 +1079,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) /* write first page of block */ write_page_prologue(mtd, g4_addr); - docg4_write_page(mtd, nand, buf, 1); + docg4_write_page(mtd, nand, buf); ret = pageprog(mtd); if (!ret) mtd->ecc_stats.badblocks++; @@ -1193,7 +1192,8 @@ static void __init init_mtd_structs(struct mtd_info *mtd) nand->ecc.prepad = 8; nand->ecc.bytes = 8; nand->ecc.strength = DOCG4_T; - nand->options = NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE; + nand->options = + NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE | NAND_NO_AUTOINCR; nand->IO_ADDR_R = nand->IO_ADDR_W = doc->virtadr + DOC_IOSPACE_DATA; nand->controller = &nand->hwcontrol; spin_lock_init(&nand->controller->lock); diff --git a/trunk/drivers/mtd/nand/fsl_elbc_nand.c b/trunk/drivers/mtd/nand/fsl_elbc_nand.c index 784293806110..80b5264f0a32 100644 --- a/trunk/drivers/mtd/nand/fsl_elbc_nand.c +++ b/trunk/drivers/mtd/nand/fsl_elbc_nand.c @@ -75,7 +75,6 @@ struct fsl_elbc_fcm_ctrl { unsigned int use_mdr; /* Non zero if the MDR is to be set */ unsigned int oob; /* Non zero if operating on OOB data */ unsigned int counter; /* counter for the initializations */ - unsigned int max_bitflips; /* Saved during READ0 cmd */ }; /* These map to the positions used by the FCM hardware ECC generator */ @@ -254,8 +253,6 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) if (chip->ecc.mode != NAND_ECC_HW) return 0; - elbc_fcm_ctrl->max_bitflips = 0; - if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) { uint32_t lteccr = in_be32(&lbc->lteccr); /* @@ -265,16 +262,11 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) * bits 28-31 are uncorrectable errors, marked elsewhere. * for small page nand only 1 bit is used. * if the ELBC doesn't have the lteccr register it reads 0 - * FIXME: 4 bits can be corrected on NANDs with 2k pages, so - * count the number of sub-pages with bitflips and update - * ecc_stats.corrected accordingly. */ if (lteccr & 0x000F000F) out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */ - if (lteccr & 0x000F0000) { + if (lteccr & 0x000F0000) mtd->ecc_stats.corrected++; - elbc_fcm_ctrl->max_bitflips = 1; - } } return 0; @@ -746,28 +738,26 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) return 0; } -static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int fsl_elbc_read_page(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, + int page) { - struct fsl_elbc_mtd *priv = chip->priv; - struct fsl_lbc_ctrl *ctrl = priv->ctrl; - struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; - fsl_elbc_read_buf(mtd, buf, mtd->writesize); - if (oob_required) - fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL) mtd->ecc_stats.failed++; - return elbc_fcm_ctrl->max_bitflips; + return 0; } /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static void fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) +static void fsl_elbc_write_page(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf) { fsl_elbc_write_buf(mtd, buf, mtd->writesize); fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -805,7 +795,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->bbt_md = &bbt_mirror_descr; /* set up nand options */ - chip->options = NAND_NO_READRDY; + chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; chip->bbt_options = NAND_BBT_USE_FLASH; chip->controller = &elbc_fcm_ctrl->controller; @@ -824,6 +814,11 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->ecc.size = 512; chip->ecc.bytes = 3; chip->ecc.strength = 1; + /* + * FIXME: can hardware ecc correct 4 bitflips if page size is + * 2k? Then does hardware report number of corrections for this + * case? If so, ecc_stats reporting needs to be fixed as well. + */ } else { /* otherwise fall back to default software ECC */ chip->ecc.mode = NAND_ECC_SOFT; diff --git a/trunk/drivers/mtd/nand/fsl_ifc_nand.c b/trunk/drivers/mtd/nand/fsl_ifc_nand.c index 9602c1b7e27e..c30ac7b83d28 100644 --- a/trunk/drivers/mtd/nand/fsl_ifc_nand.c +++ b/trunk/drivers/mtd/nand/fsl_ifc_nand.c @@ -63,7 +63,6 @@ struct fsl_ifc_nand_ctrl { unsigned int oob; /* Non zero if operating on OOB data */ unsigned int eccread; /* Non zero for a full-page ECC read */ unsigned int counter; /* counter for the initializations */ - unsigned int max_bitflips; /* Saved during READ0 cmd */ }; static struct fsl_ifc_nand_ctrl *ifc_nand_ctrl; @@ -263,8 +262,6 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_WPER) dev_err(priv->dev, "NAND Flash Write Protect Error\n"); - nctrl->max_bitflips = 0; - if (nctrl->eccread) { int errors; int bufnum = nctrl->page & priv->bufnum_mask; @@ -293,9 +290,6 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) } mtd->ecc_stats.corrected += errors; - nctrl->max_bitflips = max_t(unsigned int, - nctrl->max_bitflips, - errors); } nctrl->eccread = 0; @@ -381,31 +375,21 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, return; + /* READID must read all 8 possible bytes */ case NAND_CMD_READID: - case NAND_CMD_PARAM: { - int timing = IFC_FIR_OP_RB; - if (command == NAND_CMD_PARAM) - timing = IFC_FIR_OP_RBCD; - out_be32(&ifc->ifc_nand.nand_fir0, (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) | (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | - (timing << IFC_NAND_FIR0_OP2_SHIFT)); + (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); out_be32(&ifc->ifc_nand.nand_fcr0, - command << IFC_NAND_FCR0_CMD0_SHIFT); - out_be32(&ifc->ifc_nand.row3, column); - - /* - * although currently it's 8 bytes for READID, we always read - * the maximum 256 bytes(for PARAM) - */ - out_be32(&ifc->ifc_nand.nand_fbcr, 256); - ifc_nand_ctrl->read_bytes = 256; + NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT); + /* 8 bytes for manuf, device and exts */ + out_be32(&ifc->ifc_nand.nand_fbcr, 8); + ifc_nand_ctrl->read_bytes = 8; set_addr(mtd, 0, 0, 0); fsl_ifc_run_command(mtd); return; - } /* ERASE1 stores the block and page address */ case NAND_CMD_ERASE1: @@ -698,16 +682,15 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) return nand_fsr | NAND_STATUS_WP; } -static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int fsl_ifc_read_page(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, int page) { struct fsl_ifc_mtd *priv = chip->priv; struct fsl_ifc_ctrl *ctrl = priv->ctrl; - struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; fsl_ifc_read_buf(mtd, buf, mtd->writesize); - if (oob_required) - fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); + fsl_ifc_read_buf(mtd, chip->oob_poi, mtd->oobsize); if (ctrl->nand_stat & IFC_NAND_EVTER_STAT_ECCER) dev_err(priv->dev, "NAND Flash ECC Uncorrectable Error\n"); @@ -715,14 +698,15 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip, if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC) mtd->ecc_stats.failed++; - return nctrl->max_bitflips; + return 0; } /* ECC will be calculated automatically, and errors will be detected in * waitfunc. */ -static void fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) +static void fsl_ifc_write_page(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf) { fsl_ifc_write_buf(mtd, buf, mtd->writesize); fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -805,7 +789,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) out_be32(&ifc->ifc_nand.ncfgr, 0x0); /* set up nand options */ - chip->options = NAND_NO_READRDY; + chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR; chip->bbt_options = NAND_BBT_USE_FLASH; @@ -827,7 +811,6 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) /* Hardware generates ECC per 512 Bytes */ chip->ecc.size = 512; chip->ecc.bytes = 8; - chip->ecc.strength = 4; switch (csor & CSOR_NAND_PGS_MASK) { case CSOR_NAND_PGS_512: diff --git a/trunk/drivers/mtd/nand/fsmc_nand.c b/trunk/drivers/mtd/nand/fsmc_nand.c index 38d26240d8b1..1b8330e1155a 100644 --- a/trunk/drivers/mtd/nand/fsmc_nand.c +++ b/trunk/drivers/mtd/nand/fsmc_nand.c @@ -692,7 +692,6 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller expects OOB data read to chip->oob_poi * @page: page number to read * * This routine is needed for fsmc version 8 as reading from NAND chip has to be @@ -702,7 +701,7 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, * max of 8 bits) */ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { struct fsmc_nand_data *host = container_of(mtd, struct fsmc_nand_data, mtd); @@ -721,7 +720,6 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, */ uint16_t ecc_oob[7]; uint8_t *oob = (uint8_t *)&ecc_oob[0]; - unsigned int max_bitflips = 0; for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page); @@ -750,15 +748,13 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, chip->ecc.calculate(mtd, p, &ecc_calc[i]); stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /* @@ -998,9 +994,9 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) return PTR_ERR(host->clk); } - ret = clk_prepare_enable(host->clk); + ret = clk_enable(host->clk); if (ret) - goto err_clk_prepare_enable; + goto err_clk_enable; /* * This device ID is actually a common AMBA ID as used on the @@ -1180,8 +1176,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) if (host->mode == USE_DMA_ACCESS) dma_release_channel(host->read_dma_chan); err_req_read_chnl: - clk_disable_unprepare(host->clk); -err_clk_prepare_enable: + clk_disable(host->clk); +err_clk_enable: clk_put(host->clk); return ret; } @@ -1202,7 +1198,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) dma_release_channel(host->write_dma_chan); dma_release_channel(host->read_dma_chan); } - clk_disable_unprepare(host->clk); + clk_disable(host->clk); clk_put(host->clk); } @@ -1214,7 +1210,7 @@ static int fsmc_nand_suspend(struct device *dev) { struct fsmc_nand_data *host = dev_get_drvdata(dev); if (host) - clk_disable_unprepare(host->clk); + clk_disable(host->clk); return 0; } @@ -1222,7 +1218,7 @@ static int fsmc_nand_resume(struct device *dev) { struct fsmc_nand_data *host = dev_get_drvdata(dev); if (host) { - clk_prepare_enable(host->clk); + clk_enable(host->clk); fsmc_nand_setup(host->regs_va, host->bank, host->nand.options & NAND_BUSWIDTH_16, host->dev_timings); diff --git a/trunk/drivers/mtd/nand/gpmi-nand/bch-regs.h b/trunk/drivers/mtd/nand/gpmi-nand/bch-regs.h index a0924515c396..4effb8c579db 100644 --- a/trunk/drivers/mtd/nand/gpmi-nand/bch-regs.h +++ b/trunk/drivers/mtd/nand/gpmi-nand/bch-regs.h @@ -51,26 +51,15 @@ #define BP_BCH_FLASH0LAYOUT0_ECC0 12 #define BM_BCH_FLASH0LAYOUT0_ECC0 (0xf << BP_BCH_FLASH0LAYOUT0_ECC0) -#define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11 -#define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) -#define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \ - (GPMI_IS_MX6Q(x) \ - ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \ - & MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \ - : (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \ - & BM_BCH_FLASH0LAYOUT0_ECC0) \ - ) +#define BF_BCH_FLASH0LAYOUT0_ECC0(v) \ + (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) & BM_BCH_FLASH0LAYOUT0_ECC0) #define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE 0 #define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ (0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) -#define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ - (0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) -#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \ - (GPMI_IS_MX6Q(x) \ - ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ - : ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ - ) +#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v) \ + (((v) << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)\ + & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) #define HW_BCH_FLASH0LAYOUT1 0x00000090 @@ -83,24 +72,13 @@ #define BP_BCH_FLASH0LAYOUT1_ECCN 12 #define BM_BCH_FLASH0LAYOUT1_ECCN (0xf << BP_BCH_FLASH0LAYOUT1_ECCN) -#define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11 -#define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) -#define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \ - (GPMI_IS_MX6Q(x) \ - ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \ - & MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \ - : (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \ - & BM_BCH_FLASH0LAYOUT1_ECCN) \ - ) +#define BF_BCH_FLASH0LAYOUT1_ECCN(v) \ + (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) & BM_BCH_FLASH0LAYOUT1_ECCN) #define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE 0 #define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ (0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) -#define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ - (0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) -#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \ - (GPMI_IS_MX6Q(x) \ - ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ - : ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ - ) +#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v) \ + (((v) << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ + & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) #endif diff --git a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index a1f43329ad43..e8ea7107932e 100644 --- a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "gpmi-nand.h" #include "gpmi-regs.h" @@ -36,8 +37,6 @@ struct timing_threshod timing_default_threshold = { .max_dll_delay_in_ns = 16, }; -#define MXS_SET_ADDR 0x4 -#define MXS_CLR_ADDR 0x8 /* * Clear the bit and poll it cleared. This is usually called with * a reset address and mask being either SFTRST(bit 31) or CLKGATE @@ -48,7 +47,7 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) int timeout = 0x400; /* clear the bit */ - writel(mask, addr + MXS_CLR_ADDR); + __mxs_clrl(mask, addr); /* * SFTRST needs 3 GPMI clocks to settle, the reference manual @@ -93,11 +92,11 @@ static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) goto error; /* clear CLKGATE */ - writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR); + __mxs_clrl(MODULE_CLKGATE, reset_addr); if (!just_enable) { /* set SFTRST to reset the block */ - writel(MODULE_SFTRST, reset_addr + MXS_SET_ADDR); + __mxs_setl(MODULE_SFTRST, reset_addr); udelay(1); /* poll CLKGATE becoming set */ @@ -224,13 +223,13 @@ int bch_set_geometry(struct gpmi_nand_data *this) /* Configure layout 0. */ writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count) | BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size) - | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this) - | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this), + | BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength) + | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size), r->bch_regs + HW_BCH_FLASH0LAYOUT0); writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size) - | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this) - | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this), + | BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength) + | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size), r->bch_regs + HW_BCH_FLASH0LAYOUT1); /* Set *all* chip selects to use layout 0. */ @@ -256,12 +255,11 @@ static unsigned int ns_to_cycles(unsigned int time, return max(k, min); } -#define DEF_MIN_PROP_DELAY 5 -#define DEF_MAX_PROP_DELAY 9 /* Apply timing to current hardware conditions. */ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, struct gpmi_nfc_hardware_timing *hw) { + struct gpmi_nand_platform_data *pdata = this->pdata; struct timing_threshod *nfc = &timing_default_threshold; struct nand_chip *nand = &this->nand; struct nand_timing target = this->timing; @@ -278,8 +276,8 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, int ideal_sample_delay_in_ns; unsigned int sample_delay_factor; int tEYE; - unsigned int min_prop_delay_in_ns = DEF_MIN_PROP_DELAY; - unsigned int max_prop_delay_in_ns = DEF_MAX_PROP_DELAY; + unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns; + unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns; /* * If there are multiple chips, we need to relax the timings to allow @@ -805,8 +803,7 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip) if (GPMI_IS_MX23(this)) { mask = MX23_BM_GPMI_DEBUG_READY0 << chip; reg = readl(r->gpmi_regs + HW_GPMI_DEBUG); - } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6Q(this)) { - /* MX28 shares the same R/B register as MX6Q. */ + } else if (GPMI_IS_MX28(this)) { mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip); reg = readl(r->gpmi_regs + HW_GPMI_STAT); } else diff --git a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index a05b7b444d4f..b68e04310bd8 100644 --- a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include "gpmi-nand.h" /* add our owner bbt descriptor */ @@ -389,7 +387,7 @@ static void release_bch_irq(struct gpmi_nand_data *this) static bool gpmi_dma_filter(struct dma_chan *chan, void *param) { struct gpmi_nand_data *this = param; - int dma_channel = (int)this->private; + struct resource *r = this->private; if (!mxs_dma_is_apbh(chan)) return false; @@ -401,7 +399,7 @@ static bool gpmi_dma_filter(struct dma_chan *chan, void *param) * for mx28 : MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7 * (These eight channels share the same IRQ!) */ - if (dma_channel == chan->chan_id) { + if (r->start <= chan->chan_id && chan->chan_id <= r->end) { chan->private = &this->dma_data; return true; } @@ -421,45 +419,57 @@ static void release_dma_channels(struct gpmi_nand_data *this) static int __devinit acquire_dma_channels(struct gpmi_nand_data *this) { struct platform_device *pdev = this->pdev; - struct resource *r_dma; - struct device_node *dn; - int dma_channel; - unsigned int ret; - struct dma_chan *dma_chan; - dma_cap_mask_t mask; - - /* dma channel, we only use the first one. */ - dn = pdev->dev.of_node; - ret = of_property_read_u32(dn, "fsl,gpmi-dma-channel", &dma_channel); - if (ret) { - pr_err("unable to get DMA channel from dt.\n"); - goto acquire_err; - } - this->private = (void *)dma_channel; + struct gpmi_nand_platform_data *pdata = this->pdata; + struct resources *res = &this->resources; + struct resource *r, *r_dma; + unsigned int i; - /* gpmi dma interrupt */ + r = platform_get_resource_byname(pdev, IORESOURCE_DMA, + GPMI_NAND_DMA_CHANNELS_RES_NAME); r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ, GPMI_NAND_DMA_INTERRUPT_RES_NAME); - if (!r_dma) { + if (!r || !r_dma) { pr_err("Can't get resource for DMA\n"); - goto acquire_err; + return -ENXIO; } - this->dma_data.chan_irq = r_dma->start; - /* request dma channel */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); + /* used in gpmi_dma_filter() */ + this->private = r; + + for (i = r->start; i <= r->end; i++) { + struct dma_chan *dma_chan; + dma_cap_mask_t mask; - dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); - if (!dma_chan) { - pr_err("dma_request_channel failed.\n"); - goto acquire_err; + if (i - r->start >= pdata->max_chip_count) + break; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* get the DMA interrupt */ + if (r_dma->start == r_dma->end) { + /* only register the first. */ + if (i == r->start) + this->dma_data.chan_irq = r_dma->start; + else + this->dma_data.chan_irq = NO_IRQ; + } else + this->dma_data.chan_irq = r_dma->start + (i - r->start); + + dma_chan = dma_request_channel(mask, gpmi_dma_filter, this); + if (!dma_chan) + goto acquire_err; + + /* fill the first empty item */ + this->dma_chans[i - r->start] = dma_chan; } - this->dma_chans[0] = dma_chan; + res->dma_low_channel = r->start; + res->dma_high_channel = i; return 0; acquire_err: + pr_err("Can't acquire DMA channel %u\n", i); release_dma_channels(this); return -EINVAL; } @@ -841,7 +851,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this, } static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { struct gpmi_nand_data *this = chip->priv; struct bch_geometry *nfc_geo = &this->bch_geometry; @@ -907,31 +917,28 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, mtd->ecc_stats.corrected += corrected; } - if (oob_required) { - /* - * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() - * for details about our policy for delivering the OOB. - * - * We fill the caller's buffer with set bits, and then copy the - * block mark to th caller's buffer. Note that, if block mark - * swapping was necessary, it has already been done, so we can - * rely on the first byte of the auxiliary buffer to contain - * the block mark. - */ - memset(chip->oob_poi, ~0, mtd->oobsize); - chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; + /* + * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() for + * details about our policy for delivering the OOB. + * + * We fill the caller's buffer with set bits, and then copy the block + * mark to th caller's buffer. Note that, if block mark swapping was + * necessary, it has already been done, so we can rely on the first + * byte of the auxiliary buffer to contain the block mark. + */ + memset(chip->oob_poi, ~0, mtd->oobsize); + chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; - read_page_swap_end(this, buf, mtd->writesize, - this->payload_virt, this->payload_phys, - nfc_geo->payload_size, - payload_virt, payload_phys); - } + read_page_swap_end(this, buf, mtd->writesize, + this->payload_virt, this->payload_phys, + nfc_geo->payload_size, + payload_virt, payload_phys); exit_nfc: return ret; } -static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) +static void gpmi_ecc_write_page(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) { struct gpmi_nand_data *this = chip->priv; struct bch_geometry *nfc_geo = &this->bch_geometry; @@ -1070,7 +1077,7 @@ static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, * this driver. */ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { struct gpmi_nand_data *this = chip->priv; @@ -1093,7 +1100,11 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, chip->oob_poi[0] = chip->read_byte(mtd); } - return 0; + /* + * Return true, indicating that the next call to this function must send + * a command. + */ + return true; } static int @@ -1307,7 +1318,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) /* Write the first page of the current stride. */ dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); - chip->ecc.write_page_raw(mtd, chip, buffer, 0); + chip->ecc.write_page_raw(mtd, chip, buffer); chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); /* Wait for the write to finish. */ @@ -1433,10 +1444,6 @@ static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this) if (ret) return ret; - /* Adjust the ECC strength according to the chip. */ - this->nand.ecc.strength = this->bch_geometry.ecc_strength; - this->mtd.ecc_strength = this->bch_geometry.ecc_strength; - /* NAND boot init, depends on the gpmi_set_geometry(). */ return nand_boot_init(this); } @@ -1464,9 +1471,9 @@ void gpmi_nfc_exit(struct gpmi_nand_data *this) static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) { + struct gpmi_nand_platform_data *pdata = this->pdata; struct mtd_info *mtd = &this->mtd; struct nand_chip *chip = &this->nand; - struct mtd_part_parser_data ppdata = {}; int ret; /* init current chip */ @@ -1495,7 +1502,6 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) chip->options |= NAND_NO_SUBPAGE_WRITE; chip->ecc.mode = NAND_ECC_HW; chip->ecc.size = 1; - chip->ecc.strength = 8; chip->ecc.layout = &gpmi_hw_ecclayout; /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */ @@ -1505,14 +1511,14 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) if (ret) goto err_out; - ret = nand_scan(mtd, 1); + ret = nand_scan(mtd, pdata->max_chip_count); if (ret) { pr_err("Chip scan failed\n"); goto err_out; } - ppdata.of_node = this->pdev->dev.of_node; - ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); + ret = mtd_device_parse_register(mtd, NULL, NULL, + pdata->partitions, pdata->partition_count); if (ret) goto err_out; return 0; @@ -1522,41 +1528,12 @@ static int __devinit gpmi_nfc_init(struct gpmi_nand_data *this) return ret; } -static const struct platform_device_id gpmi_ids[] = { - { .name = "imx23-gpmi-nand", .driver_data = IS_MX23, }, - { .name = "imx28-gpmi-nand", .driver_data = IS_MX28, }, - { .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, }, - {}, -}; - -static const struct of_device_id gpmi_nand_id_table[] = { - { - .compatible = "fsl,imx23-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX23] - }, { - .compatible = "fsl,imx28-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX28] - }, { - .compatible = "fsl,imx6q-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX6Q] - }, {} -}; -MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); - static int __devinit gpmi_nand_probe(struct platform_device *pdev) { + struct gpmi_nand_platform_data *pdata = pdev->dev.platform_data; struct gpmi_nand_data *this; - const struct of_device_id *of_id; int ret; - of_id = of_match_device(gpmi_nand_id_table, &pdev->dev); - if (of_id) { - pdev->id_entry = of_id->data; - } else { - pr_err("Failed to find the right device id.\n"); - return -ENOMEM; - } - this = kzalloc(sizeof(*this), GFP_KERNEL); if (!this) { pr_err("Failed to allocate per-device memory\n"); @@ -1566,6 +1543,13 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev) platform_set_drvdata(pdev, this); this->pdev = pdev; this->dev = &pdev->dev; + this->pdata = pdata; + + if (pdata->platform_init) { + ret = pdata->platform_init(); + if (ret) + goto platform_init_error; + } ret = acquire_resources(this); if (ret) @@ -1583,6 +1567,7 @@ static int __devinit gpmi_nand_probe(struct platform_device *pdev) exit_nfc_init: release_resources(this); +platform_init_error: exit_acquire_resources: platform_set_drvdata(pdev, NULL); kfree(this); @@ -1600,10 +1585,19 @@ static int __exit gpmi_nand_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id gpmi_ids[] = { + { + .name = "imx23-gpmi-nand", + .driver_data = IS_MX23, + }, { + .name = "imx28-gpmi-nand", + .driver_data = IS_MX28, + }, {}, +}; + static struct platform_driver gpmi_nand_driver = { .driver = { .name = "gpmi-nand", - .of_match_table = gpmi_nand_id_table, }, .probe = gpmi_nand_probe, .remove = __exit_p(gpmi_nand_remove), diff --git a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index ce5daa160920..ec6180d4ff8f 100644 --- a/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/trunk/drivers/mtd/nand/gpmi-nand/gpmi-nand.h @@ -266,10 +266,8 @@ extern int gpmi_read_page(struct gpmi_nand_data *, #define STATUS_UNCORRECTABLE 0xfe /* Use the platform_id to distinguish different Archs. */ -#define IS_MX23 0x0 -#define IS_MX28 0x1 -#define IS_MX6Q 0x2 +#define IS_MX23 0x1 +#define IS_MX28 0x2 #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) -#define GPMI_IS_MX6Q(x) ((x)->pdev->id_entry->driver_data == IS_MX6Q) #endif diff --git a/trunk/drivers/mtd/nand/h1910.c b/trunk/drivers/mtd/nand/h1910.c index 50166e93ba96..9bf5ce5fa22d 100644 --- a/trunk/drivers/mtd/nand/h1910.c +++ b/trunk/drivers/mtd/nand/h1910.c @@ -124,6 +124,7 @@ static int __init h1910_init(void) /* 15 us command delay time */ this->chip_delay = 50; this->ecc.mode = NAND_ECC_SOFT; + this->options = NAND_NO_AUTOINCR; /* Scan to find existence of the device */ if (nand_scan(h1910_nand_mtd, 1)) { diff --git a/trunk/drivers/mtd/nand/jz4740_nand.c b/trunk/drivers/mtd/nand/jz4740_nand.c index a6fa884ae49b..e4147e8acb7c 100644 --- a/trunk/drivers/mtd/nand/jz4740_nand.c +++ b/trunk/drivers/mtd/nand/jz4740_nand.c @@ -332,7 +332,11 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) chip->ecc.mode = NAND_ECC_HW_OOB_FIRST; chip->ecc.size = 512; chip->ecc.bytes = 9; - chip->ecc.strength = 4; + chip->ecc.strength = 2; + /* + * FIXME: ecc_strength value of 2 bits per 512 bytes of data is a + * conservative guess, given 9 ecc bytes and reed-solomon alg. + */ if (pdata) chip->ecc.layout = pdata->ecc_layout; diff --git a/trunk/drivers/mtd/nand/mpc5121_nfc.c b/trunk/drivers/mtd/nand/mpc5121_nfc.c index c259c24d7986..c240cf1af961 100644 --- a/trunk/drivers/mtd/nand/mpc5121_nfc.c +++ b/trunk/drivers/mtd/nand/mpc5121_nfc.c @@ -734,6 +734,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op) chip->write_buf = mpc5121_nfc_write_buf; chip->verify_buf = mpc5121_nfc_verify_buf; chip->select_chip = mpc5121_nfc_select_chip; + chip->options = NAND_NO_AUTOINCR; chip->bbt_options = NAND_BBT_USE_FLASH; chip->ecc.mode = NAND_ECC_SOFT; diff --git a/trunk/drivers/mtd/nand/mxc_nand.c b/trunk/drivers/mtd/nand/mxc_nand.c index c58e6a93f445..9e374e9bd296 100644 --- a/trunk/drivers/mtd/nand/mxc_nand.c +++ b/trunk/drivers/mtd/nand/mxc_nand.c @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include #include @@ -142,47 +140,13 @@ #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) -struct mxc_nand_host; - -struct mxc_nand_devtype_data { - void (*preset)(struct mtd_info *); - void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); - void (*send_addr)(struct mxc_nand_host *, uint16_t, int); - void (*send_page)(struct mtd_info *, unsigned int); - void (*send_read_id)(struct mxc_nand_host *); - uint16_t (*get_dev_status)(struct mxc_nand_host *); - int (*check_int)(struct mxc_nand_host *); - void (*irq_control)(struct mxc_nand_host *, int); - u32 (*get_ecc_status)(struct mxc_nand_host *); - struct nand_ecclayout *ecclayout_512, *ecclayout_2k, *ecclayout_4k; - void (*select_chip)(struct mtd_info *mtd, int chip); - int (*correct_data)(struct mtd_info *mtd, u_char *dat, - u_char *read_ecc, u_char *calc_ecc); - - /* - * On i.MX21 the CONFIG2:INT bit cannot be read if interrupts are masked - * (CONFIG1:INT_MSK is set). To handle this the driver uses - * enable_irq/disable_irq_nosync instead of CONFIG1:INT_MSK - */ - int irqpending_quirk; - int needs_ip; - - size_t regs_offset; - size_t spare0_offset; - size_t axi_offset; - - int spare_len; - int eccbytes; - int eccsize; -}; - struct mxc_nand_host { struct mtd_info mtd; struct nand_chip nand; struct device *dev; - void __iomem *spare0; - void __iomem *main_area0; + void *spare0; + void *main_area0; void __iomem *base; void __iomem *regs; @@ -199,9 +163,16 @@ struct mxc_nand_host { uint8_t *data_buf; unsigned int buf_start; - - const struct mxc_nand_devtype_data *devtype_data; - struct mxc_nand_platform_data pdata; + int spare_len; + + void (*preset)(struct mtd_info *); + void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); + void (*send_addr)(struct mxc_nand_host *, uint16_t, int); + void (*send_page)(struct mtd_info *, unsigned int); + void (*send_read_id)(struct mxc_nand_host *); + uint16_t (*get_dev_status)(struct mxc_nand_host *); + int (*check_int)(struct mxc_nand_host *); + void (*irq_control)(struct mxc_nand_host *, int); }; /* OOB placement block for use with hardware ecc generation */ @@ -271,7 +242,21 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { } }; -static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL }; +static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL }; + +static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) +{ + struct mxc_nand_host *host = dev_id; + + if (!host->check_int(host)) + return IRQ_NONE; + + host->irq_control(host, 0); + + complete(&host->op_completion); + + return IRQ_HANDLED; +} static int check_int_v3(struct mxc_nand_host *host) { @@ -295,12 +280,26 @@ static int check_int_v1_v2(struct mxc_nand_host *host) if (!(tmp & NFC_V1_V2_CONFIG2_INT)) return 0; - if (!host->devtype_data->irqpending_quirk) + if (!cpu_is_mx21()) writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); return 1; } +/* + * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit + * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the + * driver can enable/disable the irq line rather than simply masking the + * interrupts. + */ +static void irq_control_mx21(struct mxc_nand_host *host, int activate) +{ + if (activate) + enable_irq(host->irq); + else + disable_irq_nosync(host->irq); +} + static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) { uint16_t tmp; @@ -329,47 +328,6 @@ static void irq_control_v3(struct mxc_nand_host *host, int activate) writel(tmp, NFC_V3_CONFIG2); } -static void irq_control(struct mxc_nand_host *host, int activate) -{ - if (host->devtype_data->irqpending_quirk) { - if (activate) - enable_irq(host->irq); - else - disable_irq_nosync(host->irq); - } else { - host->devtype_data->irq_control(host, activate); - } -} - -static u32 get_ecc_status_v1(struct mxc_nand_host *host) -{ - return readw(NFC_V1_V2_ECC_STATUS_RESULT); -} - -static u32 get_ecc_status_v2(struct mxc_nand_host *host) -{ - return readl(NFC_V1_V2_ECC_STATUS_RESULT); -} - -static u32 get_ecc_status_v3(struct mxc_nand_host *host) -{ - return readl(NFC_V3_ECC_STATUS_RESULT); -} - -static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) -{ - struct mxc_nand_host *host = dev_id; - - if (!host->devtype_data->check_int(host)) - return IRQ_NONE; - - irq_control(host, 0); - - complete(&host->op_completion); - - return IRQ_HANDLED; -} - /* This function polls the NANDFC to wait for the basic operation to * complete by checking the INT bit of config2 register. */ @@ -378,14 +336,14 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) int max_retries = 8000; if (useirq) { - if (!host->devtype_data->check_int(host)) { + if (!host->check_int(host)) { INIT_COMPLETION(host->op_completion); - irq_control(host, 1); + host->irq_control(host, 1); wait_for_completion(&host->op_completion); } } else { while (max_retries-- > 0) { - if (host->devtype_data->check_int(host)) + if (host->check_int(host)) break; udelay(1); @@ -416,7 +374,7 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) writew(cmd, NFC_V1_V2_FLASH_CMD); writew(NFC_CMD, NFC_V1_V2_CONFIG2); - if (host->devtype_data->irqpending_quirk && (cmd == NAND_CMD_RESET)) { + if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { int max_retries = 100; /* Reset completion is indicated by NFC_CONFIG2 */ /* being set to 0 */ @@ -475,27 +433,13 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops) wait_op_done(host, false); } -static void send_page_v2(struct mtd_info *mtd, unsigned int ops) -{ - struct nand_chip *nand_chip = mtd->priv; - struct mxc_nand_host *host = nand_chip->priv; - - /* NANDFC buffer 0 is used for page read/write */ - writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); - - writew(ops, NFC_V1_V2_CONFIG2); - - /* Wait for operation to complete */ - wait_op_done(host, true); -} - -static void send_page_v1(struct mtd_info *mtd, unsigned int ops) +static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; int bufs, i; - if (mtd->writesize > 512) + if (nfc_is_v1() && mtd->writesize > 512) bufs = 4; else bufs = 1; @@ -519,7 +463,7 @@ static void send_read_id_v3(struct mxc_nand_host *host) wait_op_done(host, true); - memcpy_fromio(host->data_buf, host->main_area0, 16); + memcpy(host->data_buf, host->main_area0, 16); } /* Request the NANDFC to perform a read of the NAND device ID. */ @@ -535,7 +479,7 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) /* Wait for operation to complete */ wait_op_done(host, true); - memcpy_fromio(host->data_buf, host->main_area0, 16); + memcpy(host->data_buf, host->main_area0, 16); if (this->options & NAND_BUSWIDTH_16) { /* compress the ID info */ @@ -611,7 +555,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, * additional correction. 2-Bit errors cannot be corrected by * HW ECC, so we need to return failure */ - uint16_t ecc_status = get_ecc_status_v1(host); + uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { pr_debug("MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); @@ -636,7 +580,10 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, no_subpages = mtd->writesize >> 9; - ecc_stat = host->devtype_data->get_ecc_status(host); + if (nfc_is_v21()) + ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); + else + ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT); do { err = ecc_stat & ecc_bit_mask; @@ -669,7 +616,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) /* Check for status request */ if (host->status_request) - return host->devtype_data->get_dev_status(host) & 0xFF; + return host->get_dev_status(host) & 0xFF; ret = *(uint8_t *)(host->data_buf + host->buf_start); host->buf_start++; @@ -735,7 +682,7 @@ static int mxc_nand_verify_buf(struct mtd_info *mtd, /* This function is used by upper layer for select and * deselect of the NAND chip */ -static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) +static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; @@ -754,30 +701,11 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip) clk_prepare_enable(host->clk); host->clk_act = 1; } -} -static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) -{ - struct nand_chip *nand_chip = mtd->priv; - struct mxc_nand_host *host = nand_chip->priv; - - if (chip == -1) { - /* Disable the NFC clock */ - if (host->clk_act) { - clk_disable(host->clk); - host->clk_act = 0; - } - return; - } - - if (!host->clk_act) { - /* Enable the NFC clock */ - clk_enable(host->clk); - host->clk_act = 1; + if (nfc_is_v21()) { + host->active_cs = chip; + writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); } - - host->active_cs = chip; - writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); } /* @@ -790,23 +718,23 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) u16 i, j; u16 n = mtd->writesize >> 9; u8 *d = host->data_buf + mtd->writesize; - u8 __iomem *s = host->spare0; - u16 t = host->devtype_data->spare_len; + u8 *s = host->spare0; + u16 t = host->spare_len; j = (mtd->oobsize / n >> 1) << 1; if (bfrom) { for (i = 0; i < n - 1; i++) - memcpy_fromio(d + i * j, s + i * t, j); + memcpy(d + i * j, s + i * t, j); /* the last section */ - memcpy_fromio(d + i * j, s + i * t, mtd->oobsize - i * j); + memcpy(d + i * j, s + i * t, mtd->oobsize - i * j); } else { for (i = 0; i < n - 1; i++) - memcpy_toio(&s[i * t], &d[i * j], j); + memcpy(&s[i * t], &d[i * j], j); /* the last section */ - memcpy_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j); + memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j); } } @@ -823,44 +751,34 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) * perform a read/write buf operation, the saved column * address is used to index into the full page. */ - host->devtype_data->send_addr(host, 0, page_addr == -1); + host->send_addr(host, 0, page_addr == -1); if (mtd->writesize > 512) /* another col addr cycle for 2k page */ - host->devtype_data->send_addr(host, 0, false); + host->send_addr(host, 0, false); } /* Write out page address, if necessary */ if (page_addr != -1) { /* paddr_0 - p_addr_7 */ - host->devtype_data->send_addr(host, (page_addr & 0xff), false); + host->send_addr(host, (page_addr & 0xff), false); if (mtd->writesize > 512) { if (mtd->size >= 0x10000000) { /* paddr_8 - paddr_15 */ - host->devtype_data->send_addr(host, - (page_addr >> 8) & 0xff, - false); - host->devtype_data->send_addr(host, - (page_addr >> 16) & 0xff, - true); + host->send_addr(host, (page_addr >> 8) & 0xff, false); + host->send_addr(host, (page_addr >> 16) & 0xff, true); } else /* paddr_8 - paddr_15 */ - host->devtype_data->send_addr(host, - (page_addr >> 8) & 0xff, true); + host->send_addr(host, (page_addr >> 8) & 0xff, true); } else { /* One more address cycle for higher density devices */ if (mtd->size >= 0x4000000) { /* paddr_8 - paddr_15 */ - host->devtype_data->send_addr(host, - (page_addr >> 8) & 0xff, - false); - host->devtype_data->send_addr(host, - (page_addr >> 16) & 0xff, - true); + host->send_addr(host, (page_addr >> 8) & 0xff, false); + host->send_addr(host, (page_addr >> 16) & 0xff, true); } else /* paddr_8 - paddr_15 */ - host->devtype_data->send_addr(host, - (page_addr >> 8) & 0xff, true); + host->send_addr(host, (page_addr >> 8) & 0xff, true); } } } @@ -882,35 +800,7 @@ static int get_eccsize(struct mtd_info *mtd) return 8; } -static void preset_v1(struct mtd_info *mtd) -{ - struct nand_chip *nand_chip = mtd->priv; - struct mxc_nand_host *host = nand_chip->priv; - uint16_t config1 = 0; - - if (nand_chip->ecc.mode == NAND_ECC_HW) - config1 |= NFC_V1_V2_CONFIG1_ECC_EN; - - if (!host->devtype_data->irqpending_quirk) - config1 |= NFC_V1_V2_CONFIG1_INT_MSK; - - host->eccsize = 1; - - writew(config1, NFC_V1_V2_CONFIG1); - /* preset operation */ - - /* Unlock the internal RAM Buffer */ - writew(0x2, NFC_V1_V2_CONFIG); - - /* Blocks to be unlocked */ - writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); - writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); - - /* Unlock Block Command for given address range */ - writew(0x4, NFC_V1_V2_WRPROT); -} - -static void preset_v2(struct mtd_info *mtd) +static void preset_v1_v2(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; @@ -919,12 +809,13 @@ static void preset_v2(struct mtd_info *mtd) if (nand_chip->ecc.mode == NAND_ECC_HW) config1 |= NFC_V1_V2_CONFIG1_ECC_EN; - config1 |= NFC_V2_CONFIG1_FP_INT; + if (nfc_is_v21()) + config1 |= NFC_V2_CONFIG1_FP_INT; - if (!host->devtype_data->irqpending_quirk) + if (!cpu_is_mx21()) config1 |= NFC_V1_V2_CONFIG1_INT_MSK; - if (mtd->writesize) { + if (nfc_is_v21() && mtd->writesize) { uint16_t pages_per_block = mtd->erasesize / mtd->writesize; host->eccsize = get_eccsize(mtd); @@ -943,14 +834,20 @@ static void preset_v2(struct mtd_info *mtd) writew(0x2, NFC_V1_V2_CONFIG); /* Blocks to be unlocked */ - writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); - writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); - writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); - writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); - writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); - writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); - writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); - writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); + if (nfc_is_v21()) { + writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR0); + writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR1); + writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR2); + writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR3); + writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR0); + writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR1); + writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR2); + writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR3); + } else if (nfc_is_v1()) { + writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); + writew(0xffff, NFC_V1_UNLOCKEND_BLKADDR); + } else + BUG(); /* Unlock Block Command for given address range */ writew(0x4, NFC_V1_V2_WRPROT); @@ -1040,15 +937,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, /* Command pre-processing step */ switch (command) { case NAND_CMD_RESET: - host->devtype_data->preset(mtd); - host->devtype_data->send_cmd(host, command, false); + host->preset(mtd); + host->send_cmd(host, command, false); break; case NAND_CMD_STATUS: host->buf_start = 0; host->status_request = true; - host->devtype_data->send_cmd(host, command, true); + host->send_cmd(host, command, true); mxc_do_addr_cycle(mtd, column, page_addr); break; @@ -1061,16 +958,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, command = NAND_CMD_READ0; /* only READ0 is valid */ - host->devtype_data->send_cmd(host, command, false); + host->send_cmd(host, command, false); mxc_do_addr_cycle(mtd, column, page_addr); if (mtd->writesize > 512) - host->devtype_data->send_cmd(host, - NAND_CMD_READSTART, true); + host->send_cmd(host, NAND_CMD_READSTART, true); - host->devtype_data->send_page(mtd, NFC_OUTPUT); + host->send_page(mtd, NFC_OUTPUT); - memcpy_fromio(host->data_buf, host->main_area0, mtd->writesize); + memcpy(host->data_buf, host->main_area0, mtd->writesize); copy_spare(mtd, true); break; @@ -1081,28 +977,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, host->buf_start = column; - host->devtype_data->send_cmd(host, command, false); + host->send_cmd(host, command, false); mxc_do_addr_cycle(mtd, column, page_addr); break; case NAND_CMD_PAGEPROG: - memcpy_toio(host->main_area0, host->data_buf, mtd->writesize); + memcpy(host->main_area0, host->data_buf, mtd->writesize); copy_spare(mtd, false); - host->devtype_data->send_page(mtd, NFC_INPUT); - host->devtype_data->send_cmd(host, command, true); + host->send_page(mtd, NFC_INPUT); + host->send_cmd(host, command, true); mxc_do_addr_cycle(mtd, column, page_addr); break; case NAND_CMD_READID: - host->devtype_data->send_cmd(host, command, true); + host->send_cmd(host, command, true); mxc_do_addr_cycle(mtd, column, page_addr); - host->devtype_data->send_read_id(host); + host->send_read_id(host); host->buf_start = column; break; case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: - host->devtype_data->send_cmd(host, command, false); + host->send_cmd(host, command, false); mxc_do_addr_cycle(mtd, column, page_addr); break; @@ -1136,191 +1032,15 @@ static struct nand_bbt_descr bbt_mirror_descr = { .pattern = mirror_pattern, }; -/* v1 + irqpending_quirk: i.MX21 */ -static const struct mxc_nand_devtype_data imx21_nand_devtype_data = { - .preset = preset_v1, - .send_cmd = send_cmd_v1_v2, - .send_addr = send_addr_v1_v2, - .send_page = send_page_v1, - .send_read_id = send_read_id_v1_v2, - .get_dev_status = get_dev_status_v1_v2, - .check_int = check_int_v1_v2, - .irq_control = irq_control_v1_v2, - .get_ecc_status = get_ecc_status_v1, - .ecclayout_512 = &nandv1_hw_eccoob_smallpage, - .ecclayout_2k = &nandv1_hw_eccoob_largepage, - .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ - .select_chip = mxc_nand_select_chip_v1_v3, - .correct_data = mxc_nand_correct_data_v1, - .irqpending_quirk = 1, - .needs_ip = 0, - .regs_offset = 0xe00, - .spare0_offset = 0x800, - .spare_len = 16, - .eccbytes = 3, - .eccsize = 1, -}; - -/* v1 + !irqpending_quirk: i.MX27, i.MX31 */ -static const struct mxc_nand_devtype_data imx27_nand_devtype_data = { - .preset = preset_v1, - .send_cmd = send_cmd_v1_v2, - .send_addr = send_addr_v1_v2, - .send_page = send_page_v1, - .send_read_id = send_read_id_v1_v2, - .get_dev_status = get_dev_status_v1_v2, - .check_int = check_int_v1_v2, - .irq_control = irq_control_v1_v2, - .get_ecc_status = get_ecc_status_v1, - .ecclayout_512 = &nandv1_hw_eccoob_smallpage, - .ecclayout_2k = &nandv1_hw_eccoob_largepage, - .ecclayout_4k = &nandv1_hw_eccoob_smallpage, /* XXX: needs fix */ - .select_chip = mxc_nand_select_chip_v1_v3, - .correct_data = mxc_nand_correct_data_v1, - .irqpending_quirk = 0, - .needs_ip = 0, - .regs_offset = 0xe00, - .spare0_offset = 0x800, - .axi_offset = 0, - .spare_len = 16, - .eccbytes = 3, - .eccsize = 1, -}; - -/* v21: i.MX25, i.MX35 */ -static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { - .preset = preset_v2, - .send_cmd = send_cmd_v1_v2, - .send_addr = send_addr_v1_v2, - .send_page = send_page_v2, - .send_read_id = send_read_id_v1_v2, - .get_dev_status = get_dev_status_v1_v2, - .check_int = check_int_v1_v2, - .irq_control = irq_control_v1_v2, - .get_ecc_status = get_ecc_status_v2, - .ecclayout_512 = &nandv2_hw_eccoob_smallpage, - .ecclayout_2k = &nandv2_hw_eccoob_largepage, - .ecclayout_4k = &nandv2_hw_eccoob_4k, - .select_chip = mxc_nand_select_chip_v2, - .correct_data = mxc_nand_correct_data_v2_v3, - .irqpending_quirk = 0, - .needs_ip = 0, - .regs_offset = 0x1e00, - .spare0_offset = 0x1000, - .axi_offset = 0, - .spare_len = 64, - .eccbytes = 9, - .eccsize = 0, -}; - -/* v3: i.MX51, i.MX53 */ -static const struct mxc_nand_devtype_data imx51_nand_devtype_data = { - .preset = preset_v3, - .send_cmd = send_cmd_v3, - .send_addr = send_addr_v3, - .send_page = send_page_v3, - .send_read_id = send_read_id_v3, - .get_dev_status = get_dev_status_v3, - .check_int = check_int_v3, - .irq_control = irq_control_v3, - .get_ecc_status = get_ecc_status_v3, - .ecclayout_512 = &nandv2_hw_eccoob_smallpage, - .ecclayout_2k = &nandv2_hw_eccoob_largepage, - .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ - .select_chip = mxc_nand_select_chip_v1_v3, - .correct_data = mxc_nand_correct_data_v2_v3, - .irqpending_quirk = 0, - .needs_ip = 1, - .regs_offset = 0, - .spare0_offset = 0x1000, - .axi_offset = 0x1e00, - .spare_len = 64, - .eccbytes = 0, - .eccsize = 0, -}; - -#ifdef CONFIG_OF_MTD -static const struct of_device_id mxcnd_dt_ids[] = { - { - .compatible = "fsl,imx21-nand", - .data = &imx21_nand_devtype_data, - }, { - .compatible = "fsl,imx27-nand", - .data = &imx27_nand_devtype_data, - }, { - .compatible = "fsl,imx25-nand", - .data = &imx25_nand_devtype_data, - }, { - .compatible = "fsl,imx51-nand", - .data = &imx51_nand_devtype_data, - }, - { /* sentinel */ } -}; - -static int __init mxcnd_probe_dt(struct mxc_nand_host *host) -{ - struct device_node *np = host->dev->of_node; - struct mxc_nand_platform_data *pdata = &host->pdata; - const struct of_device_id *of_id = - of_match_device(mxcnd_dt_ids, host->dev); - int buswidth; - - if (!np) - return 1; - - if (of_get_nand_ecc_mode(np) >= 0) - pdata->hw_ecc = 1; - - pdata->flash_bbt = of_get_nand_on_flash_bbt(np); - - buswidth = of_get_nand_bus_width(np); - if (buswidth < 0) - return buswidth; - - pdata->width = buswidth / 8; - - host->devtype_data = of_id->data; - - return 0; -} -#else -static int __init mxcnd_probe_dt(struct mxc_nand_host *host) -{ - return 1; -} -#endif - -static int __init mxcnd_probe_pdata(struct mxc_nand_host *host) -{ - struct mxc_nand_platform_data *pdata = host->dev->platform_data; - - if (!pdata) - return -ENODEV; - - host->pdata = *pdata; - - if (nfc_is_v1()) { - if (cpu_is_mx21()) - host->devtype_data = &imx21_nand_devtype_data; - else - host->devtype_data = &imx27_nand_devtype_data; - } else if (nfc_is_v21()) { - host->devtype_data = &imx25_nand_devtype_data; - } else if (nfc_is_v3_2()) { - host->devtype_data = &imx51_nand_devtype_data; - } else - BUG(); - - return 0; -} - static int __init mxcnd_probe(struct platform_device *pdev) { struct nand_chip *this; struct mtd_info *mtd; + struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; struct mxc_nand_host *host; struct resource *res; int err = 0; + struct nand_ecclayout *oob_smallpage, *oob_largepage; /* Allocate memory for MTD device structure and private data */ host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE + @@ -1345,6 +1065,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->priv = host; this->dev_ready = mxc_nand_dev_ready; this->cmdfunc = mxc_nand_command; + this->select_chip = mxc_nand_select_chip; this->read_byte = mxc_nand_read_byte; this->read_word = mxc_nand_read_word; this->write_buf = mxc_nand_write_buf; @@ -1374,26 +1095,36 @@ static int __init mxcnd_probe(struct platform_device *pdev) host->main_area0 = host->base; - err = mxcnd_probe_dt(host); - if (err > 0) - err = mxcnd_probe_pdata(host); - if (err < 0) - goto eirq; - - if (host->devtype_data->regs_offset) - host->regs = host->base + host->devtype_data->regs_offset; - host->spare0 = host->base + host->devtype_data->spare0_offset; - if (host->devtype_data->axi_offset) - host->regs_axi = host->base + host->devtype_data->axi_offset; - - this->ecc.bytes = host->devtype_data->eccbytes; - host->eccsize = host->devtype_data->eccsize; - - this->select_chip = host->devtype_data->select_chip; - this->ecc.size = 512; - this->ecc.layout = host->devtype_data->ecclayout_512; + if (nfc_is_v1() || nfc_is_v21()) { + host->preset = preset_v1_v2; + host->send_cmd = send_cmd_v1_v2; + host->send_addr = send_addr_v1_v2; + host->send_page = send_page_v1_v2; + host->send_read_id = send_read_id_v1_v2; + host->get_dev_status = get_dev_status_v1_v2; + host->check_int = check_int_v1_v2; + if (cpu_is_mx21()) + host->irq_control = irq_control_mx21; + else + host->irq_control = irq_control_v1_v2; + } - if (host->devtype_data->needs_ip) { + if (nfc_is_v21()) { + host->regs = host->base + 0x1e00; + host->spare0 = host->base + 0x1000; + host->spare_len = 64; + oob_smallpage = &nandv2_hw_eccoob_smallpage; + oob_largepage = &nandv2_hw_eccoob_largepage; + this->ecc.bytes = 9; + } else if (nfc_is_v1()) { + host->regs = host->base + 0xe00; + host->spare0 = host->base + 0x800; + host->spare_len = 16; + oob_smallpage = &nandv1_hw_eccoob_smallpage; + oob_largepage = &nandv1_hw_eccoob_largepage; + this->ecc.bytes = 3; + host->eccsize = 1; + } else if (nfc_is_v3_2()) { res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { err = -ENODEV; @@ -1404,22 +1135,42 @@ static int __init mxcnd_probe(struct platform_device *pdev) err = -ENOMEM; goto eirq; } - } + host->regs_axi = host->base + 0x1e00; + host->spare0 = host->base + 0x1000; + host->spare_len = 64; + host->preset = preset_v3; + host->send_cmd = send_cmd_v3; + host->send_addr = send_addr_v3; + host->send_page = send_page_v3; + host->send_read_id = send_read_id_v3; + host->check_int = check_int_v3; + host->get_dev_status = get_dev_status_v3; + host->irq_control = irq_control_v3; + oob_smallpage = &nandv2_hw_eccoob_smallpage; + oob_largepage = &nandv2_hw_eccoob_largepage; + } else + BUG(); + + this->ecc.size = 512; + this->ecc.layout = oob_smallpage; - if (host->pdata.hw_ecc) { + if (pdata->hw_ecc) { this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; - this->ecc.correct = host->devtype_data->correct_data; + if (nfc_is_v1()) + this->ecc.correct = mxc_nand_correct_data_v1; + else + this->ecc.correct = mxc_nand_correct_data_v2_v3; this->ecc.mode = NAND_ECC_HW; } else { this->ecc.mode = NAND_ECC_SOFT; } - /* NAND bus width determines access functions used by upper layer */ - if (host->pdata.width == 2) + /* NAND bus width determines access funtions used by upper layer */ + if (pdata->width == 2) this->options |= NAND_BUSWIDTH_16; - if (host->pdata.flash_bbt) { + if (pdata->flash_bbt) { this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; /* update flash based bbt */ @@ -1431,25 +1182,28 @@ static int __init mxcnd_probe(struct platform_device *pdev) host->irq = platform_get_irq(pdev, 0); /* - * Use host->devtype_data->irq_control() here instead of irq_control() - * because we must not disable_irq_nosync without having requested the - * irq. + * mask the interrupt. For i.MX21 explicitely call + * irq_control_v1_v2 to use the mask bit. We can't call + * disable_irq_nosync() for an interrupt we do not own yet. */ - host->devtype_data->irq_control(host, 0); + if (cpu_is_mx21()) + irq_control_v1_v2(host, 0); + else + host->irq_control(host, 0); err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); if (err) goto eirq; + host->irq_control(host, 0); + /* - * Now that we "own" the interrupt make sure the interrupt mask bit is - * cleared on i.MX21. Otherwise we can't read the interrupt status bit - * on this machine. + * Now that the interrupt is disabled make sure the interrupt + * mask bit is cleared on i.MX21. Otherwise we can't read + * the interrupt status bit on this machine. */ - if (host->devtype_data->irqpending_quirk) { - disable_irq_nosync(host->irq); - host->devtype_data->irq_control(host, 1); - } + if (cpu_is_mx21()) + irq_control_v1_v2(host, 1); /* first scan to find the device and get the page size */ if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) { @@ -1458,12 +1212,18 @@ static int __init mxcnd_probe(struct platform_device *pdev) } /* Call preset again, with correct writesize this time */ - host->devtype_data->preset(mtd); + host->preset(mtd); if (mtd->writesize == 2048) - this->ecc.layout = host->devtype_data->ecclayout_2k; - else if (mtd->writesize == 4096) - this->ecc.layout = host->devtype_data->ecclayout_4k; + this->ecc.layout = oob_largepage; + if (nfc_is_v21() && mtd->writesize == 4096) + this->ecc.layout = &nandv2_hw_eccoob_4k; + + /* second phase scan */ + if (nand_scan_tail(mtd)) { + err = -ENXIO; + goto escan; + } if (this->ecc.mode == NAND_ECC_HW) { if (nfc_is_v1()) @@ -1472,19 +1232,9 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->ecc.strength = (host->eccsize == 4) ? 4 : 8; } - /* second phase scan */ - if (nand_scan_tail(mtd)) { - err = -ENXIO; - goto escan; - } - /* Register the partitions */ - mtd_device_parse_register(mtd, part_probes, - &(struct mtd_part_parser_data){ - .of_node = pdev->dev.of_node, - }, - host->pdata.parts, - host->pdata.nr_parts); + mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts, + pdata->nr_parts); platform_set_drvdata(pdev, host); @@ -1525,8 +1275,6 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) static struct platform_driver mxcnd_driver = { .driver = { .name = DRIVER_NAME, - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(mxcnd_dt_ids), }, .remove = __devexit_p(mxcnd_remove), }; diff --git a/trunk/drivers/mtd/nand/nand_base.c b/trunk/drivers/mtd/nand/nand_base.c index d47586cf64ce..47b19c0bb070 100644 --- a/trunk/drivers/mtd/nand/nand_base.c +++ b/trunk/drivers/mtd/nand/nand_base.c @@ -1066,17 +1066,15 @@ EXPORT_SYMBOL(nand_lock); * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { chip->read_buf(mtd, buf, mtd->writesize); - if (oob_required) - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); return 0; } @@ -1085,14 +1083,13 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * We need a special oob layout and handling even when OOB isn't used. */ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, - int oob_required, int page) + struct nand_chip *chip, + uint8_t *buf, int page) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1129,11 +1126,10 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read */ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1142,9 +1138,8 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; - unsigned int max_bitflips = 0; - chip->ecc.read_page_raw(mtd, chip, buf, 1, page); + chip->ecc.read_page_raw(mtd, chip, buf, page); for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) chip->ecc.calculate(mtd, p, &ecc_calc[i]); @@ -1159,14 +1154,12 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, int stat; stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /** @@ -1187,7 +1180,6 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, int datafrag_len, eccfrag_len, aligned_len, aligned_pos; int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; int index = 0; - unsigned int max_bitflips = 0; /* Column address within the page aligned to ECC size (256bytes) */ start_step = data_offs / chip->ecc.size; @@ -1252,14 +1244,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /** @@ -1267,13 +1257,12 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Not for syndrome calculating ECC controllers which need a special oob layout. */ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1282,7 +1271,6 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *ecc_calc = chip->buffers->ecccalc; uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; - unsigned int max_bitflips = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { chip->ecc.hwctl(mtd, NAND_ECC_READ); @@ -1301,14 +1289,12 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, int stat; stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /** @@ -1316,7 +1302,6 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Hardware ECC for large page chips, require OOB to be read first. For this @@ -1326,7 +1311,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * the data area, by overwriting the NAND manufacturer bad block markings. */ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, int page) + struct nand_chip *chip, uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1335,7 +1320,6 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, uint8_t *ecc_code = chip->buffers->ecccode; uint32_t *eccpos = chip->ecc.layout->eccpos; uint8_t *ecc_calc = chip->buffers->ecccalc; - unsigned int max_bitflips = 0; /* Read the OOB area first */ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); @@ -1353,14 +1337,12 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, chip->ecc.calculate(mtd, p, &ecc_calc[i]); stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } } - return max_bitflips; + return 0; } /** @@ -1368,21 +1350,19 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps; uint8_t *p = buf; uint8_t *oob = chip->oob_poi; - unsigned int max_bitflips = 0; for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { int stat; @@ -1399,12 +1379,10 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, chip->read_buf(mtd, oob, eccbytes); stat = chip->ecc.correct(mtd, p, oob, NULL); - if (stat < 0) { + if (stat < 0) mtd->ecc_stats.failed++; - } else { + else mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } oob += eccbytes; @@ -1419,7 +1397,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, if (i) chip->read_buf(mtd, oob, i); - return max_bitflips; + return 0; } /** @@ -1481,9 +1459,11 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { - int chipnr, page, realpage, col, bytes, aligned, oob_required; + int chipnr, page, realpage, col, bytes, aligned; struct nand_chip *chip = mtd->priv; struct mtd_ecc_stats stats; + int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; + int sndcmd = 1; int ret = 0; uint32_t readlen = ops->len; uint32_t oobreadlen = ops->ooblen; @@ -1491,7 +1471,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, mtd->oobavail : mtd->oobsize; uint8_t *bufpoi, *oob, *buf; - unsigned int max_bitflips = 0; stats = mtd->ecc_stats; @@ -1505,7 +1484,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, buf = ops->datbuf; oob = ops->oobbuf; - oob_required = oob ? 1 : 0; while (1) { bytes = min(mtd->writesize - col, readlen); @@ -1515,22 +1493,21 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, if (realpage != chip->pagebuf || oob) { bufpoi = aligned ? buf : chip->buffers->databuf; - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + if (likely(sndcmd)) { + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + sndcmd = 0; + } - /* - * Now read the page into the buffer. Absent an error, - * the read methods return max bitflips per ecc step. - */ + /* Now read the page into the buffer */ if (unlikely(ops->mode == MTD_OPS_RAW)) - ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, - oob_required, - page); + ret = chip->ecc.read_page_raw(mtd, chip, + bufpoi, page); else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi); else ret = chip->ecc.read_page(mtd, chip, bufpoi, - oob_required, page); + page); if (ret < 0) { if (!aligned) /* Invalidate page cache */ @@ -1538,25 +1515,22 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, break; } - max_bitflips = max_t(unsigned int, max_bitflips, ret); - /* Transfer not aligned data */ if (!aligned) { if (!NAND_SUBPAGE_READ(chip) && !oob && !(mtd->ecc_stats.failed - stats.failed) && - (ops->mode != MTD_OPS_RAW)) { + (ops->mode != MTD_OPS_RAW)) chip->pagebuf = realpage; - chip->pagebuf_bitflips = ret; - } else { + else /* Invalidate page cache */ chip->pagebuf = -1; - } memcpy(buf, chip->buffers->databuf + col, bytes); } buf += bytes; if (unlikely(oob)) { + int toread = min(oobreadlen, max_oobsize); if (toread) { @@ -1567,7 +1541,13 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, } if (!(chip->options & NAND_NO_READRDY)) { - /* Apply delay or wait for ready/busy pin */ + /* + * Apply delay or wait for ready/busy pin. Do + * this before the AUTOINCR check, so no + * problems arise if a chip which does auto + * increment is marked as NOAUTOINCR by the + * board driver. + */ if (!chip->dev_ready) udelay(chip->chip_delay); else @@ -1576,8 +1556,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, } else { memcpy(buf, chip->buffers->databuf + col, bytes); buf += bytes; - max_bitflips = max_t(unsigned int, max_bitflips, - chip->pagebuf_bitflips); } readlen -= bytes; @@ -1597,19 +1575,26 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, chip->select_chip(mtd, -1); chip->select_chip(mtd, chipnr); } + + /* + * Check, if the chip supports auto page increment or if we + * have hit a block boundary. + */ + if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) + sndcmd = 1; } ops->retlen = ops->len - (size_t) readlen; if (oob) ops->oobretlen = ops->ooblen - oobreadlen; - if (ret < 0) + if (ret) return ret; if (mtd->ecc_stats.failed - stats.failed) return -EBADMSG; - return max_bitflips; + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } /** @@ -1645,13 +1630,17 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, * @mtd: mtd info structure * @chip: nand chip info structure * @page: page number to read + * @sndcmd: flag whether to issue read command or not */ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + if (sndcmd) { + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + sndcmd = 0; + } chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - return 0; + return sndcmd; } /** @@ -1660,9 +1649,10 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @page: page number to read + * @sndcmd: flag whether to issue read command or not */ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { uint8_t *buf = chip->oob_poi; int length = mtd->oobsize; @@ -1689,7 +1679,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, if (length > 0) chip->read_buf(mtd, bufpoi, length); - return 0; + return 1; } /** @@ -1785,13 +1775,13 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { - int page, realpage, chipnr; + int page, realpage, chipnr, sndcmd = 1; struct nand_chip *chip = mtd->priv; struct mtd_ecc_stats stats; + int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; int readlen = ops->ooblen; int len; uint8_t *buf = ops->oobbuf; - int ret = 0; pr_debug("%s: from = 0x%08Lx, len = %i\n", __func__, (unsigned long long)from, readlen); @@ -1827,18 +1817,20 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, while (1) { if (ops->mode == MTD_OPS_RAW) - ret = chip->ecc.read_oob_raw(mtd, chip, page); + sndcmd = chip->ecc.read_oob_raw(mtd, chip, page, sndcmd); else - ret = chip->ecc.read_oob(mtd, chip, page); - - if (ret < 0) - break; + sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); len = min(len, readlen); buf = nand_transfer_oob(chip, buf, ops, len); if (!(chip->options & NAND_NO_READRDY)) { - /* Apply delay or wait for ready/busy pin */ + /* + * Apply delay or wait for ready/busy pin. Do this + * before the AUTOINCR check, so no problems arise if a + * chip which does auto increment is marked as + * NOAUTOINCR by the board driver. + */ if (!chip->dev_ready) udelay(chip->chip_delay); else @@ -1859,12 +1851,16 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, chip->select_chip(mtd, -1); chip->select_chip(mtd, chipnr); } - } - ops->oobretlen = ops->ooblen - readlen; + /* + * Check, if the chip supports auto page increment or if we + * have hit a block boundary. + */ + if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck)) + sndcmd = 1; + } - if (ret < 0) - return ret; + ops->oobretlen = ops->ooblen; if (mtd->ecc_stats.failed - stats.failed) return -EBADMSG; @@ -1923,16 +1919,14 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { chip->write_buf(mtd, buf, mtd->writesize); - if (oob_required) - chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); } /** @@ -1940,13 +1934,12 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB * * We need a special oob layout and handling even when ECC isn't checked. */ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1980,10 +1973,9 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB */ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1999,7 +1991,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0; i < chip->ecc.total; i++) chip->oob_poi[eccpos[i]] = ecc_calc[i]; - chip->ecc.write_page_raw(mtd, chip, buf, 1); + chip->ecc.write_page_raw(mtd, chip, buf); } /** @@ -2007,10 +1999,9 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB */ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -2036,14 +2027,12 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer - * @oob_required: must write chip->oob_poi to OOB * * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ static void nand_write_page_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, - const uint8_t *buf, int oob_required) + struct nand_chip *chip, const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -2082,23 +2071,21 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, * @mtd: MTD device structure * @chip: NAND chip descriptor * @buf: the data to write - * @oob_required: must write chip->oob_poi to OOB * @page: page number to write * @cached: cached programming * @raw: use _raw version of write_page */ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page, - int cached, int raw) + const uint8_t *buf, int page, int cached, int raw) { int status; chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); if (unlikely(raw)) - chip->ecc.write_page_raw(mtd, chip, buf, oob_required); + chip->ecc.write_page_raw(mtd, chip, buf); else - chip->ecc.write_page(mtd, chip, buf, oob_required); + chip->ecc.write_page(mtd, chip, buf); /* * Cached progamming disabled for now. Not sure if it's worth the @@ -2131,9 +2118,6 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, if (chip->verify_buf(mtd, buf, mtd->writesize)) return -EIO; - - /* Make sure the next page prog is preceded by a status read */ - chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); #endif return 0; } @@ -2218,7 +2202,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, uint8_t *oob = ops->oobbuf; uint8_t *buf = ops->datbuf; int ret, subpage; - int oob_required = oob ? 1 : 0; ops->retlen = 0; if (!writelen) @@ -2281,8 +2264,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, memset(chip->oob_poi, 0xff, mtd->oobsize); } - ret = chip->write_page(mtd, chip, wbuf, oob_required, page, - cached, (ops->mode == MTD_OPS_RAW)); + ret = chip->write_page(mtd, chip, wbuf, page, cached, + (ops->mode == MTD_OPS_RAW)); if (ret) break; @@ -2915,7 +2898,8 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, *busw = NAND_BUSWIDTH_16; chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= NAND_NO_READRDY & NAND_CHIPOPTIONS_MSK; + chip->options |= (NAND_NO_READRDY | + NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK; pr_info("ONFI flash detected\n"); return 1; @@ -3092,6 +3076,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; ident_done: + /* + * Set chip as a default. Board drivers can override it, if necessary. + */ + chip->options |= NAND_NO_AUTOINCR; + /* Try to identify manufacturer */ for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { if (nand_manuf_ids[maf_idx].id == *maf_id) @@ -3165,11 +3154,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, if (mtd->writesize > 512 && chip->cmdfunc == nand_command) chip->cmdfunc = nand_command_lp; - pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," - " page size: %d, OOB size: %d\n", - *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, - chip->onfi_version ? chip->onfi_params.model : type->name, - mtd->writesize, mtd->oobsize); + pr_info("NAND device: Manufacturer ID:" + " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, + nand_manuf_ids[maf_idx].name, + chip->onfi_version ? chip->onfi_params.model : type->name); return type; } @@ -3341,13 +3329,8 @@ int nand_scan_tail(struct mtd_info *mtd) if (!chip->ecc.write_oob) chip->ecc.write_oob = nand_write_oob_syndrome; - if (mtd->writesize >= chip->ecc.size) { - if (!chip->ecc.strength) { - pr_warn("Driver must set ecc.strength when using hardware ECC\n"); - BUG(); - } + if (mtd->writesize >= chip->ecc.size) break; - } pr_warn("%d byte HW ECC not possible on " "%d byte page size, fallback to SW ECC\n", chip->ecc.size, mtd->writesize); @@ -3402,7 +3385,7 @@ int nand_scan_tail(struct mtd_info *mtd) BUG(); } chip->ecc.strength = - chip->ecc.bytes * 8 / fls(8 * chip->ecc.size); + chip->ecc.bytes*8 / fls(8*chip->ecc.size); break; case NAND_ECC_NONE: @@ -3500,7 +3483,7 @@ int nand_scan_tail(struct mtd_info *mtd) /* propagate ecc info to mtd_info */ mtd->ecclayout = chip->ecc.layout; - mtd->ecc_strength = chip->ecc.strength; + mtd->ecc_strength = chip->ecc.strength * chip->ecc.steps; /* Check, if we should skip the bad block table scan */ if (chip->options & NAND_SKIP_BBTSCAN) diff --git a/trunk/drivers/mtd/nand/nand_bbt.c b/trunk/drivers/mtd/nand/nand_bbt.c index 30d1319ff065..20a112f591fe 100644 --- a/trunk/drivers/mtd/nand/nand_bbt.c +++ b/trunk/drivers/mtd/nand/nand_bbt.c @@ -324,7 +324,6 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, buf += mtd->oobsize + mtd->writesize; len -= mtd->writesize; - offs += mtd->writesize; } return 0; } diff --git a/trunk/drivers/mtd/nand/nand_ids.c b/trunk/drivers/mtd/nand/nand_ids.c index 621b70b7a159..af4fe8ca7b5e 100644 --- a/trunk/drivers/mtd/nand/nand_ids.c +++ b/trunk/drivers/mtd/nand/nand_ids.c @@ -70,7 +70,7 @@ struct nand_flash_dev nand_flash_ids[] = { * These are the new chips with large page size. The pagesize and the * erasesize is determined from the extended id bytes */ -#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY) +#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR) #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16) /* 512 Megabit */ @@ -157,7 +157,9 @@ struct nand_flash_dev nand_flash_ids[] = { * writes possible, but not implemented now */ {"AND 128MiB 3,3V 8-bit", 0x01, 2048, 128, 0x4000, - NAND_IS_AND | NAND_NO_READRDY | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH}, + NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY | + BBT_AUTO_REFRESH + }, {NULL,} }; diff --git a/trunk/drivers/mtd/nand/nandsim.c b/trunk/drivers/mtd/nand/nandsim.c index 6cc8fbfabb8e..261f478f8cc3 100644 --- a/trunk/drivers/mtd/nand/nandsim.c +++ b/trunk/drivers/mtd/nand/nandsim.c @@ -268,6 +268,7 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " #define OPT_PAGE512 0x00000002 /* 512-byte page chips */ #define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */ #define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */ +#define OPT_AUTOINCR 0x00000020 /* page number auto incrementation is possible */ #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */ #define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */ #define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */ @@ -593,7 +594,7 @@ static int init_nandsim(struct mtd_info *mtd) ns->options |= OPT_PAGE256; } else if (ns->geom.pgsz == 512) { - ns->options |= OPT_PAGE512; + ns->options |= (OPT_PAGE512 | OPT_AUTOINCR); if (ns->busw == 8) ns->options |= OPT_PAGE512_8BIT; } else if (ns->geom.pgsz == 2048) { @@ -662,6 +663,8 @@ static int init_nandsim(struct mtd_info *mtd) for (i = 0; nand_flash_ids[i].name != NULL; i++) { if (second_id_byte != nand_flash_ids[i].id) continue; + if (!(nand_flash_ids[i].options & NAND_NO_AUTOINCR)) + ns->options |= OPT_AUTOINCR; } if (ns->busw == 16) @@ -1933,8 +1936,20 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd) if (ns->regs.count == ns->regs.num) { NS_DBG("read_byte: all bytes were read\n"); - if (NS_STATE(ns->nxstate) == STATE_READY) + /* + * The OPT_AUTOINCR allows to read next consecutive pages without + * new read operation cycle. + */ + if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { + ns->regs.count = 0; + if (ns->regs.row + 1 < ns->geom.pgnum) + ns->regs.row += 1; + NS_DBG("read_byte: switch to the next page (%#x)\n", ns->regs.row); + do_state_action(ns, ACTION_CPY); + } + else if (NS_STATE(ns->nxstate) == STATE_READY) switch_state(ns); + } return outb; @@ -2188,7 +2203,14 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) ns->regs.count += len; if (ns->regs.count == ns->regs.num) { - if (NS_STATE(ns->nxstate) == STATE_READY) + if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) { + ns->regs.count = 0; + if (ns->regs.row + 1 < ns->geom.pgnum) + ns->regs.row += 1; + NS_DBG("read_buf: switch to the next page (%#x)\n", ns->regs.row); + do_state_action(ns, ACTION_CPY); + } + else if (NS_STATE(ns->nxstate) == STATE_READY) switch_state(ns); } diff --git a/trunk/drivers/mtd/nand/omap2.c b/trunk/drivers/mtd/nand/omap2.c index d7f681d0c9b9..c2b0bba9d8b3 100644 --- a/trunk/drivers/mtd/nand/omap2.c +++ b/trunk/drivers/mtd/nand/omap2.c @@ -21,10 +21,6 @@ #include #include -#ifdef CONFIG_MTD_NAND_OMAP_BCH -#include -#endif - #include #include #include @@ -131,11 +127,6 @@ struct omap_nand_info { } iomode; u_char *buf; int buf_len; - -#ifdef CONFIG_MTD_NAND_OMAP_BCH - struct bch_control *bch; - struct nand_ecclayout ecclayout; -#endif }; /** @@ -411,7 +402,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); if (ret) /* PFPW engine is busy, use cpu copy method */ - goto out_copy_unmap; + goto out_copy; init_completion(&info->comp); @@ -430,8 +421,6 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); return 0; -out_copy_unmap: - dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); out_copy: if (info->nand.options & NAND_BUSWIDTH_16) is_write == 0 ? omap_read_buf16(mtd, (u_char *) addr, len) @@ -890,7 +879,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); unsigned long timeo = jiffies; - int status, state = this->state; + int status = NAND_STATUS_FAIL, state = this->state; if (state == FL_ERASING) timeo += (HZ * 400) / 1000; @@ -905,8 +894,6 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) break; cond_resched(); } - - status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA); return status; } @@ -938,226 +925,6 @@ static int omap_dev_ready(struct mtd_info *mtd) return 1; } -#ifdef CONFIG_MTD_NAND_OMAP_BCH - -/** - * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction - * @mtd: MTD device structure - * @mode: Read/Write mode - */ -static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) -{ - int nerrors; - unsigned int dev_width; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - struct nand_chip *chip = mtd->priv; - - nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4; - dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; - /* - * Program GPMC to perform correction on one 512-byte sector at a time. - * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and - * gives a slight (5%) performance gain (but requires additional code). - */ - (void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors); -} - -/** - * omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes - * @mtd: MTD device structure - * @dat: The pointer to data on which ecc is computed - * @ecc_code: The ecc_code buffer - */ -static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code); -} - -/** - * omap3_calculate_ecc_bch8 - Generate 13 bytes of ECC bytes - * @mtd: MTD device structure - * @dat: The pointer to data on which ecc is computed - * @ecc_code: The ecc_code buffer - */ -static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code); -} - -/** - * omap3_correct_data_bch - Decode received data and correct errors - * @mtd: MTD device structure - * @data: page data - * @read_ecc: ecc read from nand flash - * @calc_ecc: ecc read from HW ECC registers - */ -static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data, - u_char *read_ecc, u_char *calc_ecc) -{ - int i, count; - /* cannot correct more than 8 errors */ - unsigned int errloc[8]; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - - count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL, - errloc); - if (count > 0) { - /* correct errors */ - for (i = 0; i < count; i++) { - /* correct data only, not ecc bytes */ - if (errloc[i] < 8*512) - data[errloc[i]/8] ^= 1 << (errloc[i] & 7); - pr_debug("corrected bitflip %u\n", errloc[i]); - } - } else if (count < 0) { - pr_err("ecc unrecoverable error\n"); - } - return count; -} - -/** - * omap3_free_bch - Release BCH ecc resources - * @mtd: MTD device structure - */ -static void omap3_free_bch(struct mtd_info *mtd) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - if (info->bch) { - free_bch(info->bch); - info->bch = NULL; - } -} - -/** - * omap3_init_bch - Initialize BCH ECC - * @mtd: MTD device structure - * @ecc_opt: OMAP ECC mode (OMAP_ECC_BCH4_CODE_HW or OMAP_ECC_BCH8_CODE_HW) - */ -static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) -{ - int ret, max_errors; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); -#ifdef CONFIG_MTD_NAND_OMAP_BCH8 - const int hw_errors = 8; -#else - const int hw_errors = 4; -#endif - info->bch = NULL; - - max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ? 8 : 4; - if (max_errors != hw_errors) { - pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported", - max_errors, hw_errors); - goto fail; - } - - /* initialize GPMC BCH engine */ - ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors); - if (ret) - goto fail; - - /* software bch library is only used to detect and locate errors */ - info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */); - if (!info->bch) - goto fail; - - info->nand.ecc.size = 512; - info->nand.ecc.hwctl = omap3_enable_hwecc_bch; - info->nand.ecc.correct = omap3_correct_data_bch; - info->nand.ecc.mode = NAND_ECC_HW; - - /* - * The number of corrected errors in an ecc block that will trigger - * block scrubbing defaults to the ecc strength (4 or 8). - * Set mtd->bitflip_threshold here to define a custom threshold. - */ - - if (max_errors == 8) { - info->nand.ecc.strength = 8; - info->nand.ecc.bytes = 13; - info->nand.ecc.calculate = omap3_calculate_ecc_bch8; - } else { - info->nand.ecc.strength = 4; - info->nand.ecc.bytes = 7; - info->nand.ecc.calculate = omap3_calculate_ecc_bch4; - } - - pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors); - return 0; -fail: - omap3_free_bch(mtd); - return -1; -} - -/** - * omap3_init_bch_tail - Build an oob layout for BCH ECC correction. - * @mtd: MTD device structure - */ -static int omap3_init_bch_tail(struct mtd_info *mtd) -{ - int i, steps; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - struct nand_ecclayout *layout = &info->ecclayout; - - /* build oob layout */ - steps = mtd->writesize/info->nand.ecc.size; - layout->eccbytes = steps*info->nand.ecc.bytes; - - /* do not bother creating special oob layouts for small page devices */ - if (mtd->oobsize < 64) { - pr_err("BCH ecc is not supported on small page devices\n"); - goto fail; - } - - /* reserve 2 bytes for bad block marker */ - if (layout->eccbytes+2 > mtd->oobsize) { - pr_err("no oob layout available for oobsize %d eccbytes %u\n", - mtd->oobsize, layout->eccbytes); - goto fail; - } - - /* put ecc bytes at oob tail */ - for (i = 0; i < layout->eccbytes; i++) - layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i; - - layout->oobfree[0].offset = 2; - layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; - info->nand.ecc.layout = layout; - - if (!(info->nand.options & NAND_BUSWIDTH_16)) - info->nand.badblock_pattern = &bb_descrip_flashbased; - return 0; -fail: - omap3_free_bch(mtd); - return -1; -} - -#else -static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) -{ - pr_err("CONFIG_MTD_NAND_OMAP_BCH is not enabled\n"); - return -1; -} -static int omap3_init_bch_tail(struct mtd_info *mtd) -{ - return -1; -} -static void omap3_free_bch(struct mtd_info *mtd) -{ -} -#endif /* CONFIG_MTD_NAND_OMAP_BCH */ - static int __devinit omap_nand_probe(struct platform_device *pdev) { struct omap_nand_info *info; @@ -1296,13 +1063,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->nand.ecc.hwctl = omap_enable_hwecc; info->nand.ecc.correct = omap_correct_data; info->nand.ecc.mode = NAND_ECC_HW; - } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || - (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { - err = omap3_init_bch(&info->mtd, pdata->ecc_opt); - if (err) { - err = -EINVAL; - goto out_release_mem_region; - } } /* DIP switches on some boards change between 8 and 16 bit @@ -1334,14 +1094,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) (offset + omap_oobinfo.eccbytes); info->nand.ecc.layout = &omap_oobinfo; - } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || - (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { - /* build OOB layout for BCH ECC correction */ - err = omap3_init_bch_tail(&info->mtd); - if (err) { - err = -EINVAL; - goto out_release_mem_region; - } } /* second phase scan */ @@ -1370,7 +1122,6 @@ static int omap_nand_remove(struct platform_device *pdev) struct mtd_info *mtd = platform_get_drvdata(pdev); struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - omap3_free_bch(&info->mtd); platform_set_drvdata(pdev, NULL); if (info->dma_ch != -1) diff --git a/trunk/drivers/mtd/nand/pasemi_nand.c b/trunk/drivers/mtd/nand/pasemi_nand.c index 1440e51cedcc..974dbf8251c9 100644 --- a/trunk/drivers/mtd/nand/pasemi_nand.c +++ b/trunk/drivers/mtd/nand/pasemi_nand.c @@ -155,6 +155,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev) chip->ecc.mode = NAND_ECC_SOFT; /* Enable the following for a flash based bad block table */ + chip->options = NAND_NO_AUTOINCR; chip->bbt_options = NAND_BBT_USE_FLASH; /* Scan to find existence of the device */ diff --git a/trunk/drivers/mtd/nand/plat_nand.c b/trunk/drivers/mtd/nand/plat_nand.c index 1bcb52040422..6404e6e81b10 100644 --- a/trunk/drivers/mtd/nand/plat_nand.c +++ b/trunk/drivers/mtd/nand/plat_nand.c @@ -23,18 +23,14 @@ struct plat_nand_data { void __iomem *io_base; }; -static const char *part_probe_types[] = { "cmdlinepart", NULL }; - /* * Probe for the NAND device. */ static int __devinit plat_nand_probe(struct platform_device *pdev) { struct platform_nand_data *pdata = pdev->dev.platform_data; - struct mtd_part_parser_data ppdata; struct plat_nand_data *data; struct resource *res; - const char **part_types; int err = 0; if (pdata->chip.nr_chips < 1) { @@ -79,7 +75,6 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) data->chip.select_chip = pdata->ctrl.select_chip; data->chip.write_buf = pdata->ctrl.write_buf; data->chip.read_buf = pdata->ctrl.read_buf; - data->chip.read_byte = pdata->ctrl.read_byte; data->chip.chip_delay = pdata->chip.chip_delay; data->chip.options |= pdata->chip.options; data->chip.bbt_options |= pdata->chip.bbt_options; @@ -103,10 +98,8 @@ static int __devinit plat_nand_probe(struct platform_device *pdev) goto out; } - part_types = pdata->chip.part_probe_types ? : part_probe_types; - - ppdata.of_node = pdev->dev.of_node; - err = mtd_device_parse_register(&data->mtd, part_types, &ppdata, + err = mtd_device_parse_register(&data->mtd, + pdata->chip.part_probe_types, NULL, pdata->chip.partitions, pdata->chip.nr_partitions); @@ -147,19 +140,12 @@ static int __devexit plat_nand_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id plat_nand_match[] = { - { .compatible = "gen_nand" }, - {}, -}; -MODULE_DEVICE_TABLE(of, plat_nand_match); - static struct platform_driver plat_nand_driver = { - .probe = plat_nand_probe, - .remove = __devexit_p(plat_nand_remove), - .driver = { - .name = "gen_nand", - .owner = THIS_MODULE, - .of_match_table = plat_nand_match, + .probe = plat_nand_probe, + .remove = __devexit_p(plat_nand_remove), + .driver = { + .name = "gen_nand", + .owner = THIS_MODULE, }, }; diff --git a/trunk/drivers/mtd/nand/pxa3xx_nand.c b/trunk/drivers/mtd/nand/pxa3xx_nand.c index 252aaefcacfa..def50caa6f84 100644 --- a/trunk/drivers/mtd/nand/pxa3xx_nand.c +++ b/trunk/drivers/mtd/nand/pxa3xx_nand.c @@ -682,15 +682,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, } static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, int oob_required) + struct nand_chip *chip, const uint8_t *buf) { chip->write_buf(mtd, buf, mtd->writesize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); } static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int oob_required, - int page) + struct nand_chip *chip, uint8_t *buf, int page) { struct pxa3xx_nand_host *host = mtd->priv; struct pxa3xx_nand_info *info = host->info_data; @@ -1005,6 +1004,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) chip->ecc.size = host->page_size; chip->ecc.strength = 1; + chip->options = NAND_NO_AUTOINCR; chip->options |= NAND_NO_READRDY; if (host->reg_ndcr & NDCR_DWIDTH_M) chip->options |= NAND_BUSWIDTH_16; diff --git a/trunk/drivers/mtd/nand/r852.c b/trunk/drivers/mtd/nand/r852.c index 8cb627751c9c..c2040187c813 100644 --- a/trunk/drivers/mtd/nand/r852.c +++ b/trunk/drivers/mtd/nand/r852.c @@ -539,11 +539,14 @@ int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, * nand_read_oob_syndrome assumes we can send column address - we can't */ static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) + int page, int sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + if (sndcmd) { + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + sndcmd = 0; + } chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - return 0; + return sndcmd; } /* @@ -1101,7 +1104,18 @@ static struct pci_driver r852_pci_driver = { .driver.pm = &r852_pm_ops, }; -module_pci_driver(r852_pci_driver); +static __init int r852_module_init(void) +{ + return pci_register_driver(&r852_pci_driver); +} + +static void __exit r852_module_exit(void) +{ + pci_unregister_driver(&r852_pci_driver); +} + +module_init(r852_module_init); +module_exit(r852_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Maxim Levitsky "); diff --git a/trunk/drivers/mtd/nand/sh_flctl.c b/trunk/drivers/mtd/nand/sh_flctl.c index aa9b8a5e0b8f..e9b2b260de3a 100644 --- a/trunk/drivers/mtd/nand/sh_flctl.c +++ b/trunk/drivers/mtd/nand/sh_flctl.c @@ -344,7 +344,7 @@ static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_va } static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) + uint8_t *buf, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -359,14 +359,14 @@ static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, if (flctl->hwecc_cant_correct[i]) mtd->ecc_stats.failed++; else - mtd->ecc_stats.corrected += 0; /* FIXME */ + mtd->ecc_stats.corrected += 0; } return 0; } static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required) + const uint8_t *buf) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -881,6 +881,8 @@ static int __devinit flctl_probe(struct platform_device *pdev) flctl->hwecc = pdata->has_hwecc; flctl->holden = pdata->use_holden; + nand->options = NAND_NO_AUTOINCR; + /* Set address of hardware control function */ /* 20 us command delay time */ nand->chip_delay = 20; diff --git a/trunk/drivers/mtd/nand/sm_common.c b/trunk/drivers/mtd/nand/sm_common.c index 082bcdcd6bcf..774c3c266713 100644 --- a/trunk/drivers/mtd/nand/sm_common.c +++ b/trunk/drivers/mtd/nand/sm_common.c @@ -94,16 +94,17 @@ static struct nand_flash_dev nand_smartmedia_flash_ids[] = { {NULL,} }; +#define XD_TYPEM (NAND_NO_AUTOINCR | NAND_BROKEN_XD) static struct nand_flash_dev nand_xd_flash_ids[] = { {"xD 16MiB 3,3V", 0x73, 512, 16, 0x4000, 0}, {"xD 32MiB 3,3V", 0x75, 512, 32, 0x4000, 0}, {"xD 64MiB 3,3V", 0x76, 512, 64, 0x4000, 0}, {"xD 128MiB 3,3V", 0x79, 512, 128, 0x4000, 0}, - {"xD 256MiB 3,3V", 0x71, 512, 256, 0x4000, NAND_BROKEN_XD}, - {"xD 512MiB 3,3V", 0xdc, 512, 512, 0x4000, NAND_BROKEN_XD}, - {"xD 1GiB 3,3V", 0xd3, 512, 1024, 0x4000, NAND_BROKEN_XD}, - {"xD 2GiB 3,3V", 0xd5, 512, 2048, 0x4000, NAND_BROKEN_XD}, + {"xD 256MiB 3,3V", 0x71, 512, 256, 0x4000, XD_TYPEM}, + {"xD 512MiB 3,3V", 0xdc, 512, 512, 0x4000, XD_TYPEM}, + {"xD 1GiB 3,3V", 0xd3, 512, 1024, 0x4000, XD_TYPEM}, + {"xD 2GiB 3,3V", 0xd5, 512, 2048, 0x4000, XD_TYPEM}, {NULL,} }; diff --git a/trunk/drivers/mtd/onenand/onenand_base.c b/trunk/drivers/mtd/onenand/onenand_base.c index 7153e0d27101..b3ce12ef359e 100644 --- a/trunk/drivers/mtd/onenand/onenand_base.c +++ b/trunk/drivers/mtd/onenand/onenand_base.c @@ -1201,8 +1201,7 @@ static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, if (mtd->ecc_stats.failed - stats.failed) return -EBADMSG; - /* return max bitflips per ecc step; ONENANDs correct 1 bit only */ - return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0; + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } /** @@ -1334,8 +1333,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, if (mtd->ecc_stats.failed - stats.failed) return -EBADMSG; - /* return max bitflips per ecc step; ONENANDs correct 1 bit only */ - return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0; + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; } /** diff --git a/trunk/drivers/mtd/ubi/debug.c b/trunk/drivers/mtd/ubi/debug.c index 09d4f8d9d592..9f957c2d48e9 100644 --- a/trunk/drivers/mtd/ubi/debug.c +++ b/trunk/drivers/mtd/ubi/debug.c @@ -264,9 +264,6 @@ static struct dentry *dfs_rootdir; */ int ubi_debugfs_init(void) { - if (!IS_ENABLED(DEBUG_FS)) - return 0; - dfs_rootdir = debugfs_create_dir("ubi", NULL); if (IS_ERR_OR_NULL(dfs_rootdir)) { int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir); @@ -284,8 +281,7 @@ int ubi_debugfs_init(void) */ void ubi_debugfs_exit(void) { - if (IS_ENABLED(DEBUG_FS)) - debugfs_remove(dfs_rootdir); + debugfs_remove(dfs_rootdir); } /* Read an UBI debugfs file */ @@ -407,9 +403,6 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) struct dentry *dent; struct ubi_debug_info *d = ubi->dbg; - if (!IS_ENABLED(DEBUG_FS)) - return 0; - n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME, ubi->ubi_num); if (n == UBI_DFS_DIR_LEN) { @@ -477,6 +470,5 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) */ void ubi_debugfs_exit_dev(struct ubi_device *ubi) { - if (IS_ENABLED(DEBUG_FS)) - debugfs_remove_recursive(ubi->dbg->dfs_dir); + debugfs_remove_recursive(ubi->dbg->dfs_dir); } diff --git a/trunk/drivers/mtd/ubi/wl.c b/trunk/drivers/mtd/ubi/wl.c index b6be644e7b85..9df100a4ec38 100644 --- a/trunk/drivers/mtd/ubi/wl.c +++ b/trunk/drivers/mtd/ubi/wl.c @@ -1262,11 +1262,11 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum) dbg_wl("flush pending work for LEB %d:%d (%d pending works)", vol_id, lnum, ubi->works_count); + down_write(&ubi->work_sem); while (found) { struct ubi_work *wrk; found = 0; - down_read(&ubi->work_sem); spin_lock(&ubi->wl_lock); list_for_each_entry(wrk, &ubi->works, list) { if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) && @@ -1277,27 +1277,18 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum) spin_unlock(&ubi->wl_lock); err = wrk->func(ubi, wrk, 0); - if (err) { - up_read(&ubi->work_sem); - return err; - } - + if (err) + goto out; spin_lock(&ubi->wl_lock); found = 1; break; } } spin_unlock(&ubi->wl_lock); - up_read(&ubi->work_sem); } - /* - * Make sure all the works which have been done in parallel are - * finished. - */ - down_write(&ubi->work_sem); +out: up_write(&ubi->work_sem); - return err; } diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index b9c2ae62166d..2ee8cf9e8a3b 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -76,7 +76,6 @@ #include #include #include -#include #include "bonding.h" #include "bond_3ad.h" #include "bond_alb.h" @@ -382,6 +381,8 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) return next; } +#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb)) + /** * bond_dev_queue_xmit - Prepare skb for xmit. * @@ -394,9 +395,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, { skb->dev = slave_dev; - BUILD_BUG_ON(sizeof(skb->queue_mapping) != - sizeof(qdisc_skb_cb(skb)->bond_queue_mapping)); - skb->queue_mapping = qdisc_skb_cb(skb)->bond_queue_mapping; + skb->queue_mapping = bond_queue_mapping(skb); if (unlikely(netpoll_tx_running(slave_dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); @@ -4172,7 +4171,7 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) /* * Save the original txq to restore before passing to the driver */ - qdisc_skb_cb(skb)->bond_queue_mapping = skb->queue_mapping; + bond_queue_mapping(skb) = skb->queue_mapping; if (unlikely(txq >= dev->real_num_tx_queues)) { do { diff --git a/trunk/drivers/net/bonding/bond_sysfs.c b/trunk/drivers/net/bonding/bond_sysfs.c index 485bedb8278c..aef42f045320 100644 --- a/trunk/drivers/net/bonding/bond_sysfs.c +++ b/trunk/drivers/net/bonding/bond_sysfs.c @@ -1082,12 +1082,8 @@ static ssize_t bonding_store_primary(struct device *d, } } - strncpy(bond->params.primary, ifname, IFNAMSIZ); - bond->params.primary[IFNAMSIZ - 1] = 0; - - pr_info("%s: Recording %s as primary, " - "but it has not been enslaved to %s yet.\n", - bond->dev->name, ifname, bond->dev->name); + pr_info("%s: Unable to set %.*s as primary slave.\n", + bond->dev->name, (int)strlen(buf) - 1, buf); out: write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); diff --git a/trunk/drivers/net/can/c_can/c_can.c b/trunk/drivers/net/can/c_can/c_can.c index 8dc84d66eea1..536bda072a16 100644 --- a/trunk/drivers/net/can/c_can/c_can.c +++ b/trunk/drivers/net/can/c_can/c_can.c @@ -686,7 +686,7 @@ static int c_can_get_berr_counter(const struct net_device *dev, * * We iterate from priv->tx_echo to priv->tx_next and check if the * packet has been transmitted, echo it back to the CAN framework. - * If we discover a not yet transmitted packet, stop looking for more. + * If we discover a not yet transmitted package, stop looking for more. */ static void c_can_do_tx(struct net_device *dev) { @@ -698,7 +698,7 @@ static void c_can_do_tx(struct net_device *dev) for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { msg_obj_no = get_tx_echo_msg_obj(priv); val = c_can_read_reg32(priv, &priv->regs->txrqst1); - if (!(val & (1 << (msg_obj_no - 1)))) { + if (!(val & (1 << msg_obj_no))) { can_get_echo_skb(dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); stats->tx_bytes += priv->read_reg(priv, @@ -706,8 +706,6 @@ static void c_can_do_tx(struct net_device *dev) & IF_MCONT_DLC_MASK; stats->tx_packets++; c_can_inval_msg_object(dev, 0, msg_obj_no); - } else { - break; } } @@ -952,7 +950,7 @@ static int c_can_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->irqstatus; + irqstatus = priv->read_reg(priv, &priv->regs->interrupt); if (!irqstatus) goto end; @@ -1030,11 +1028,12 @@ static int c_can_poll(struct napi_struct *napi, int quota) static irqreturn_t c_can_isr(int irq, void *dev_id) { + u16 irqstatus; struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); - priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt); - if (!priv->irqstatus) + irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + if (!irqstatus) return IRQ_NONE; /* disable all interrupts and schedule the NAPI */ @@ -1064,11 +1063,10 @@ static int c_can_open(struct net_device *dev) goto exit_irq_fail; } - napi_enable(&priv->napi); - /* start the c_can controller */ c_can_start(dev); + napi_enable(&priv->napi); netif_start_queue(dev); return 0; diff --git a/trunk/drivers/net/can/c_can/c_can.h b/trunk/drivers/net/can/c_can/c_can.h index 5f32d34af507..9b7fbef3d09a 100644 --- a/trunk/drivers/net/can/c_can/c_can.h +++ b/trunk/drivers/net/can/c_can/c_can.h @@ -76,7 +76,6 @@ struct c_can_priv { unsigned int tx_next; unsigned int tx_echo; void *priv; /* for board-specific data */ - u16 irqstatus; }; struct net_device *alloc_c_can_dev(void); diff --git a/trunk/drivers/net/can/cc770/cc770_platform.c b/trunk/drivers/net/can/cc770/cc770_platform.c index 688371cda37a..53115eee8075 100644 --- a/trunk/drivers/net/can/cc770/cc770_platform.c +++ b/trunk/drivers/net/can/cc770/cc770_platform.c @@ -154,7 +154,7 @@ static int __devinit cc770_get_platform_data(struct platform_device *pdev, struct cc770_platform_data *pdata = pdev->dev.platform_data; priv->can.clock.freq = pdata->osc_freq; - if (priv->cpu_interface & CPUIF_DSC) + if (priv->cpu_interface | CPUIF_DSC) priv->can.clock.freq /= 2; priv->clkout = pdata->cor; priv->bus_config = pdata->bcr; diff --git a/trunk/drivers/net/dummy.c b/trunk/drivers/net/dummy.c index bab0158f1cc3..442d91a2747b 100644 --- a/trunk/drivers/net/dummy.c +++ b/trunk/drivers/net/dummy.c @@ -187,10 +187,8 @@ static int __init dummy_init_module(void) rtnl_lock(); err = __rtnl_link_register(&dummy_link_ops); - for (i = 0; i < numdummies && !err; i++) { + for (i = 0; i < numdummies && !err; i++) err = dummy_init_one(); - cond_resched(); - } if (err < 0) __rtnl_link_unregister(&dummy_link_ops); rtnl_unlock(); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 7de824184979..e30e2a2f354c 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -747,6 +747,21 @@ struct bnx2x_fastpath { #define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG +#define BNX2X_IP_CSUM_ERR(cqe) \ + (!((cqe)->fast_path_cqe.status_flags & \ + ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \ + ((cqe)->fast_path_cqe.type_error_flags & \ + ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG)) + +#define BNX2X_L4_CSUM_ERR(cqe) \ + (!((cqe)->fast_path_cqe.status_flags & \ + ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \ + ((cqe)->fast_path_cqe.type_error_flags & \ + ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) + +#define BNX2X_RX_CSUM_OK(cqe) \ + (!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe))) + #define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \ (((le16_to_cpu(flags) & \ PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index cbc56f274e0c..ad0743bf4bde 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -617,25 +617,6 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp, return 0; } -static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, - struct bnx2x_fastpath *fp) -{ - /* Do nothing if no IP/L4 csum validation was done */ - - if (cqe->fast_path_cqe.status_flags & - (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | - ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) - return; - - /* If both IP/L4 validation were done, check if an error was found. */ - - if (cqe->fast_path_cqe.type_error_flags & - (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | - ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) - fp->eth_q_stats.hw_csum_err++; - else - skb->ip_summed = CHECKSUM_UNNECESSARY; -} int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) { @@ -825,9 +806,13 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) skb_checksum_none_assert(skb); - if (bp->dev->features & NETIF_F_RXCSUM) - bnx2x_csum_validate(skb, cqe, fp); + if (bp->dev->features & NETIF_F_RXCSUM) { + if (likely(BNX2X_RX_CSUM_OK(cqe))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + fp->eth_q_stats.hw_csum_err++; + } skb_record_rx_queue(skb, fp->rx_queue); diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.c b/trunk/drivers/net/ethernet/broadcom/tg3.c index e47ff8be1d7b..edeeb516807a 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.c +++ b/trunk/drivers/net/ethernet/broadcom/tg3.c @@ -14275,8 +14275,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - if (tg3_flag(tp, 5755_PLUS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + if (tg3_flag(tp, 5755_PLUS)) tg3_flag_set(tp, SHORT_DMA_BUG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_main.c b/trunk/drivers/net/ethernet/emulex/benet/be_main.c index fdb50cec6b51..08efd308d78a 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_main.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_main.c @@ -736,8 +736,6 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb); if (copied) { - int gso_segs = skb_shinfo(skb)->gso_segs; - /* record the sent skb in the sent_skb table */ BUG_ON(txo->sent_skb_list[start]); txo->sent_skb_list[start] = skb; @@ -755,7 +753,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, be_txq_notify(adapter, txq->id, wrb_cnt); - be_tx_stats_update(txo, wrb_cnt, copied, gso_segs, stopped); + be_tx_stats_update(txo, wrb_cnt, copied, + skb_shinfo(skb)->gso_segs, stopped); } else { txq->head = start; dev_kfree_skb_any(skb); diff --git a/trunk/drivers/net/ethernet/freescale/fec_mpc52xx.c b/trunk/drivers/net/ethernet/freescale/fec_mpc52xx.c index 2933d08b036e..97f947b3d94a 100644 --- a/trunk/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/trunk/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -437,7 +437,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) length = status & BCOM_FEC_RX_BD_LEN_MASK; skb_put(rskb, length - 4); /* length without CRC32 */ rskb->protocol = eth_type_trans(rskb, dev); - if (!skb_defer_rx_timestamp(rskb)) + if (!skb_defer_rx_timestamp(skb)) netif_rx(rskb); spin_lock(&priv->lock); diff --git a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c index 7483ca0a6282..95731c841044 100644 --- a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -4080,7 +4080,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, spin_lock_irqsave(&adapter->stats_lock, irq_flags); e1000_tbi_adjust_stats(hw, &adapter->stats, - length, mapped); + length, skb->data); spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); length--; diff --git a/trunk/drivers/net/ethernet/intel/e1000e/ethtool.c b/trunk/drivers/net/ethernet/intel/e1000e/ethtool.c index 905e2147d918..d863075df7a4 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -258,8 +258,7 @@ static int e1000_set_settings(struct net_device *netdev, * When SoL/IDER sessions are active, autoneg/speed/duplex * cannot be changed */ - if (hw->phy.ops.check_reset_block && - hw->phy.ops.check_reset_block(hw)) { + if (hw->phy.ops.check_reset_block(hw)) { e_err("Cannot change link characteristics when SoL/IDER is active.\n"); return -EINVAL; } @@ -1616,8 +1615,7 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) * PHY loopback cannot be performed if SoL/IDER * sessions are active */ - if (hw->phy.ops.check_reset_block && - hw->phy.ops.check_reset_block(hw)) { + if (hw->phy.ops.check_reset_block(hw)) { e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); *data = 0; goto out; diff --git a/trunk/drivers/net/ethernet/intel/e1000e/ich8lan.c b/trunk/drivers/net/ethernet/intel/e1000e/ich8lan.c index 238ab2f8a5e7..bbf70ba367da 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -165,14 +165,14 @@ #define I217_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */ /* Intel Rapid Start Technology Support */ -#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70) +#define I217_PROXY_CTRL PHY_REG(BM_WUC_PAGE, 70) #define I217_PROXY_CTRL_AUTO_DISABLE 0x0080 #define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28) -#define I217_SxCTRL_ENABLE_LPI_RESET 0x1000 +#define I217_SxCTRL_MASK 0x1000 #define I217_CGFREG PHY_REG(772, 29) -#define I217_CGFREG_ENABLE_MTA_RESET 0x0002 +#define I217_CGFREG_MASK 0x0002 #define I217_MEMPWR PHY_REG(772, 26) -#define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010 +#define I217_MEMPWR_MASK 0x0010 /* Strapping Option Register - RO */ #define E1000_STRAP 0x0000C @@ -4089,12 +4089,12 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) * power good. */ e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg); - phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET; + phy_reg |= I217_SxCTRL_MASK; e1e_wphy_locked(hw, I217_SxCTRL, phy_reg); /* Disable the SMB release on LCD reset. */ e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); - phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE; + phy_reg &= ~I217_MEMPWR; e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); } @@ -4103,7 +4103,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) * Support */ e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); - phy_reg |= I217_CGFREG_ENABLE_MTA_RESET; + phy_reg |= I217_CGFREG_MASK; e1e_wphy_locked(hw, I217_CGFREG, phy_reg); release: @@ -4176,7 +4176,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); if (ret_val) goto release; - phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE; + phy_reg |= I217_MEMPWR_MASK; e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); /* Disable Proxy */ @@ -4186,7 +4186,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) ret_val = e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); if (ret_val) goto release; - phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET; + phy_reg &= ~I217_CGFREG_MASK; e1e_wphy_locked(hw, I217_CGFREG, phy_reg); release: if (ret_val) diff --git a/trunk/drivers/net/ethernet/intel/e1000e/mac.c b/trunk/drivers/net/ethernet/intel/e1000e/mac.c index a13439928488..026e8b3ab52e 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/mac.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/mac.c @@ -709,7 +709,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw) * In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ - if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block(hw)) return 0; /* diff --git a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c index 31d37a2b5ba8..a4b0435b00dc 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c @@ -6237,7 +6237,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->hw.phy.ms_type = e1000_ms_hw_default; } - if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block(hw)) e_info("PHY reset is blocked due to SOL/IDER session.\n"); /* Set initial default active device features */ @@ -6404,7 +6404,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (!(adapter->flags & FLAG_HAS_AMT)) e1000e_release_hw_control(adapter); err_eeprom: - if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) + if (!hw->phy.ops.check_reset_block(hw)) e1000_phy_hw_reset(&adapter->hw); err_hw_init: kfree(adapter->tx_ring); diff --git a/trunk/drivers/net/ethernet/intel/e1000e/phy.c b/trunk/drivers/net/ethernet/intel/e1000e/phy.c index b860d4f7ea2a..0334d013bc3c 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/phy.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/phy.c @@ -2155,11 +2155,9 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) s32 ret_val; u32 ctrl; - if (phy->ops.check_reset_block) { - ret_val = phy->ops.check_reset_block(hw); - if (ret_val) - return 0; - } + ret_val = phy->ops.check_reset_block(hw); + if (ret_val) + return 0; ret_val = phy->ops.acquire(hw); if (ret_val) diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 17ad6a3c1be1..bf20457ea23a 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1390,8 +1390,6 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb) { - struct net_device *dev = rx_ring->netdev; - ixgbe_update_rsc_stats(rx_ring, skb); ixgbe_rx_hash(rx_ring, rx_desc, skb); @@ -1403,15 +1401,14 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb); #endif - if ((dev->features & NETIF_F_HW_VLAN_RX) && - ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { + if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan); __vlan_hwaccel_put_tag(skb, vid); } skb_record_rx_queue(skb, rx_ring->queue_index); - skb->protocol = eth_type_trans(skb, dev); + skb->protocol = eth_type_trans(skb, rx_ring->netdev); } static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector, @@ -3610,6 +3607,10 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) if (hw->mac.type == ixgbe_mac_82598EB) netif_set_gso_max_size(adapter->netdev, 32768); + + /* Enable VLAN tag insert/strip */ + adapter->netdev->features |= NETIF_F_HW_VLAN_RX; + hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true); #ifdef IXGBE_FCOE @@ -6700,6 +6701,11 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); +#ifdef CONFIG_DCB + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) + features &= ~NETIF_F_HW_VLAN_RX; +#endif + /* return error if RXHASH is being enabled when RSS is not supported */ if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED)) features &= ~NETIF_F_RXHASH; @@ -6712,6 +6718,7 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev, if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) features &= ~NETIF_F_LRO; + return features; } @@ -6759,11 +6766,6 @@ static int ixgbe_set_features(struct net_device *netdev, need_reset = true; } - if (features & NETIF_F_HW_VLAN_RX) - ixgbe_vlan_strip_enable(adapter); - else - ixgbe_vlan_strip_disable(adapter); - if (changed & NETIF_F_RXALL) need_reset = true; diff --git a/trunk/drivers/net/ethernet/marvell/mv643xx_eth.c b/trunk/drivers/net/ethernet/marvell/mv643xx_eth.c index f0f06b2bc28b..04d901d0ff63 100644 --- a/trunk/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/trunk/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -436,9 +436,7 @@ struct mv643xx_eth_private { /* * Hardware-specific parameters. */ -#if defined(CONFIG_HAVE_CLK) struct clk *clk; -#endif unsigned int t_clk; }; @@ -2897,17 +2895,17 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->dev = dev; /* - * Start with a default rate, and if there is a clock, allow - * it to override the default. + * Get the clk rate, if there is one, otherwise use the default. */ - mp->t_clk = 133000000; -#if defined(CONFIG_HAVE_CLK) mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0")); if (!IS_ERR(mp->clk)) { clk_prepare_enable(mp->clk); mp->t_clk = clk_get_rate(mp->clk); + } else { + mp->t_clk = 133000000; + printk(KERN_WARNING "Unable to get clock"); } -#endif + set_params(mp, pd); netif_set_real_num_tx_queues(dev, mp->txq_count); netif_set_real_num_rx_queues(dev, mp->rxq_count); @@ -2997,13 +2995,10 @@ static int mv643xx_eth_remove(struct platform_device *pdev) phy_detach(mp->phy); cancel_work_sync(&mp->tx_timeout_task); -#if defined(CONFIG_HAVE_CLK) if (!IS_ERR(mp->clk)) { clk_disable_unprepare(mp->clk); clk_put(mp->clk); } -#endif - free_netdev(mp->dev); platform_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/net/ethernet/marvell/sky2.c b/trunk/drivers/net/ethernet/marvell/sky2.c index 28a54451a3e5..cace36f2ab92 100644 --- a/trunk/drivers/net/ethernet/marvell/sky2.c +++ b/trunk/drivers/net/ethernet/marvell/sky2.c @@ -4381,12 +4381,10 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features) struct sky2_port *sky2 = netdev_priv(dev); netdev_features_t changed = dev->features ^ features; - if ((changed & NETIF_F_RXCSUM) && - !(sky2->hw->flags & SKY2_HW_NEW_LE)) { - sky2_write32(sky2->hw, - Q_ADDR(rxqaddr[sky2->port], Q_CSR), - (features & NETIF_F_RXCSUM) - ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + if (changed & NETIF_F_RXCSUM) { + bool on = features & NETIF_F_RXCSUM; + sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), + on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } if (changed & NETIF_F_RXHASH) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c b/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c index 842c8ce9494e..1bcead1fa2f6 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -617,7 +617,7 @@ static struct mlx4_cmd_info cmd_info[] = { .out_is_imm = false, .encode_slave_id = false, .verify = NULL, - .wrapper = mlx4_QUERY_FW_wrapper + .wrapper = NULL }, { .opcode = MLX4_CMD_QUERY_HCA, @@ -635,7 +635,7 @@ static struct mlx4_cmd_info cmd_info[] = { .out_is_imm = false, .encode_slave_id = false, .verify = NULL, - .wrapper = mlx4_QUERY_DEV_CAP_wrapper + .wrapper = NULL }, { .opcode = MLX4_CMD_QUERY_FUNC_CAP, diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_main.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_main.c index 69ba57270481..988b2424e1c6 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -136,12 +136,13 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, struct mlx4_en_dev *mdev = (struct mlx4_en_dev *) endev_ptr; struct mlx4_en_priv *priv; + if (!mdev->pndev[port]) + return; + + priv = netdev_priv(mdev->pndev[port]); switch (event) { case MLX4_DEV_EVENT_PORT_UP: case MLX4_DEV_EVENT_PORT_DOWN: - if (!mdev->pndev[port]) - return; - priv = netdev_priv(mdev->pndev[port]); /* To prevent races, we poll the link state in a separate task rather than changing it here */ priv->link_state = event; @@ -153,10 +154,7 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr, break; default: - if (port < 1 || port > dev->caps.num_ports || - !mdev->pndev[port]) - return; - mlx4_warn(mdev, "Unhandled event %d for port %d\n", event, port); + mlx4_warn(mdev, "Unhandled event: %d\n", event); } } diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c b/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c index bce98d9c0039..3b6f8efbf141 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -426,7 +426,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) mlx4_dbg(dev, "FLR event for slave: %d\n", flr_slave); - if (flr_slave >= dev->num_slaves) { + if (flr_slave > dev->num_slaves) { mlx4_warn(dev, "Got FLR for unknown function: %d\n", flr_slave); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c index 9c83bb8151ea..68f5cd6cb3c7 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -412,7 +412,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) outbox = mailbox->buf; err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A, !mlx4_is_slave(dev)); if (err) goto out; @@ -590,7 +590,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) for (i = 1; i <= dev_cap->num_ports; ++i) { err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_B, + !mlx4_is_slave(dev)); if (err) goto out; @@ -668,28 +669,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) return err; } -int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err = 0; - u8 field; - - err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); - if (err) - return err; - - /* For guests, report Blueflame disabled */ - MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_BF_OFFSET); - field &= 0x7f; - MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET); - - return 0; -} - int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, @@ -881,9 +860,6 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) ((fw_ver & 0xffff0000ull) >> 16) | ((fw_ver & 0x0000ffffull) << 16); - if (mlx4_is_slave(dev)) - goto out; - MLX4_GET(lg, outbox, QUERY_FW_PPF_ID); dev->caps.function = lg; @@ -951,27 +927,6 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) return err; } -int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - u8 *outbuf; - int err; - - outbuf = outbox->buf; - err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_FW, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); - if (err) - return err; - - /* for slaves, zero out everything except FW version */ - outbuf[0] = outbuf[1] = 0; - memset(&outbuf[8], 0, QUERY_FW_OUT_SIZE - 8); - return 0; -} - static void get_board_id(void *vsd, char *board_id) { int i; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c index ee6f4fe00837..2e024a68fa81 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c @@ -142,6 +142,12 @@ struct mlx4_port_config { struct pci_dev *pdev; }; +static inline int mlx4_master_get_num_eqs(struct mlx4_dev *dev) +{ + return dev->caps.reserved_eqs + + MLX4_MFUNC_EQ_NUM * (dev->num_slaves + 1); +} + int mlx4_check_port_params(struct mlx4_dev *dev, enum mlx4_port_type *port_type) { @@ -211,7 +217,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) } dev->caps.num_ports = dev_cap->num_ports; - dev->phys_caps.num_phys_eqs = MLX4_MAX_EQ_NUM; for (i = 1; i <= dev->caps.num_ports; ++i) { dev->caps.vl_cap[i] = dev_cap->max_vl[i]; dev->caps.ib_mtu_cap[i] = dev_cap->ib_mtu[i]; @@ -430,17 +435,12 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz; memset(&dev_cap, 0, sizeof(dev_cap)); - dev->caps.max_qp_dest_rdma = 1 << hca_param.log_rd_per_qp; err = mlx4_dev_cap(dev, &dev_cap); if (err) { mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); return err; } - err = mlx4_QUERY_FW(dev); - if (err) - mlx4_err(dev, "QUERY_FW command failed: could not get FW version.\n"); - page_size = ~dev->caps.page_size_cap + 1; mlx4_warn(dev, "HCA minimum page size:%d\n", page_size); if (page_size > PAGE_SIZE) { @@ -485,15 +485,15 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) dev->caps.num_mgms = 0; dev->caps.num_amgms = 0; + for (i = 1; i <= dev->caps.num_ports; ++i) + dev->caps.port_mask[i] = dev->caps.port_type[i]; + if (dev->caps.num_ports > MLX4_MAX_PORTS) { mlx4_err(dev, "HCA has %d ports, but we only support %d, " "aborting.\n", dev->caps.num_ports, MLX4_MAX_PORTS); return -ENODEV; } - for (i = 1; i <= dev->caps.num_ports; ++i) - dev->caps.port_mask[i] = dev->caps.port_type[i]; - if (dev->caps.uar_page_size * (dev->caps.num_uars - dev->caps.reserved_uars) > pci_resource_len(dev->pdev, 2)) { @@ -504,6 +504,18 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) return -ENODEV; } +#if 0 + mlx4_warn(dev, "sqp_demux:%d\n", dev->caps.sqp_demux); + mlx4_warn(dev, "num_uars:%d reserved_uars:%d uar region:0x%x bar2:0x%llx\n", + dev->caps.num_uars, dev->caps.reserved_uars, + dev->caps.uar_page_size * dev->caps.num_uars, + pci_resource_len(dev->pdev, 2)); + mlx4_warn(dev, "num_eqs:%d reserved_eqs:%d\n", dev->caps.num_eqs, + dev->caps.reserved_eqs); + mlx4_warn(dev, "num_pds:%d reserved_pds:%d slave_pd_shift:%d pd_base:%d\n", + dev->caps.num_pds, dev->caps.reserved_pds, + dev->caps.slave_pd_shift, dev->caps.pd_base); +#endif return 0; } @@ -798,8 +810,9 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, if (err) goto err_srq; - num_eqs = (mlx4_is_master(dev)) ? dev->phys_caps.num_phys_eqs : - dev->caps.num_eqs; + num_eqs = (mlx4_is_master(dev)) ? + roundup_pow_of_two(mlx4_master_get_num_eqs(dev)) : + dev->caps.num_eqs; err = mlx4_init_icm_table(dev, &priv->eq_table.cmpt_table, cmpt_base + ((u64) (MLX4_CMPT_TYPE_EQ * @@ -861,8 +874,9 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, } - num_eqs = (mlx4_is_master(dev)) ? dev->phys_caps.num_phys_eqs : - dev->caps.num_eqs; + num_eqs = (mlx4_is_master(dev)) ? + roundup_pow_of_two(mlx4_master_get_num_eqs(dev)) : + dev->caps.num_eqs; err = mlx4_init_icm_table(dev, &priv->eq_table.table, init_hca->eqc_base, dev_cap->eqc_entry_sz, num_eqs, num_eqs, 0, 0); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h index e5d20220762c..86b6e5a2fabf 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -1039,11 +1039,6 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev); void mlx4_free_resource_tracker(struct mlx4_dev *dev, enum mlx4_res_tracker_free_type type); -int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, @@ -1059,11 +1054,6 @@ int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_cmd_mailbox *inbox, struct mlx4_cmd_mailbox *outbox, struct mlx4_cmd_info *cmd); -int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/port.c b/trunk/drivers/net/ethernet/mellanox/mlx4/port.c index a8fb52992c64..1fe2c7a8b40c 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/port.c @@ -697,10 +697,10 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, if (slave != dev->caps.function) memset(inbox->buf, 0, 256); if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { - *(u8 *) inbox->buf |= !!reset_qkey_viols << 6; + *(u8 *) inbox->buf = !!reset_qkey_viols << 6; ((__be32 *) inbox->buf)[2] = agg_cap_mask; } else { - ((u8 *) inbox->buf)[3] |= !!reset_qkey_viols; + ((u8 *) inbox->buf)[3] = !!reset_qkey_viols; ((__be32 *) inbox->buf)[1] = agg_cap_mask; } diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c b/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c index b83bc928d52a..06e5adeb76f7 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c @@ -126,9 +126,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, profile[MLX4_RES_AUXC].num = request->num_qp; profile[MLX4_RES_SRQ].num = request->num_srq; profile[MLX4_RES_CQ].num = request->num_cq; - profile[MLX4_RES_EQ].num = mlx4_is_mfunc(dev) ? - dev->phys_caps.num_phys_eqs : - min_t(unsigned, dev_cap->max_eqs, MAX_MSIX); + profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs, MAX_MSIX); profile[MLX4_RES_DMPT].num = request->num_mpt; profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS; profile[MLX4_RES_MTT].num = request->num_mtt * (1 << log_mtts_per_seg); @@ -217,10 +215,9 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, init_hca->log_num_cqs = profile[i].log_num; break; case MLX4_RES_EQ: - dev->caps.num_eqs = roundup_pow_of_two(min_t(unsigned, dev_cap->max_eqs, - MAX_MSIX)); + dev->caps.num_eqs = profile[i].num; init_hca->eqc_base = profile[i].start; - init_hca->log_num_eqs = ilog2(dev->caps.num_eqs); + init_hca->log_num_eqs = profile[i].log_num; break; case MLX4_RES_DMPT: dev->caps.num_mpts = profile[i].num; diff --git a/trunk/drivers/net/ethernet/nxp/lpc_eth.c b/trunk/drivers/net/ethernet/nxp/lpc_eth.c index 083d6715335c..8d2666fcffd7 100644 --- a/trunk/drivers/net/ethernet/nxp/lpc_eth.c +++ b/trunk/drivers/net/ethernet/nxp/lpc_eth.c @@ -946,16 +946,16 @@ static void __lpc_handle_xmit(struct net_device *ndev) /* Update stats */ ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; + + /* Free buffer */ + dev_kfree_skb_irq(skb); } - dev_kfree_skb_irq(skb); txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base)); } - if (pldat->num_used_tx_buffs <= ENET_TX_DESC/2) { - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); - } + if (netif_queue_stopped(ndev)) + netif_wake_queue(ndev); } static int __lpc_handle_recv(struct net_device *ndev, int budget) @@ -1320,7 +1320,6 @@ static const struct net_device_ops lpc_netdev_ops = { .ndo_set_rx_mode = lpc_eth_set_multicast_list, .ndo_do_ioctl = lpc_eth_ioctl, .ndo_set_mac_address = lpc_set_mac_address, - .ndo_change_mtu = eth_change_mtu, }; static int lpc_eth_drv_probe(struct platform_device *pdev) diff --git a/trunk/drivers/net/ethernet/realtek/8139cp.c b/trunk/drivers/net/ethernet/realtek/8139cp.c index 995d0cfc4c06..5eef290997f9 100644 --- a/trunk/drivers/net/ethernet/realtek/8139cp.c +++ b/trunk/drivers/net/ethernet/realtek/8139cp.c @@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp) cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - cpw32_f(HiTxRingAddr, 0); - cpw32_f(HiTxRingAddr + 4, 0); - - ring_dma = cp->ring_dma; - cpw32_f(RxRingAddr, ring_dma & 0xffffffff); - cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); - - ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; - cpw32_f(TxRingAddr, ring_dma & 0xffffffff); - cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); - cp_start_hw(cp); cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ @@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp) cpw8(Config5, cpr8(Config5) & PMEStatus); + cpw32_f(HiTxRingAddr, 0); + cpw32_f(HiTxRingAddr + 4, 0); + + ring_dma = cp->ring_dma; + cpw32_f(RxRingAddr, ring_dma & 0xffffffff); + cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); + + ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; + cpw32_f(TxRingAddr, ring_dma & 0xffffffff); + cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); + cpw16(MultiIntr, 0); cpw8_f(Cfg9346, Cfg9346_Lock); @@ -1636,7 +1636,7 @@ static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len) static void eeprom_cmd_end(void __iomem *ee_addr) { - writeb(0, ee_addr); + writeb (~EE_CS, ee_addr); eeprom_delay (); } diff --git a/trunk/drivers/net/ethernet/realtek/8139too.c b/trunk/drivers/net/ethernet/realtek/8139too.c index 1d83565cc6af..03df076ed596 100644 --- a/trunk/drivers/net/ethernet/realtek/8139too.c +++ b/trunk/drivers/net/ethernet/realtek/8139too.c @@ -1173,7 +1173,7 @@ static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_l } /* Terminate the EEPROM access. */ - RTL_W8(Cfg9346, 0); + RTL_W8 (Cfg9346, ~EE_CS); eeprom_delay (); return retval; diff --git a/trunk/drivers/net/ethernet/realtek/r8169.c b/trunk/drivers/net/ethernet/realtek/r8169.c index 7260aa79466a..00b4f56a671c 100644 --- a/trunk/drivers/net/ethernet/realtek/r8169.c +++ b/trunk/drivers/net/ethernet/realtek/r8169.c @@ -5889,7 +5889,11 @@ static void rtl_slow_event_work(struct rtl8169_private *tp) if (status & LinkChg) __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); - rtl_irq_enable_all(tp); + napi_disable(&tp->napi); + rtl_irq_disable(tp); + + napi_enable(&tp->napi); + napi_schedule(&tp->napi); } static void rtl_task(struct work_struct *work) @@ -6341,8 +6345,6 @@ static void __devexit rtl_remove_one(struct pci_dev *pdev) cancel_work_sync(&tp->wk.work); - netif_napi_del(&tp->napi); - unregister_netdev(dev); rtl_release_firmware(tp); @@ -6666,7 +6668,6 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; err_out_msi_4: - netif_napi_del(&tp->napi); rtl_disable_msi(pdev, tp); iounmap(ioaddr); err_out_free_res_3: diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/Kconfig b/trunk/drivers/net/ethernet/stmicro/stmmac/Kconfig index 9f448279e12a..036428348faa 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -13,7 +13,7 @@ config STMMAC_ETH if STMMAC_ETH config STMMAC_PLATFORM - bool "STMMAC Platform bus support" + tristate "STMMAC platform bus support" depends on STMMAC_ETH default y ---help--- @@ -26,7 +26,7 @@ config STMMAC_PLATFORM If unsure, say N. config STMMAC_PCI - bool "STMMAC PCI bus support (EXPERIMENTAL)" + tristate "STMMAC support on PCI bus (EXPERIMENTAL)" depends on STMMAC_ETH && PCI && EXPERIMENTAL ---help--- This is to select the Synopsys DWMAC available on PCI devices, diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h index dc20c56efc9d..6b5d060ee9de 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -26,7 +26,6 @@ #include #include #include -#include #include "common.h" #ifdef CONFIG_STMMAC_TIMER #include "stmmac_timer.h" @@ -96,6 +95,7 @@ extern int stmmac_mdio_register(struct net_device *ndev); extern void stmmac_set_ethtool_ops(struct net_device *netdev); extern const struct stmmac_desc_ops enh_desc_ops; extern const struct stmmac_desc_ops ndesc_ops; + int stmmac_freeze(struct net_device *ndev); int stmmac_restore(struct net_device *ndev); int stmmac_resume(struct net_device *ndev); @@ -109,7 +109,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, static inline int stmmac_clk_enable(struct stmmac_priv *priv) { if (!IS_ERR(priv->stmmac_clk)) - return clk_prepare_enable(priv->stmmac_clk); + return clk_enable(priv->stmmac_clk); return 0; } @@ -119,7 +119,7 @@ static inline void stmmac_clk_disable(struct stmmac_priv *priv) if (IS_ERR(priv->stmmac_clk)) return; - clk_disable_unprepare(priv->stmmac_clk); + clk_disable(priv->stmmac_clk); } static inline int stmmac_clk_get(struct stmmac_priv *priv) { @@ -143,60 +143,3 @@ static inline int stmmac_clk_get(struct stmmac_priv *priv) return 0; } #endif /* CONFIG_HAVE_CLK */ - - -#ifdef CONFIG_STMMAC_PLATFORM -extern struct platform_driver stmmac_pltfr_driver; -static inline int stmmac_register_platform(void) -{ - int err; - - err = platform_driver_register(&stmmac_pltfr_driver); - if (err) - pr_err("stmmac: failed to register the platform driver\n"); - - return err; -} -static inline void stmmac_unregister_platform(void) -{ - platform_driver_register(&stmmac_pltfr_driver); -} -#else -static inline int stmmac_register_platform(void) -{ - pr_debug("stmmac: do not register the platf driver\n"); - - return -EINVAL; -} -static inline void stmmac_unregister_platform(void) -{ -} -#endif /* CONFIG_STMMAC_PLATFORM */ - -#ifdef CONFIG_STMMAC_PCI -extern struct pci_driver stmmac_pci_driver; -static inline int stmmac_register_pci(void) -{ - int err; - - err = pci_register_driver(&stmmac_pci_driver); - if (err) - pr_err("stmmac: failed to register the PCI driver\n"); - - return err; -} -static inline void stmmac_unregister_pci(void) -{ - pci_unregister_driver(&stmmac_pci_driver); -} -#else -static inline int stmmac_register_pci(void) -{ - pr_debug("stmmac: do not register the PCI driver\n"); - - return -EINVAL; -} -static inline void stmmac_unregister_pci(void) -{ -} -#endif /* CONFIG_STMMAC_PCI */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 51b3b68528ee..70966330f44e 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -833,9 +833,8 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) /** * stmmac_selec_desc_mode - * @priv : private structure - * Description: select the Enhanced/Alternate or Normal descriptors - */ + * @dev : device pointer + * Description: select the Enhanced/Alternate or Normal descriptors */ static void stmmac_selec_desc_mode(struct stmmac_priv *priv) { if (priv->plat->enh_desc) { @@ -1862,8 +1861,6 @@ static int stmmac_hw_init(struct stmmac_priv *priv) /** * stmmac_dvr_probe * @device: device pointer - * @plat_dat: platform data pointer - * @addr: iobase memory address * Description: this is the main probe function used to * call the alloc_etherdev, allocate the priv structure. */ @@ -2093,34 +2090,6 @@ int stmmac_restore(struct net_device *ndev) } #endif /* CONFIG_PM */ -/* Driver can be configured w/ and w/ both PCI and Platf drivers - * depending on the configuration selected. - */ -static int __init stmmac_init(void) -{ - int err_plt = 0; - int err_pci = 0; - - err_plt = stmmac_register_platform(); - err_pci = stmmac_register_pci(); - - if ((err_pci) && (err_plt)) { - pr_err("stmmac: driver registration failed\n"); - return -EINVAL; - } - - return 0; -} - -static void __exit stmmac_exit(void) -{ - stmmac_unregister_platform(); - stmmac_unregister_pci(); -} - -module_init(stmmac_init); -module_exit(stmmac_exit); - #ifndef MODULE static int __init stmmac_cmdline_opt(char *str) { diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index cf826e6b6aa1..58fab5303e9c 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -179,7 +179,7 @@ static DEFINE_PCI_DEVICE_TABLE(stmmac_id_table) = { MODULE_DEVICE_TABLE(pci, stmmac_id_table); -struct pci_driver stmmac_pci_driver = { +static struct pci_driver stmmac_driver = { .name = STMMAC_RESOURCE_NAME, .id_table = stmmac_id_table, .probe = stmmac_pci_probe, @@ -190,6 +190,33 @@ struct pci_driver stmmac_pci_driver = { #endif }; +/** + * stmmac_init_module - Entry point for the driver + * Description: This function is the entry point for the driver. + */ +static int __init stmmac_init_module(void) +{ + int ret; + + ret = pci_register_driver(&stmmac_driver); + if (ret < 0) + pr_err("%s: ERROR: driver registration failed\n", __func__); + + return ret; +} + +/** + * stmmac_cleanup_module - Cleanup routine for the driver + * Description: This function is the cleanup routine for the driver. + */ +static void __exit stmmac_cleanup_module(void) +{ + pci_unregister_driver(&stmmac_driver); +} + +module_init(stmmac_init_module); +module_exit(stmmac_cleanup_module); + MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PCI driver"); MODULE_AUTHOR("Rayagond Kokatanur "); MODULE_AUTHOR("Giuseppe Cavallaro "); diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 680d2b8dfe27..3dd8f0803808 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -255,7 +255,7 @@ static const struct of_device_id stmmac_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, stmmac_dt_ids); -struct platform_driver stmmac_pltfr_driver = { +static struct platform_driver stmmac_driver = { .probe = stmmac_pltfr_probe, .remove = stmmac_pltfr_remove, .driver = { @@ -266,6 +266,8 @@ struct platform_driver stmmac_pltfr_driver = { }, }; +module_platform_driver(stmmac_driver); + MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver"); MODULE_AUTHOR("Giuseppe Cavallaro "); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/ethernet/sun/niu.c b/trunk/drivers/net/ethernet/sun/niu.c index 8c726b7004d3..703c8cce2a2c 100644 --- a/trunk/drivers/net/ethernet/sun/niu.c +++ b/trunk/drivers/net/ethernet/sun/niu.c @@ -3598,6 +3598,7 @@ static int release_tx_packet(struct niu *np, struct tx_ring_info *rp, int idx) static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) { struct netdev_queue *txq; + unsigned int tx_bytes; u16 pkt_cnt, tmp; int cons, index; u64 cs; @@ -3620,12 +3621,18 @@ static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) netif_printk(np, tx_done, KERN_DEBUG, np->dev, "%s() pkt_cnt[%u] cons[%d]\n", __func__, pkt_cnt, cons); - while (pkt_cnt--) + tx_bytes = 0; + tmp = pkt_cnt; + while (tmp--) { + tx_bytes += rp->tx_buffs[cons].skb->len; cons = release_tx_packet(np, rp, cons); + } rp->cons = cons; smp_mb(); + netdev_tx_completed_queue(txq, pkt_cnt, tx_bytes); + out: if (unlikely(netif_tx_queue_stopped(txq) && (niu_tx_avail(rp) > NIU_TX_WAKEUP_THRESH(rp)))) { @@ -4326,6 +4333,7 @@ static void niu_free_channels(struct niu *np) struct tx_ring_info *rp = &np->tx_rings[i]; niu_free_tx_ring_info(np, rp); + netdev_tx_reset_queue(netdev_get_tx_queue(np->dev, i)); } kfree(np->tx_rings); np->tx_rings = NULL; @@ -6731,6 +6739,8 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb, prod = NEXT_TX(rp, prod); } + netdev_tx_sent_queue(txq, skb->len); + if (prod < rp->prod) rp->wrap_bit ^= TX_RING_KICK_WRAP; rp->prod = prod; diff --git a/trunk/drivers/net/ethernet/tile/Kconfig b/trunk/drivers/net/ethernet/tile/Kconfig index 098b1c42b393..2d9218f86bca 100644 --- a/trunk/drivers/net/ethernet/tile/Kconfig +++ b/trunk/drivers/net/ethernet/tile/Kconfig @@ -7,8 +7,6 @@ config TILE_NET depends on TILE default y select CRC32 - select TILE_GXIO_MPIPE if TILEGX - select HIGH_RES_TIMERS if TILEGX ---help--- This is a standard Linux network device driver for the on-chip Tilera Gigabit Ethernet and XAUI interfaces. diff --git a/trunk/drivers/net/ethernet/tile/Makefile b/trunk/drivers/net/ethernet/tile/Makefile index 0ef9eefd3211..f634f142cab4 100644 --- a/trunk/drivers/net/ethernet/tile/Makefile +++ b/trunk/drivers/net/ethernet/tile/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_TILE_NET) += tile_net.o ifdef CONFIG_TILEGX -tile_net-y := tilegx.o +tile_net-objs := tilegx.o mpipe.o iorpc_mpipe.o dma_queue.o else -tile_net-y := tilepro.o +tile_net-objs := tilepro.o endif diff --git a/trunk/drivers/net/ethernet/tile/tilegx.c b/trunk/drivers/net/ethernet/tile/tilegx.c deleted file mode 100644 index 83b4b388ad49..000000000000 --- a/trunk/drivers/net/ethernet/tile/tilegx.c +++ /dev/null @@ -1,1898 +0,0 @@ -/* - * Copyright 2012 Tilera Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for - * more details. - */ - -#include -#include -#include -#include -#include /* printk() */ -#include /* kmalloc() */ -#include /* error codes */ -#include /* size_t */ -#include -#include -#include -#include /* struct device, and other headers */ -#include /* eth_type_trans */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* Default transmit lockup timeout period, in jiffies. */ -#define TILE_NET_TIMEOUT (5 * HZ) - -/* The maximum number of distinct channels (idesc.channel is 5 bits). */ -#define TILE_NET_CHANNELS 32 - -/* Maximum number of idescs to handle per "poll". */ -#define TILE_NET_BATCH 128 - -/* Maximum number of packets to handle per "poll". */ -#define TILE_NET_WEIGHT 64 - -/* Number of entries in each iqueue. */ -#define IQUEUE_ENTRIES 512 - -/* Number of entries in each equeue. */ -#define EQUEUE_ENTRIES 2048 - -/* Total header bytes per equeue slot. Must be big enough for 2 bytes - * of NET_IP_ALIGN alignment, plus 14 bytes (?) of L2 header, plus up to - * 60 bytes of actual TCP header. We round up to align to cache lines. - */ -#define HEADER_BYTES 128 - -/* Maximum completions per cpu per device (must be a power of two). - * ISSUE: What is the right number here? If this is too small, then - * egress might block waiting for free space in a completions array. - * ISSUE: At the least, allocate these only for initialized echannels. - */ -#define TILE_NET_MAX_COMPS 64 - -#define MAX_FRAGS (MAX_SKB_FRAGS + 1) - -/* Size of completions data to allocate. - * ISSUE: Probably more than needed since we don't use all the channels. - */ -#define COMPS_SIZE (TILE_NET_CHANNELS * sizeof(struct tile_net_comps)) - -/* Size of NotifRing data to allocate. */ -#define NOTIF_RING_SIZE (IQUEUE_ENTRIES * sizeof(gxio_mpipe_idesc_t)) - -/* Timeout to wake the per-device TX timer after we stop the queue. - * We don't want the timeout too short (adds overhead, and might end - * up causing stop/wake/stop/wake cycles) or too long (affects performance). - * For the 10 Gb NIC, 30 usec means roughly 30+ 1500-byte packets. - */ -#define TX_TIMER_DELAY_USEC 30 - -/* Timeout to wake the per-cpu egress timer to free completions. */ -#define EGRESS_TIMER_DELAY_USEC 1000 - -MODULE_AUTHOR("Tilera Corporation"); -MODULE_LICENSE("GPL"); - -/* A "packet fragment" (a chunk of memory). */ -struct frag { - void *buf; - size_t length; -}; - -/* A single completion. */ -struct tile_net_comp { - /* The "complete_count" when the completion will be complete. */ - s64 when; - /* The buffer to be freed when the completion is complete. */ - struct sk_buff *skb; -}; - -/* The completions for a given cpu and echannel. */ -struct tile_net_comps { - /* The completions. */ - struct tile_net_comp comp_queue[TILE_NET_MAX_COMPS]; - /* The number of completions used. */ - unsigned long comp_next; - /* The number of completions freed. */ - unsigned long comp_last; -}; - -/* The transmit wake timer for a given cpu and echannel. */ -struct tile_net_tx_wake { - struct hrtimer timer; - struct net_device *dev; -}; - -/* Info for a specific cpu. */ -struct tile_net_info { - /* The NAPI struct. */ - struct napi_struct napi; - /* Packet queue. */ - gxio_mpipe_iqueue_t iqueue; - /* Our cpu. */ - int my_cpu; - /* True if iqueue is valid. */ - bool has_iqueue; - /* NAPI flags. */ - bool napi_added; - bool napi_enabled; - /* Number of small sk_buffs which must still be provided. */ - unsigned int num_needed_small_buffers; - /* Number of large sk_buffs which must still be provided. */ - unsigned int num_needed_large_buffers; - /* A timer for handling egress completions. */ - struct hrtimer egress_timer; - /* True if "egress_timer" is scheduled. */ - bool egress_timer_scheduled; - /* Comps for each egress channel. */ - struct tile_net_comps *comps_for_echannel[TILE_NET_CHANNELS]; - /* Transmit wake timer for each egress channel. */ - struct tile_net_tx_wake tx_wake[TILE_NET_CHANNELS]; -}; - -/* Info for egress on a particular egress channel. */ -struct tile_net_egress { - /* The "equeue". */ - gxio_mpipe_equeue_t *equeue; - /* The headers for TSO. */ - unsigned char *headers; -}; - -/* Info for a specific device. */ -struct tile_net_priv { - /* Our network device. */ - struct net_device *dev; - /* The primary link. */ - gxio_mpipe_link_t link; - /* The primary channel, if open, else -1. */ - int channel; - /* The "loopify" egress link, if needed. */ - gxio_mpipe_link_t loopify_link; - /* The "loopify" egress channel, if open, else -1. */ - int loopify_channel; - /* The egress channel (channel or loopify_channel). */ - int echannel; - /* Total stats. */ - struct net_device_stats stats; -}; - -/* Egress info, indexed by "priv->echannel" (lazily created as needed). */ -static struct tile_net_egress egress_for_echannel[TILE_NET_CHANNELS]; - -/* Devices currently associated with each channel. - * NOTE: The array entry can become NULL after ifconfig down, but - * we do not free the underlying net_device structures, so it is - * safe to use a pointer after reading it from this array. - */ -static struct net_device *tile_net_devs_for_channel[TILE_NET_CHANNELS]; - -/* A mutex for "tile_net_devs_for_channel". */ -static DEFINE_MUTEX(tile_net_devs_for_channel_mutex); - -/* The per-cpu info. */ -static DEFINE_PER_CPU(struct tile_net_info, per_cpu_info); - -/* The "context" for all devices. */ -static gxio_mpipe_context_t context; - -/* Buffer sizes and mpipe enum codes for buffer stacks. - * See arch/tile/include/gxio/mpipe.h for the set of possible values. - */ -#define BUFFER_SIZE_SMALL_ENUM GXIO_MPIPE_BUFFER_SIZE_128 -#define BUFFER_SIZE_SMALL 128 -#define BUFFER_SIZE_LARGE_ENUM GXIO_MPIPE_BUFFER_SIZE_1664 -#define BUFFER_SIZE_LARGE 1664 - -/* The small/large "buffer stacks". */ -static int small_buffer_stack = -1; -static int large_buffer_stack = -1; - -/* Amount of memory allocated for each buffer stack. */ -static size_t buffer_stack_size; - -/* The actual memory allocated for the buffer stacks. */ -static void *small_buffer_stack_va; -static void *large_buffer_stack_va; - -/* The buckets. */ -static int first_bucket = -1; -static int num_buckets = 1; - -/* The ingress irq. */ -static int ingress_irq = -1; - -/* Text value of tile_net.cpus if passed as a module parameter. */ -static char *network_cpus_string; - -/* The actual cpus in "network_cpus". */ -static struct cpumask network_cpus_map; - -/* If "loopify=LINK" was specified, this is "LINK". */ -static char *loopify_link_name; - -/* If "tile_net.custom" was specified, this is non-NULL. */ -static char *custom_str; - -/* The "tile_net.cpus" argument specifies the cpus that are dedicated - * to handle ingress packets. - * - * The parameter should be in the form "tile_net.cpus=m-n[,x-y]", where - * m, n, x, y are integer numbers that represent the cpus that can be - * neither a dedicated cpu nor a dataplane cpu. - */ -static bool network_cpus_init(void) -{ - char buf[1024]; - int rc; - - if (network_cpus_string == NULL) - return false; - - rc = cpulist_parse_crop(network_cpus_string, &network_cpus_map); - if (rc != 0) { - pr_warn("tile_net.cpus=%s: malformed cpu list\n", - network_cpus_string); - return false; - } - - /* Remove dedicated cpus. */ - cpumask_and(&network_cpus_map, &network_cpus_map, cpu_possible_mask); - - if (cpumask_empty(&network_cpus_map)) { - pr_warn("Ignoring empty tile_net.cpus='%s'.\n", - network_cpus_string); - return false; - } - - cpulist_scnprintf(buf, sizeof(buf), &network_cpus_map); - pr_info("Linux network CPUs: %s\n", buf); - return true; -} - -module_param_named(cpus, network_cpus_string, charp, 0444); -MODULE_PARM_DESC(cpus, "cpulist of cores that handle network interrupts"); - -/* The "tile_net.loopify=LINK" argument causes the named device to - * actually use "loop0" for ingress, and "loop1" for egress. This - * allows an app to sit between the actual link and linux, passing - * (some) packets along to linux, and forwarding (some) packets sent - * out by linux. - */ -module_param_named(loopify, loopify_link_name, charp, 0444); -MODULE_PARM_DESC(loopify, "name the device to use loop0/1 for ingress/egress"); - -/* The "tile_net.custom" argument causes us to ignore the "conventional" - * classifier metadata, in particular, the "l2_offset". - */ -module_param_named(custom, custom_str, charp, 0444); -MODULE_PARM_DESC(custom, "indicates a (heavily) customized classifier"); - -/* Atomically update a statistics field. - * Note that on TILE-Gx, this operation is fire-and-forget on the - * issuing core (single-cycle dispatch) and takes only a few cycles - * longer than a regular store when the request reaches the home cache. - * No expensive bus management overhead is required. - */ -static void tile_net_stats_add(unsigned long value, unsigned long *field) -{ - BUILD_BUG_ON(sizeof(atomic_long_t) != sizeof(unsigned long)); - atomic_long_add(value, (atomic_long_t *)field); -} - -/* Allocate and push a buffer. */ -static bool tile_net_provide_buffer(bool small) -{ - int stack = small ? small_buffer_stack : large_buffer_stack; - const unsigned long buffer_alignment = 128; - struct sk_buff *skb; - int len; - - len = sizeof(struct sk_buff **) + buffer_alignment; - len += (small ? BUFFER_SIZE_SMALL : BUFFER_SIZE_LARGE); - skb = dev_alloc_skb(len); - if (skb == NULL) - return false; - - /* Make room for a back-pointer to 'skb' and guarantee alignment. */ - skb_reserve(skb, sizeof(struct sk_buff **)); - skb_reserve(skb, -(long)skb->data & (buffer_alignment - 1)); - - /* Save a back-pointer to 'skb'. */ - *(struct sk_buff **)(skb->data - sizeof(struct sk_buff **)) = skb; - - /* Make sure "skb" and the back-pointer have been flushed. */ - wmb(); - - gxio_mpipe_push_buffer(&context, stack, - (void *)va_to_tile_io_addr(skb->data)); - - return true; -} - -/* Convert a raw mpipe buffer to its matching skb pointer. */ -static struct sk_buff *mpipe_buf_to_skb(void *va) -{ - /* Acquire the associated "skb". */ - struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); - struct sk_buff *skb = *skb_ptr; - - /* Paranoia. */ - if (skb->data != va) { - /* Panic here since there's a reasonable chance - * that corrupt buffers means generic memory - * corruption, with unpredictable system effects. - */ - panic("Corrupt linux buffer! va=%p, skb=%p, skb->data=%p", - va, skb, skb->data); - } - - return skb; -} - -static void tile_net_pop_all_buffers(int stack) -{ - for (;;) { - tile_io_addr_t addr = - (tile_io_addr_t)gxio_mpipe_pop_buffer(&context, stack); - if (addr == 0) - break; - dev_kfree_skb_irq(mpipe_buf_to_skb(tile_io_addr_to_va(addr))); - } -} - -/* Provide linux buffers to mPIPE. */ -static void tile_net_provide_needed_buffers(void) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - - while (info->num_needed_small_buffers != 0) { - if (!tile_net_provide_buffer(true)) - goto oops; - info->num_needed_small_buffers--; - } - - while (info->num_needed_large_buffers != 0) { - if (!tile_net_provide_buffer(false)) - goto oops; - info->num_needed_large_buffers--; - } - - return; - -oops: - /* Add a description to the page allocation failure dump. */ - pr_notice("Tile %d still needs some buffers\n", info->my_cpu); -} - -static inline bool filter_packet(struct net_device *dev, void *buf) -{ - /* Filter packets received before we're up. */ - if (dev == NULL || !(dev->flags & IFF_UP)) - return true; - - /* Filter out packets that aren't for us. */ - if (!(dev->flags & IFF_PROMISC) && - !is_multicast_ether_addr(buf) && - compare_ether_addr(dev->dev_addr, buf) != 0) - return true; - - return false; -} - -static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb, - gxio_mpipe_idesc_t *idesc, unsigned long len) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - - /* Encode the actual packet length. */ - skb_put(skb, len); - - skb->protocol = eth_type_trans(skb, dev); - - /* Acknowledge "good" hardware checksums. */ - if (idesc->cs && idesc->csum_seed_val == 0xFFFF) - skb->ip_summed = CHECKSUM_UNNECESSARY; - - netif_receive_skb(skb); - - /* Update stats. */ - tile_net_stats_add(1, &priv->stats.rx_packets); - tile_net_stats_add(len, &priv->stats.rx_bytes); - - /* Need a new buffer. */ - if (idesc->size == BUFFER_SIZE_SMALL_ENUM) - info->num_needed_small_buffers++; - else - info->num_needed_large_buffers++; -} - -/* Handle a packet. Return true if "processed", false if "filtered". */ -static bool tile_net_handle_packet(gxio_mpipe_idesc_t *idesc) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct net_device *dev = tile_net_devs_for_channel[idesc->channel]; - uint8_t l2_offset; - void *va; - void *buf; - unsigned long len; - bool filter; - - /* Drop packets for which no buffer was available. - * NOTE: This happens under heavy load. - */ - if (idesc->be) { - struct tile_net_priv *priv = netdev_priv(dev); - tile_net_stats_add(1, &priv->stats.rx_dropped); - gxio_mpipe_iqueue_consume(&info->iqueue, idesc); - if (net_ratelimit()) - pr_info("Dropping packet (insufficient buffers).\n"); - return false; - } - - /* Get the "l2_offset", if allowed. */ - l2_offset = custom_str ? 0 : gxio_mpipe_idesc_get_l2_offset(idesc); - - /* Get the raw buffer VA (includes "headroom"). */ - va = tile_io_addr_to_va((unsigned long)(long)idesc->va); - - /* Get the actual packet start/length. */ - buf = va + l2_offset; - len = idesc->l2_size - l2_offset; - - /* Point "va" at the raw buffer. */ - va -= NET_IP_ALIGN; - - filter = filter_packet(dev, buf); - if (filter) { - gxio_mpipe_iqueue_drop(&info->iqueue, idesc); - } else { - struct sk_buff *skb = mpipe_buf_to_skb(va); - - /* Skip headroom, and any custom header. */ - skb_reserve(skb, NET_IP_ALIGN + l2_offset); - - tile_net_receive_skb(dev, skb, idesc, len); - } - - gxio_mpipe_iqueue_consume(&info->iqueue, idesc); - return !filter; -} - -/* Handle some packets for the current CPU. - * - * This function handles up to TILE_NET_BATCH idescs per call. - * - * ISSUE: Since we do not provide new buffers until this function is - * complete, we must initially provide enough buffers for each network - * cpu to fill its iqueue and also its batched idescs. - * - * ISSUE: The "rotting packet" race condition occurs if a packet - * arrives after the queue appears to be empty, and before the - * hypervisor interrupt is re-enabled. - */ -static int tile_net_poll(struct napi_struct *napi, int budget) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - unsigned int work = 0; - gxio_mpipe_idesc_t *idesc; - int i, n; - - /* Process packets. */ - while ((n = gxio_mpipe_iqueue_try_peek(&info->iqueue, &idesc)) > 0) { - for (i = 0; i < n; i++) { - if (i == TILE_NET_BATCH) - goto done; - if (tile_net_handle_packet(idesc + i)) { - if (++work >= budget) - goto done; - } - } - } - - /* There are no packets left. */ - napi_complete(&info->napi); - - /* Re-enable hypervisor interrupts. */ - gxio_mpipe_enable_notif_ring_interrupt(&context, info->iqueue.ring); - - /* HACK: Avoid the "rotting packet" problem. */ - if (gxio_mpipe_iqueue_try_peek(&info->iqueue, &idesc) > 0) - napi_schedule(&info->napi); - - /* ISSUE: Handle completions? */ - -done: - tile_net_provide_needed_buffers(); - - return work; -} - -/* Handle an ingress interrupt on the current cpu. */ -static irqreturn_t tile_net_handle_ingress_irq(int irq, void *unused) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - napi_schedule(&info->napi); - return IRQ_HANDLED; -} - -/* Free some completions. This must be called with interrupts blocked. */ -static int tile_net_free_comps(gxio_mpipe_equeue_t *equeue, - struct tile_net_comps *comps, - int limit, bool force_update) -{ - int n = 0; - while (comps->comp_last < comps->comp_next) { - unsigned int cid = comps->comp_last % TILE_NET_MAX_COMPS; - struct tile_net_comp *comp = &comps->comp_queue[cid]; - if (!gxio_mpipe_equeue_is_complete(equeue, comp->when, - force_update || n == 0)) - break; - dev_kfree_skb_irq(comp->skb); - comps->comp_last++; - if (++n == limit) - break; - } - return n; -} - -/* Add a completion. This must be called with interrupts blocked. - * tile_net_equeue_try_reserve() will have ensured a free completion entry. - */ -static void add_comp(gxio_mpipe_equeue_t *equeue, - struct tile_net_comps *comps, - uint64_t when, struct sk_buff *skb) -{ - int cid = comps->comp_next % TILE_NET_MAX_COMPS; - comps->comp_queue[cid].when = when; - comps->comp_queue[cid].skb = skb; - comps->comp_next++; -} - -static void tile_net_schedule_tx_wake_timer(struct net_device *dev) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - - hrtimer_start(&info->tx_wake[priv->echannel].timer, - ktime_set(0, TX_TIMER_DELAY_USEC * 1000UL), - HRTIMER_MODE_REL_PINNED); -} - -static enum hrtimer_restart tile_net_handle_tx_wake_timer(struct hrtimer *t) -{ - struct tile_net_tx_wake *tx_wake = - container_of(t, struct tile_net_tx_wake, timer); - netif_wake_subqueue(tx_wake->dev, smp_processor_id()); - return HRTIMER_NORESTART; -} - -/* Make sure the egress timer is scheduled. */ -static void tile_net_schedule_egress_timer(void) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - - if (!info->egress_timer_scheduled) { - hrtimer_start(&info->egress_timer, - ktime_set(0, EGRESS_TIMER_DELAY_USEC * 1000UL), - HRTIMER_MODE_REL_PINNED); - info->egress_timer_scheduled = true; - } -} - -/* The "function" for "info->egress_timer". - * - * This timer will reschedule itself as long as there are any pending - * completions expected for this tile. - */ -static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - unsigned long irqflags; - bool pending = false; - int i; - - local_irq_save(irqflags); - - /* The timer is no longer scheduled. */ - info->egress_timer_scheduled = false; - - /* Free all possible comps for this tile. */ - for (i = 0; i < TILE_NET_CHANNELS; i++) { - struct tile_net_egress *egress = &egress_for_echannel[i]; - struct tile_net_comps *comps = info->comps_for_echannel[i]; - if (comps->comp_last >= comps->comp_next) - continue; - tile_net_free_comps(egress->equeue, comps, -1, true); - pending = pending || (comps->comp_last < comps->comp_next); - } - - /* Reschedule timer if needed. */ - if (pending) - tile_net_schedule_egress_timer(); - - local_irq_restore(irqflags); - - return HRTIMER_NORESTART; -} - -/* Helper function for "tile_net_update()". - * "dev" (i.e. arg) is the device being brought up or down, - * or NULL if all devices are now down. - */ -static void tile_net_update_cpu(void *arg) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct net_device *dev = arg; - - if (!info->has_iqueue) - return; - - if (dev != NULL) { - if (!info->napi_added) { - netif_napi_add(dev, &info->napi, - tile_net_poll, TILE_NET_WEIGHT); - info->napi_added = true; - } - if (!info->napi_enabled) { - napi_enable(&info->napi); - info->napi_enabled = true; - } - enable_percpu_irq(ingress_irq, 0); - } else { - disable_percpu_irq(ingress_irq); - if (info->napi_enabled) { - napi_disable(&info->napi); - info->napi_enabled = false; - } - /* FIXME: Drain the iqueue. */ - } -} - -/* Helper function for tile_net_open() and tile_net_stop(). - * Always called under tile_net_devs_for_channel_mutex. - */ -static int tile_net_update(struct net_device *dev) -{ - static gxio_mpipe_rules_t rules; /* too big to fit on the stack */ - bool saw_channel = false; - int channel; - int rc; - int cpu; - - gxio_mpipe_rules_init(&rules, &context); - - for (channel = 0; channel < TILE_NET_CHANNELS; channel++) { - if (tile_net_devs_for_channel[channel] == NULL) - continue; - if (!saw_channel) { - saw_channel = true; - gxio_mpipe_rules_begin(&rules, first_bucket, - num_buckets, NULL); - gxio_mpipe_rules_set_headroom(&rules, NET_IP_ALIGN); - } - gxio_mpipe_rules_add_channel(&rules, channel); - } - - /* NOTE: This can fail if there is no classifier. - * ISSUE: Can anything else cause it to fail? - */ - rc = gxio_mpipe_rules_commit(&rules); - if (rc != 0) { - netdev_warn(dev, "gxio_mpipe_rules_commit failed: %d\n", rc); - return -EIO; - } - - /* Update all cpus, sequentially (to protect "netif_napi_add()"). */ - for_each_online_cpu(cpu) - smp_call_function_single(cpu, tile_net_update_cpu, - (saw_channel ? dev : NULL), 1); - - /* HACK: Allow packets to flow in the simulator. */ - if (saw_channel) - sim_enable_mpipe_links(0, -1); - - return 0; -} - -/* Allocate and initialize mpipe buffer stacks, and register them in - * the mPIPE TLBs, for both small and large packet sizes. - * This routine supports tile_net_init_mpipe(), below. - */ -static int init_buffer_stacks(struct net_device *dev, int num_buffers) -{ - pte_t hash_pte = pte_set_home((pte_t) { 0 }, PAGE_HOME_HASH); - int rc; - - /* Compute stack bytes; we round up to 64KB and then use - * alloc_pages() so we get the required 64KB alignment as well. - */ - buffer_stack_size = - ALIGN(gxio_mpipe_calc_buffer_stack_bytes(num_buffers), - 64 * 1024); - - /* Allocate two buffer stack indices. */ - rc = gxio_mpipe_alloc_buffer_stacks(&context, 2, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_buffer_stacks failed: %d\n", - rc); - return rc; - } - small_buffer_stack = rc; - large_buffer_stack = rc + 1; - - /* Allocate the small memory stack. */ - small_buffer_stack_va = - alloc_pages_exact(buffer_stack_size, GFP_KERNEL); - if (small_buffer_stack_va == NULL) { - netdev_err(dev, - "Could not alloc %zd bytes for buffer stacks\n", - buffer_stack_size); - return -ENOMEM; - } - rc = gxio_mpipe_init_buffer_stack(&context, small_buffer_stack, - BUFFER_SIZE_SMALL_ENUM, - small_buffer_stack_va, - buffer_stack_size, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init_buffer_stack: %d\n", rc); - return rc; - } - rc = gxio_mpipe_register_client_memory(&context, small_buffer_stack, - hash_pte, 0); - if (rc != 0) { - netdev_err(dev, - "gxio_mpipe_register_buffer_memory failed: %d\n", - rc); - return rc; - } - - /* Allocate the large buffer stack. */ - large_buffer_stack_va = - alloc_pages_exact(buffer_stack_size, GFP_KERNEL); - if (large_buffer_stack_va == NULL) { - netdev_err(dev, - "Could not alloc %zd bytes for buffer stacks\n", - buffer_stack_size); - return -ENOMEM; - } - rc = gxio_mpipe_init_buffer_stack(&context, large_buffer_stack, - BUFFER_SIZE_LARGE_ENUM, - large_buffer_stack_va, - buffer_stack_size, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init_buffer_stack failed: %d\n", - rc); - return rc; - } - rc = gxio_mpipe_register_client_memory(&context, large_buffer_stack, - hash_pte, 0); - if (rc != 0) { - netdev_err(dev, - "gxio_mpipe_register_buffer_memory failed: %d\n", - rc); - return rc; - } - - return 0; -} - -/* Allocate per-cpu resources (memory for completions and idescs). - * This routine supports tile_net_init_mpipe(), below. - */ -static int alloc_percpu_mpipe_resources(struct net_device *dev, - int cpu, int ring) -{ - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - int order, i, rc; - struct page *page; - void *addr; - - /* Allocate the "comps". */ - order = get_order(COMPS_SIZE); - page = homecache_alloc_pages(GFP_KERNEL, order, cpu); - if (page == NULL) { - netdev_err(dev, "Failed to alloc %zd bytes comps memory\n", - COMPS_SIZE); - return -ENOMEM; - } - addr = pfn_to_kaddr(page_to_pfn(page)); - memset(addr, 0, COMPS_SIZE); - for (i = 0; i < TILE_NET_CHANNELS; i++) - info->comps_for_echannel[i] = - addr + i * sizeof(struct tile_net_comps); - - /* If this is a network cpu, create an iqueue. */ - if (cpu_isset(cpu, network_cpus_map)) { - order = get_order(NOTIF_RING_SIZE); - page = homecache_alloc_pages(GFP_KERNEL, order, cpu); - if (page == NULL) { - netdev_err(dev, - "Failed to alloc %zd bytes iqueue memory\n", - NOTIF_RING_SIZE); - return -ENOMEM; - } - addr = pfn_to_kaddr(page_to_pfn(page)); - rc = gxio_mpipe_iqueue_init(&info->iqueue, &context, ring++, - addr, NOTIF_RING_SIZE, 0); - if (rc < 0) { - netdev_err(dev, - "gxio_mpipe_iqueue_init failed: %d\n", rc); - return rc; - } - info->has_iqueue = true; - } - - return ring; -} - -/* Initialize NotifGroup and buckets. - * This routine supports tile_net_init_mpipe(), below. - */ -static int init_notif_group_and_buckets(struct net_device *dev, - int ring, int network_cpus_count) -{ - int group, rc; - - /* Allocate one NotifGroup. */ - rc = gxio_mpipe_alloc_notif_groups(&context, 1, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_notif_groups failed: %d\n", - rc); - return rc; - } - group = rc; - - /* Initialize global num_buckets value. */ - if (network_cpus_count > 4) - num_buckets = 256; - else if (network_cpus_count > 1) - num_buckets = 16; - - /* Allocate some buckets, and set global first_bucket value. */ - rc = gxio_mpipe_alloc_buckets(&context, num_buckets, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_buckets failed: %d\n", rc); - return rc; - } - first_bucket = rc; - - /* Init group and buckets. */ - rc = gxio_mpipe_init_notif_group_and_buckets( - &context, group, ring, network_cpus_count, - first_bucket, num_buckets, - GXIO_MPIPE_BUCKET_STICKY_FLOW_LOCALITY); - if (rc != 0) { - netdev_err( - dev, - "gxio_mpipe_init_notif_group_and_buckets failed: %d\n", - rc); - return rc; - } - - return 0; -} - -/* Create an irq and register it, then activate the irq and request - * interrupts on all cores. Note that "ingress_irq" being initialized - * is how we know not to call tile_net_init_mpipe() again. - * This routine supports tile_net_init_mpipe(), below. - */ -static int tile_net_setup_interrupts(struct net_device *dev) -{ - int cpu, rc; - - rc = create_irq(); - if (rc < 0) { - netdev_err(dev, "create_irq failed: %d\n", rc); - return rc; - } - ingress_irq = rc; - tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU); - rc = request_irq(ingress_irq, tile_net_handle_ingress_irq, - 0, NULL, NULL); - if (rc != 0) { - netdev_err(dev, "request_irq failed: %d\n", rc); - destroy_irq(ingress_irq); - ingress_irq = -1; - return rc; - } - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - if (info->has_iqueue) { - gxio_mpipe_request_notif_ring_interrupt( - &context, cpu_x(cpu), cpu_y(cpu), - 1, ingress_irq, info->iqueue.ring); - } - } - - return 0; -} - -/* Undo any state set up partially by a failed call to tile_net_init_mpipe. */ -static void tile_net_init_mpipe_fail(void) -{ - int cpu; - - /* Do cleanups that require the mpipe context first. */ - if (small_buffer_stack >= 0) - tile_net_pop_all_buffers(small_buffer_stack); - if (large_buffer_stack >= 0) - tile_net_pop_all_buffers(large_buffer_stack); - - /* Destroy mpipe context so the hardware no longer owns any memory. */ - gxio_mpipe_destroy(&context); - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - free_pages((unsigned long)(info->comps_for_echannel[0]), - get_order(COMPS_SIZE)); - info->comps_for_echannel[0] = NULL; - free_pages((unsigned long)(info->iqueue.idescs), - get_order(NOTIF_RING_SIZE)); - info->iqueue.idescs = NULL; - } - - if (small_buffer_stack_va) - free_pages_exact(small_buffer_stack_va, buffer_stack_size); - if (large_buffer_stack_va) - free_pages_exact(large_buffer_stack_va, buffer_stack_size); - - small_buffer_stack_va = NULL; - large_buffer_stack_va = NULL; - large_buffer_stack = -1; - small_buffer_stack = -1; - first_bucket = -1; -} - -/* The first time any tilegx network device is opened, we initialize - * the global mpipe state. If this step fails, we fail to open the - * device, but if it succeeds, we never need to do it again, and since - * tile_net can't be unloaded, we never undo it. - * - * Note that some resources in this path (buffer stack indices, - * bindings from init_buffer_stack, etc.) are hypervisor resources - * that are freed implicitly by gxio_mpipe_destroy(). - */ -static int tile_net_init_mpipe(struct net_device *dev) -{ - int i, num_buffers, rc; - int cpu; - int first_ring, ring; - int network_cpus_count = cpus_weight(network_cpus_map); - - if (!hash_default) { - netdev_err(dev, "Networking requires hash_default!\n"); - return -EIO; - } - - rc = gxio_mpipe_init(&context, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init failed: %d\n", rc); - return -EIO; - } - - /* Set up the buffer stacks. */ - num_buffers = - network_cpus_count * (IQUEUE_ENTRIES + TILE_NET_BATCH); - rc = init_buffer_stacks(dev, num_buffers); - if (rc != 0) - goto fail; - - /* Provide initial buffers. */ - rc = -ENOMEM; - for (i = 0; i < num_buffers; i++) { - if (!tile_net_provide_buffer(true)) { - netdev_err(dev, "Cannot allocate initial sk_bufs!\n"); - goto fail; - } - } - for (i = 0; i < num_buffers; i++) { - if (!tile_net_provide_buffer(false)) { - netdev_err(dev, "Cannot allocate initial sk_bufs!\n"); - goto fail; - } - } - - /* Allocate one NotifRing for each network cpu. */ - rc = gxio_mpipe_alloc_notif_rings(&context, network_cpus_count, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_notif_rings failed %d\n", - rc); - goto fail; - } - - /* Init NotifRings per-cpu. */ - first_ring = rc; - ring = first_ring; - for_each_online_cpu(cpu) { - rc = alloc_percpu_mpipe_resources(dev, cpu, ring); - if (rc < 0) - goto fail; - ring = rc; - } - - /* Initialize NotifGroup and buckets. */ - rc = init_notif_group_and_buckets(dev, first_ring, network_cpus_count); - if (rc != 0) - goto fail; - - /* Create and enable interrupts. */ - rc = tile_net_setup_interrupts(dev); - if (rc != 0) - goto fail; - - return 0; - -fail: - tile_net_init_mpipe_fail(); - return rc; -} - -/* Create persistent egress info for a given egress channel. - * Note that this may be shared between, say, "gbe0" and "xgbe0". - * ISSUE: Defer header allocation until TSO is actually needed? - */ -static int tile_net_init_egress(struct net_device *dev, int echannel) -{ - struct page *headers_page, *edescs_page, *equeue_page; - gxio_mpipe_edesc_t *edescs; - gxio_mpipe_equeue_t *equeue; - unsigned char *headers; - int headers_order, edescs_order, equeue_order; - size_t edescs_size; - int edma; - int rc = -ENOMEM; - - /* Only initialize once. */ - if (egress_for_echannel[echannel].equeue != NULL) - return 0; - - /* Allocate memory for the "headers". */ - headers_order = get_order(EQUEUE_ENTRIES * HEADER_BYTES); - headers_page = alloc_pages(GFP_KERNEL, headers_order); - if (headers_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for TSO headers.\n", - PAGE_SIZE << headers_order); - goto fail; - } - headers = pfn_to_kaddr(page_to_pfn(headers_page)); - - /* Allocate memory for the "edescs". */ - edescs_size = EQUEUE_ENTRIES * sizeof(*edescs); - edescs_order = get_order(edescs_size); - edescs_page = alloc_pages(GFP_KERNEL, edescs_order); - if (edescs_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for eDMA ring.\n", - edescs_size); - goto fail_headers; - } - edescs = pfn_to_kaddr(page_to_pfn(edescs_page)); - - /* Allocate memory for the "equeue". */ - equeue_order = get_order(sizeof(*equeue)); - equeue_page = alloc_pages(GFP_KERNEL, equeue_order); - if (equeue_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for equeue info.\n", - PAGE_SIZE << equeue_order); - goto fail_edescs; - } - equeue = pfn_to_kaddr(page_to_pfn(equeue_page)); - - /* Allocate an edma ring. Note that in practice this can't - * fail, which is good, because we will leak an edma ring if so. - */ - rc = gxio_mpipe_alloc_edma_rings(&context, 1, 0, 0); - if (rc < 0) { - netdev_warn(dev, "gxio_mpipe_alloc_edma_rings failed: %d\n", - rc); - goto fail_equeue; - } - edma = rc; - - /* Initialize the equeue. */ - rc = gxio_mpipe_equeue_init(equeue, &context, edma, echannel, - edescs, edescs_size, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_equeue_init failed: %d\n", rc); - goto fail_equeue; - } - - /* Done. */ - egress_for_echannel[echannel].equeue = equeue; - egress_for_echannel[echannel].headers = headers; - return 0; - -fail_equeue: - __free_pages(equeue_page, equeue_order); - -fail_edescs: - __free_pages(edescs_page, edescs_order); - -fail_headers: - __free_pages(headers_page, headers_order); - -fail: - return rc; -} - -/* Return channel number for a newly-opened link. */ -static int tile_net_link_open(struct net_device *dev, gxio_mpipe_link_t *link, - const char *link_name) -{ - int rc = gxio_mpipe_link_open(link, &context, link_name, 0); - if (rc < 0) { - netdev_err(dev, "Failed to open '%s'\n", link_name); - return rc; - } - rc = gxio_mpipe_link_channel(link); - if (rc < 0 || rc >= TILE_NET_CHANNELS) { - netdev_err(dev, "gxio_mpipe_link_channel bad value: %d\n", rc); - gxio_mpipe_link_close(link); - return -EINVAL; - } - return rc; -} - -/* Help the kernel activate the given network interface. */ -static int tile_net_open(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int cpu, rc; - - mutex_lock(&tile_net_devs_for_channel_mutex); - - /* Do one-time initialization the first time any device is opened. */ - if (ingress_irq < 0) { - rc = tile_net_init_mpipe(dev); - if (rc != 0) - goto fail; - } - - /* Determine if this is the "loopify" device. */ - if (unlikely((loopify_link_name != NULL) && - !strcmp(dev->name, loopify_link_name))) { - rc = tile_net_link_open(dev, &priv->link, "loop0"); - if (rc < 0) - goto fail; - priv->channel = rc; - rc = tile_net_link_open(dev, &priv->loopify_link, "loop1"); - if (rc < 0) - goto fail; - priv->loopify_channel = rc; - priv->echannel = rc; - } else { - rc = tile_net_link_open(dev, &priv->link, dev->name); - if (rc < 0) - goto fail; - priv->channel = rc; - priv->echannel = rc; - } - - /* Initialize egress info (if needed). Once ever, per echannel. */ - rc = tile_net_init_egress(dev, priv->echannel); - if (rc != 0) - goto fail; - - tile_net_devs_for_channel[priv->channel] = dev; - - rc = tile_net_update(dev); - if (rc != 0) - goto fail; - - mutex_unlock(&tile_net_devs_for_channel_mutex); - - /* Initialize the transmit wake timer for this device for each cpu. */ - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - struct tile_net_tx_wake *tx_wake = - &info->tx_wake[priv->echannel]; - - hrtimer_init(&tx_wake->timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - tx_wake->timer.function = tile_net_handle_tx_wake_timer; - tx_wake->dev = dev; - } - - for_each_online_cpu(cpu) - netif_start_subqueue(dev, cpu); - netif_carrier_on(dev); - return 0; - -fail: - if (priv->loopify_channel >= 0) { - if (gxio_mpipe_link_close(&priv->loopify_link) != 0) - netdev_warn(dev, "Failed to close loopify link!\n"); - priv->loopify_channel = -1; - } - if (priv->channel >= 0) { - if (gxio_mpipe_link_close(&priv->link) != 0) - netdev_warn(dev, "Failed to close link!\n"); - priv->channel = -1; - } - priv->echannel = -1; - tile_net_devs_for_channel[priv->channel] = NULL; - mutex_unlock(&tile_net_devs_for_channel_mutex); - - /* Don't return raw gxio error codes to generic Linux. */ - return (rc > -512) ? rc : -EIO; -} - -/* Help the kernel deactivate the given network interface. */ -static int tile_net_stop(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int cpu; - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - struct tile_net_tx_wake *tx_wake = - &info->tx_wake[priv->echannel]; - - hrtimer_cancel(&tx_wake->timer); - netif_stop_subqueue(dev, cpu); - } - - mutex_lock(&tile_net_devs_for_channel_mutex); - tile_net_devs_for_channel[priv->channel] = NULL; - (void)tile_net_update(dev); - if (priv->loopify_channel >= 0) { - if (gxio_mpipe_link_close(&priv->loopify_link) != 0) - netdev_warn(dev, "Failed to close loopify link!\n"); - priv->loopify_channel = -1; - } - if (priv->channel >= 0) { - if (gxio_mpipe_link_close(&priv->link) != 0) - netdev_warn(dev, "Failed to close link!\n"); - priv->channel = -1; - } - priv->echannel = -1; - mutex_unlock(&tile_net_devs_for_channel_mutex); - - return 0; -} - -/* Determine the VA for a fragment. */ -static inline void *tile_net_frag_buf(skb_frag_t *f) -{ - unsigned long pfn = page_to_pfn(skb_frag_page(f)); - return pfn_to_kaddr(pfn) + f->page_offset; -} - -/* Acquire a completion entry and an egress slot, or if we can't, - * stop the queue and schedule the tx_wake timer. - */ -static s64 tile_net_equeue_try_reserve(struct net_device *dev, - struct tile_net_comps *comps, - gxio_mpipe_equeue_t *equeue, - int num_edescs) -{ - /* Try to acquire a completion entry. */ - if (comps->comp_next - comps->comp_last < TILE_NET_MAX_COMPS - 1 || - tile_net_free_comps(equeue, comps, 32, false) != 0) { - - /* Try to acquire an egress slot. */ - s64 slot = gxio_mpipe_equeue_try_reserve(equeue, num_edescs); - if (slot >= 0) - return slot; - - /* Freeing some completions gives the equeue time to drain. */ - tile_net_free_comps(equeue, comps, TILE_NET_MAX_COMPS, false); - - slot = gxio_mpipe_equeue_try_reserve(equeue, num_edescs); - if (slot >= 0) - return slot; - } - - /* Still nothing; give up and stop the queue for a short while. */ - netif_stop_subqueue(dev, smp_processor_id()); - tile_net_schedule_tx_wake_timer(dev); - return -1; -} - -/* Determine how many edesc's are needed for TSO. - * - * Sometimes, if "sendfile()" requires copying, we will be called with - * "data" containing the header and payload, with "frags" being empty. - * Sometimes, for example when using NFS over TCP, a single segment can - * span 3 fragments. This requires special care. - */ -static int tso_count_edescs(struct sk_buff *skb) -{ - struct skb_shared_info *sh = skb_shinfo(skb); - unsigned int data_len = skb->data_len; - unsigned int p_len = sh->gso_size; - long f_id = -1; /* id of the current fragment */ - long f_size = -1; /* size of the current fragment */ - long f_used = -1; /* bytes used from the current fragment */ - long n; /* size of the current piece of payload */ - int num_edescs = 0; - int segment; - - for (segment = 0; segment < sh->gso_segs; segment++) { - - unsigned int p_used = 0; - - /* One edesc for header and for each piece of the payload. */ - for (num_edescs++; p_used < p_len; num_edescs++) { - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; - } - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - } - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - return num_edescs; -} - -/* Prepare modified copies of the skbuff headers. - * FIXME: add support for IPv6. - */ -static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, - s64 slot) -{ - struct skb_shared_info *sh = skb_shinfo(skb); - struct iphdr *ih; - struct tcphdr *th; - unsigned int data_len = skb->data_len; - unsigned char *data = skb->data; - unsigned int ih_off, th_off, sh_len, p_len; - unsigned int isum_seed, tsum_seed, id, seq; - long f_id = -1; /* id of the current fragment */ - long f_size = -1; /* size of the current fragment */ - long f_used = -1; /* bytes used from the current fragment */ - long n; /* size of the current piece of payload */ - int segment; - - /* Locate original headers and compute various lengths. */ - ih = ip_hdr(skb); - th = tcp_hdr(skb); - ih_off = skb_network_offset(skb); - th_off = skb_transport_offset(skb); - sh_len = th_off + tcp_hdrlen(skb); - p_len = sh->gso_size; - - /* Set up seed values for IP and TCP csum and initialize id and seq. */ - isum_seed = ((0xFFFF - ih->check) + - (0xFFFF - ih->tot_len) + - (0xFFFF - ih->id)); - tsum_seed = th->check + (0xFFFF ^ htons(skb->len)); - id = ntohs(ih->id); - seq = ntohl(th->seq); - - /* Prepare all the headers. */ - for (segment = 0; segment < sh->gso_segs; segment++) { - unsigned char *buf; - unsigned int p_used = 0; - - /* Copy to the header memory for this segment. */ - buf = headers + (slot % EQUEUE_ENTRIES) * HEADER_BYTES + - NET_IP_ALIGN; - memcpy(buf, data, sh_len); - - /* Update copied ip header. */ - ih = (struct iphdr *)(buf + ih_off); - ih->tot_len = htons(sh_len + p_len - ih_off); - ih->id = htons(id); - ih->check = csum_long(isum_seed + ih->tot_len + - ih->id) ^ 0xffff; - - /* Update copied tcp header. */ - th = (struct tcphdr *)(buf + th_off); - th->seq = htonl(seq); - th->check = csum_long(tsum_seed + htons(sh_len + p_len)); - if (segment != sh->gso_segs - 1) { - th->fin = 0; - th->psh = 0; - } - - /* Skip past the header. */ - slot++; - - /* Skip past the payload. */ - while (p_used < p_len) { - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; - } - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - - slot++; - } - - id++; - seq += p_len; - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - /* Flush the headers so they are ready for hardware DMA. */ - wmb(); -} - -/* Pass all the data to mpipe for egress. */ -static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, - struct sk_buff *skb, unsigned char *headers, s64 slot) -{ - struct tile_net_priv *priv = netdev_priv(dev); - struct skb_shared_info *sh = skb_shinfo(skb); - unsigned int data_len = skb->data_len; - unsigned int p_len = sh->gso_size; - gxio_mpipe_edesc_t edesc_head = { { 0 } }; - gxio_mpipe_edesc_t edesc_body = { { 0 } }; - long f_id = -1; /* id of the current fragment */ - long f_size = -1; /* size of the current fragment */ - long f_used = -1; /* bytes used from the current fragment */ - long n; /* size of the current piece of payload */ - unsigned long tx_packets = 0, tx_bytes = 0; - unsigned int csum_start, sh_len; - int segment; - - /* Prepare to egress the headers: set up header edesc. */ - csum_start = skb_checksum_start_offset(skb); - sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - edesc_head.csum = 1; - edesc_head.csum_start = csum_start; - edesc_head.csum_dest = csum_start + skb->csum_offset; - edesc_head.xfer_size = sh_len; - - /* This is only used to specify the TLB. */ - edesc_head.stack_idx = large_buffer_stack; - edesc_body.stack_idx = large_buffer_stack; - - /* Egress all the edescs. */ - for (segment = 0; segment < sh->gso_segs; segment++) { - void *va; - unsigned char *buf; - unsigned int p_used = 0; - - /* Egress the header. */ - buf = headers + (slot % EQUEUE_ENTRIES) * HEADER_BYTES + - NET_IP_ALIGN; - edesc_head.va = va_to_tile_io_addr(buf); - gxio_mpipe_equeue_put_at(equeue, edesc_head, slot); - slot++; - - /* Egress the payload. */ - while (p_used < p_len) { - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; - } - - va = tile_net_frag_buf(&sh->frags[f_id]) + f_used; - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - - /* Egress a piece of the payload. */ - edesc_body.va = va_to_tile_io_addr(va); - edesc_body.xfer_size = n; - edesc_body.bound = !(p_used < p_len); - gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); - slot++; - } - - tx_packets++; - tx_bytes += sh_len + p_len; - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - /* Update stats. */ - tile_net_stats_add(tx_packets, &priv->stats.tx_packets); - tile_net_stats_add(tx_bytes, &priv->stats.tx_bytes); -} - -/* Do "TSO" handling for egress. - * - * Normally drivers set NETIF_F_TSO only to support hardware TSO; - * otherwise the stack uses scatter-gather to implement GSO in software. - * On our testing, enabling GSO support (via NETIF_F_SG) drops network - * performance down to around 7.5 Gbps on the 10G interfaces, although - * also dropping cpu utilization way down, to under 8%. But - * implementing "TSO" in the driver brings performance back up to line - * rate, while dropping cpu usage even further, to less than 4%. In - * practice, profiling of GSO shows that skb_segment() is what causes - * the performance overheads; we benefit in the driver from using - * preallocated memory to duplicate the TCP/IP headers. - */ -static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - int channel = priv->echannel; - struct tile_net_egress *egress = &egress_for_echannel[channel]; - struct tile_net_comps *comps = info->comps_for_echannel[channel]; - gxio_mpipe_equeue_t *equeue = egress->equeue; - unsigned long irqflags; - int num_edescs; - s64 slot; - - /* Determine how many mpipe edesc's are needed. */ - num_edescs = tso_count_edescs(skb); - - local_irq_save(irqflags); - - /* Try to acquire a completion entry and an egress slot. */ - slot = tile_net_equeue_try_reserve(dev, comps, equeue, num_edescs); - if (slot < 0) { - local_irq_restore(irqflags); - return NETDEV_TX_BUSY; - } - - /* Set up copies of header data properly. */ - tso_headers_prepare(skb, egress->headers, slot); - - /* Actually pass the data to the network hardware. */ - tso_egress(dev, equeue, skb, egress->headers, slot); - - /* Add a completion record. */ - add_comp(equeue, comps, slot + num_edescs - 1, skb); - - local_irq_restore(irqflags); - - /* Make sure the egress timer is scheduled. */ - tile_net_schedule_egress_timer(); - - return NETDEV_TX_OK; -} - -/* Analyze the body and frags for a transmit request. */ -static unsigned int tile_net_tx_frags(struct frag *frags, - struct sk_buff *skb, - void *b_data, unsigned int b_len) -{ - unsigned int i, n = 0; - - struct skb_shared_info *sh = skb_shinfo(skb); - - if (b_len != 0) { - frags[n].buf = b_data; - frags[n++].length = b_len; - } - - for (i = 0; i < sh->nr_frags; i++) { - skb_frag_t *f = &sh->frags[i]; - frags[n].buf = tile_net_frag_buf(f); - frags[n++].length = skb_frag_size(f); - } - - return n; -} - -/* Help the kernel transmit a packet. */ -static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - struct tile_net_egress *egress = &egress_for_echannel[priv->echannel]; - gxio_mpipe_equeue_t *equeue = egress->equeue; - struct tile_net_comps *comps = - info->comps_for_echannel[priv->echannel]; - unsigned int len = skb->len; - unsigned char *data = skb->data; - unsigned int num_edescs; - struct frag frags[MAX_FRAGS]; - gxio_mpipe_edesc_t edescs[MAX_FRAGS]; - unsigned long irqflags; - gxio_mpipe_edesc_t edesc = { { 0 } }; - unsigned int i; - s64 slot; - - if (skb_is_gso(skb)) - return tile_net_tx_tso(skb, dev); - - num_edescs = tile_net_tx_frags(frags, skb, data, skb_headlen(skb)); - - /* This is only used to specify the TLB. */ - edesc.stack_idx = large_buffer_stack; - - /* Prepare the edescs. */ - for (i = 0; i < num_edescs; i++) { - edesc.xfer_size = frags[i].length; - edesc.va = va_to_tile_io_addr(frags[i].buf); - edescs[i] = edesc; - } - - /* Mark the final edesc. */ - edescs[num_edescs - 1].bound = 1; - - /* Add checksum info to the initial edesc, if needed. */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { - unsigned int csum_start = skb_checksum_start_offset(skb); - edescs[0].csum = 1; - edescs[0].csum_start = csum_start; - edescs[0].csum_dest = csum_start + skb->csum_offset; - } - - local_irq_save(irqflags); - - /* Try to acquire a completion entry and an egress slot. */ - slot = tile_net_equeue_try_reserve(dev, comps, equeue, num_edescs); - if (slot < 0) { - local_irq_restore(irqflags); - return NETDEV_TX_BUSY; - } - - for (i = 0; i < num_edescs; i++) - gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++); - - /* Add a completion record. */ - add_comp(equeue, comps, slot - 1, skb); - - /* NOTE: Use ETH_ZLEN for short packets (e.g. 42 < 60). */ - tile_net_stats_add(1, &priv->stats.tx_packets); - tile_net_stats_add(max_t(unsigned int, len, ETH_ZLEN), - &priv->stats.tx_bytes); - - local_irq_restore(irqflags); - - /* Make sure the egress timer is scheduled. */ - tile_net_schedule_egress_timer(); - - return NETDEV_TX_OK; -} - -/* Return subqueue id on this core (one per core). */ -static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb) -{ - return smp_processor_id(); -} - -/* Deal with a transmit timeout. */ -static void tile_net_tx_timeout(struct net_device *dev) -{ - int cpu; - - for_each_online_cpu(cpu) - netif_wake_subqueue(dev, cpu); -} - -/* Ioctl commands. */ -static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - return -EOPNOTSUPP; -} - -/* Get system network statistics for device. */ -static struct net_device_stats *tile_net_get_stats(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - return &priv->stats; -} - -/* Change the MTU. */ -static int tile_net_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 1500)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -/* Change the Ethernet address of the NIC. - * - * The hypervisor driver does not support changing MAC address. However, - * the hardware does not do anything with the MAC address, so the address - * which gets used on outgoing packets, and which is accepted on incoming - * packets, is completely up to us. - * - * Returns 0 on success, negative on failure. - */ -static int tile_net_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void tile_net_netpoll(struct net_device *dev) -{ - disable_percpu_irq(ingress_irq); - tile_net_handle_ingress_irq(ingress_irq, NULL); - enable_percpu_irq(ingress_irq, 0); -} -#endif - -static const struct net_device_ops tile_net_ops = { - .ndo_open = tile_net_open, - .ndo_stop = tile_net_stop, - .ndo_start_xmit = tile_net_tx, - .ndo_select_queue = tile_net_select_queue, - .ndo_do_ioctl = tile_net_ioctl, - .ndo_get_stats = tile_net_get_stats, - .ndo_change_mtu = tile_net_change_mtu, - .ndo_tx_timeout = tile_net_tx_timeout, - .ndo_set_mac_address = tile_net_set_mac_address, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = tile_net_netpoll, -#endif -}; - -/* The setup function. - * - * This uses ether_setup() to assign various fields in dev, including - * setting IFF_BROADCAST and IFF_MULTICAST, then sets some extra fields. - */ -static void tile_net_setup(struct net_device *dev) -{ - ether_setup(dev); - dev->netdev_ops = &tile_net_ops; - dev->watchdog_timeo = TILE_NET_TIMEOUT; - dev->features |= NETIF_F_LLTX; - dev->features |= NETIF_F_HW_CSUM; - dev->features |= NETIF_F_SG; - dev->features |= NETIF_F_TSO; - dev->mtu = 1500; -} - -/* Allocate the device structure, register the device, and obtain the - * MAC address from the hypervisor. - */ -static void tile_net_dev_init(const char *name, const uint8_t *mac) -{ - int ret; - int i; - int nz_addr = 0; - struct net_device *dev; - struct tile_net_priv *priv; - - /* HACK: Ignore "loop" links. */ - if (strncmp(name, "loop", 4) == 0) - return; - - /* Allocate the device structure. Normally, "name" is a - * template, instantiated by register_netdev(), but not for us. - */ - dev = alloc_netdev_mqs(sizeof(*priv), name, tile_net_setup, - NR_CPUS, 1); - if (!dev) { - pr_err("alloc_netdev_mqs(%s) failed\n", name); - return; - } - - /* Initialize "priv". */ - priv = netdev_priv(dev); - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - priv->channel = -1; - priv->loopify_channel = -1; - priv->echannel = -1; - - /* Get the MAC address and set it in the device struct; this must - * be done before the device is opened. If the MAC is all zeroes, - * we use a random address, since we're probably on the simulator. - */ - for (i = 0; i < 6; i++) - nz_addr |= mac[i]; - - if (nz_addr) { - memcpy(dev->dev_addr, mac, 6); - dev->addr_len = 6; - } else { - random_ether_addr(dev->dev_addr); - } - - /* Register the network device. */ - ret = register_netdev(dev); - if (ret) { - netdev_err(dev, "register_netdev failed %d\n", ret); - free_netdev(dev); - return; - } -} - -/* Per-cpu module initialization. */ -static void tile_net_init_module_percpu(void *unused) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - int my_cpu = smp_processor_id(); - - info->has_iqueue = false; - - info->my_cpu = my_cpu; - - /* Initialize the egress timer. */ - hrtimer_init(&info->egress_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - info->egress_timer.function = tile_net_handle_egress_timer; -} - -/* Module initialization. */ -static int __init tile_net_init_module(void) -{ - int i; - char name[GXIO_MPIPE_LINK_NAME_LEN]; - uint8_t mac[6]; - - pr_info("Tilera Network Driver\n"); - - mutex_init(&tile_net_devs_for_channel_mutex); - - /* Initialize each CPU. */ - on_each_cpu(tile_net_init_module_percpu, NULL, 1); - - /* Find out what devices we have, and initialize them. */ - for (i = 0; gxio_mpipe_link_enumerate_mac(i, name, mac) >= 0; i++) - tile_net_dev_init(name, mac); - - if (!network_cpus_init()) - network_cpus_map = *cpu_online_mask; - - return 0; -} - -module_init(tile_net_init_module); diff --git a/trunk/drivers/net/hyperv/hyperv_net.h b/trunk/drivers/net/hyperv/hyperv_net.h index 2857ab078aac..4ffcd57b011b 100644 --- a/trunk/drivers/net/hyperv/hyperv_net.h +++ b/trunk/drivers/net/hyperv/hyperv_net.h @@ -478,7 +478,6 @@ struct netvsc_device { u32 nvsp_version; atomic_t num_outstanding_sends; - wait_queue_head_t wait_drain; bool start_remove; bool destroy; /* diff --git a/trunk/drivers/net/hyperv/netvsc.c b/trunk/drivers/net/hyperv/netvsc.c index 0c569831db5a..8b919471472f 100644 --- a/trunk/drivers/net/hyperv/netvsc.c +++ b/trunk/drivers/net/hyperv/netvsc.c @@ -42,7 +42,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) if (!net_device) return NULL; - init_waitqueue_head(&net_device->wait_drain); net_device->start_remove = false; net_device->destroy = false; net_device->dev = device; @@ -388,8 +387,12 @@ int netvsc_device_remove(struct hv_device *device) spin_unlock_irqrestore(&device->channel->inbound_lock, flags); /* Wait for all send completions */ - wait_event(net_device->wait_drain, - atomic_read(&net_device->num_outstanding_sends) == 0); + while (atomic_read(&net_device->num_outstanding_sends)) { + dev_info(&device->device, + "waiting for %d requests to complete...\n", + atomic_read(&net_device->num_outstanding_sends)); + udelay(100); + } netvsc_disconnect_vsp(net_device); @@ -483,9 +486,6 @@ static void netvsc_send_completion(struct hv_device *device, num_outstanding_sends = atomic_dec_return(&net_device->num_outstanding_sends); - if (net_device->destroy && num_outstanding_sends == 0) - wake_up(&net_device->wait_drain); - if (netif_queue_stopped(ndev) && !net_device->start_remove && (hv_ringbuf_avail_percent(&device->channel->outbound) > RING_AVAIL_PERCENT_HIWATER || diff --git a/trunk/drivers/net/phy/icplus.c b/trunk/drivers/net/phy/icplus.c index 47f8e8939266..5ac46f5226f3 100644 --- a/trunk/drivers/net/phy/icplus.c +++ b/trunk/drivers/net/phy/icplus.c @@ -41,8 +41,6 @@ MODULE_LICENSE("GPL"); #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ -#define IP101A_G_IRQ_PIN_USED (1<<15) /* INTR pin used */ -#define IP101A_G_IRQ_DEFAULT IP101A_G_IRQ_PIN_USED static int ip175c_config_init(struct phy_device *phydev) { @@ -138,11 +136,6 @@ static int ip1001_config_init(struct phy_device *phydev) if (c < 0) return c; - /* INTR pin used: speed/link/duplex will cause an interrupt */ - c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); - if (c < 0) - return c; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { /* Additional delay (2ns) used to adjust RX clock phase * at RGMII interface */ diff --git a/trunk/drivers/net/phy/mdio_bus.c b/trunk/drivers/net/phy/mdio_bus.c index 5061608f408c..683ef1ce5519 100644 --- a/trunk/drivers/net/phy/mdio_bus.c +++ b/trunk/drivers/net/phy/mdio_bus.c @@ -96,7 +96,7 @@ static int of_mdio_bus_match(struct device *dev, void *mdio_bus_np) } /** * of_mdio_find_bus - Given an mii_bus node, find the mii_bus. - * @mdio_bus_np: Pointer to the mii_bus. + * @mdio_np: Pointer to the mii_bus. * * Returns a pointer to the mii_bus, or NULL if none found. * diff --git a/trunk/drivers/net/usb/mcs7830.c b/trunk/drivers/net/usb/mcs7830.c index 03c2d8d653df..add1064f755d 100644 --- a/trunk/drivers/net/usb/mcs7830.c +++ b/trunk/drivers/net/usb/mcs7830.c @@ -629,31 +629,11 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) return skb->len > 0; } -static void mcs7830_status(struct usbnet *dev, struct urb *urb) -{ - u8 *buf = urb->transfer_buffer; - bool link; - - if (urb->actual_length < 16) - return; - - link = !(buf[1] & 0x20); - if (netif_carrier_ok(dev->net) != link) { - if (link) { - netif_carrier_on(dev->net); - usbnet_defer_kevent(dev, EVENT_LINK_RESET); - } else - netif_carrier_off(dev->net); - netdev_dbg(dev->net, "Link Status is: %d\n", link); - } -} - static const struct driver_info moschip_info = { .description = "MOSCHIP 7830/7832/7730 usb-NET adapter", .bind = mcs7830_bind, .rx_fixup = mcs7830_rx_fixup, - .flags = FLAG_ETHER | FLAG_LINK_INTR, - .status = mcs7830_status, + .flags = FLAG_ETHER, .in = 1, .out = 2, }; @@ -662,8 +642,7 @@ static const struct driver_info sitecom_info = { .description = "Sitecom LN-30 usb-NET adapter", .bind = mcs7830_bind, .rx_fixup = mcs7830_rx_fixup, - .flags = FLAG_ETHER | FLAG_LINK_INTR, - .status = mcs7830_status, + .flags = FLAG_ETHER, .in = 1, .out = 2, }; diff --git a/trunk/drivers/net/usb/sierra_net.c b/trunk/drivers/net/usb/sierra_net.c index d75d1f56becf..3faef5670d1f 100644 --- a/trunk/drivers/net/usb/sierra_net.c +++ b/trunk/drivers/net/usb/sierra_net.c @@ -946,7 +946,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, } static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; -static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { +static const struct sierra_net_info_data sierra_net_info_data_68A3 = { .rx_urb_size = 8 * 1024, .whitelist = { .infolen = ARRAY_SIZE(sierra_net_ifnum_list), @@ -954,7 +954,7 @@ static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { } }; -static const struct driver_info sierra_net_info_direct_ip = { +static const struct driver_info sierra_net_info_68A3 = { .description = "Sierra Wireless USB-to-WWAN Modem", .flags = FLAG_WWAN | FLAG_SEND_ZLP, .bind = sierra_net_bind, @@ -962,18 +962,12 @@ static const struct driver_info sierra_net_info_direct_ip = { .status = sierra_net_status, .rx_fixup = sierra_net_rx_fixup, .tx_fixup = sierra_net_tx_fixup, - .data = (unsigned long)&sierra_net_info_data_direct_ip, + .data = (unsigned long)&sierra_net_info_data_68A3, }; static const struct usb_device_id products[] = { {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, - {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ - .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + .driver_info = (unsigned long) &sierra_net_info_68A3}, {}, /* last item */ }; diff --git a/trunk/drivers/net/virtio_net.c b/trunk/drivers/net/virtio_net.c index f18149ae2588..5214b1eceb95 100644 --- a/trunk/drivers/net/virtio_net.c +++ b/trunk/drivers/net/virtio_net.c @@ -42,8 +42,7 @@ module_param(gso, bool, 0444); #define VIRTNET_DRIVER_VERSION "1.0.0" struct virtnet_stats { - struct u64_stats_sync tx_syncp; - struct u64_stats_sync rx_syncp; + struct u64_stats_sync syncp; u64 tx_bytes; u64 tx_packets; @@ -301,10 +300,10 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len) hdr = skb_vnet_hdr(skb); - u64_stats_update_begin(&stats->rx_syncp); + u64_stats_update_begin(&stats->syncp); stats->rx_bytes += skb->len; stats->rx_packets++; - u64_stats_update_end(&stats->rx_syncp); + u64_stats_update_end(&stats->syncp); if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { pr_debug("Needs csum!\n"); @@ -566,10 +565,10 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) { pr_debug("Sent skb %p\n", skb); - u64_stats_update_begin(&stats->tx_syncp); + u64_stats_update_begin(&stats->syncp); stats->tx_bytes += skb->len; stats->tx_packets++; - u64_stats_update_end(&stats->tx_syncp); + u64_stats_update_end(&stats->syncp); tot_sgs += skb_vnet_hdr(skb)->num_sg; dev_kfree_skb_any(skb); @@ -704,16 +703,12 @@ static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev, u64 tpackets, tbytes, rpackets, rbytes; do { - start = u64_stats_fetch_begin(&stats->tx_syncp); + start = u64_stats_fetch_begin(&stats->syncp); tpackets = stats->tx_packets; tbytes = stats->tx_bytes; - } while (u64_stats_fetch_retry(&stats->tx_syncp, start)); - - do { - start = u64_stats_fetch_begin(&stats->rx_syncp); rpackets = stats->rx_packets; rbytes = stats->rx_bytes; - } while (u64_stats_fetch_retry(&stats->rx_syncp, start)); + } while (u64_stats_fetch_retry(&stats->syncp, start)); tot->rx_packets += rpackets; tot->tx_packets += tpackets; diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index c06b6cb5c91e..67c13af6f206 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -877,10 +877,6 @@ struct b43_wl { * from the mac80211 subsystem. */ u16 mac80211_initially_registered_queues; - /* Set this if we call ieee80211_register_hw() and check if we call - * ieee80211_unregister_hw(). */ - bool hw_registred; - /* We can only have one operating interface (802.11 core) * at a time. General information about this interface follows. */ diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index acd03a4f9730..5a39b226b2e3 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -2437,7 +2437,6 @@ static void b43_request_firmware(struct work_struct *work) err = ieee80211_register_hw(wl->hw); if (err) goto err_one_core_detach; - wl->hw_registred = true; b43_leds_register(wl->current_dev); goto out; @@ -5300,7 +5299,6 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1; wl->mac80211_initially_registered_queues = hw->queues; - wl->hw_registred = false; hw->max_rates = 2; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) @@ -5372,15 +5370,12 @@ static void b43_bcma_remove(struct bcma_device *core) * as the ieee80211 unreg will destroy the workqueue. */ cancel_work_sync(&wldev->restart_work); - B43_WARN_ON(!wl); - if (wl->current_dev == wldev && wl->hw_registred) { - /* Restore the queues count before unregistering, because firmware detect - * might have modified it. Restoring is important, so the networking - * stack can properly free resources. */ - wl->hw->queues = wl->mac80211_initially_registered_queues; - b43_leds_stop(wldev); - ieee80211_unregister_hw(wl->hw); - } + /* Restore the queues count before unregistering, because firmware detect + * might have modified it. Restoring is important, so the networking + * stack can properly free resources. */ + wl->hw->queues = wl->mac80211_initially_registered_queues; + b43_leds_stop(wldev); + ieee80211_unregister_hw(wl->hw); b43_one_core_detach(wldev->dev); @@ -5451,7 +5446,7 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); - if (wl->current_dev == wldev && wl->hw_registred) { + if (wl->current_dev == wldev) { /* Restore the queues count before unregistering, because firmware detect * might have modified it. Restoring is important, so the networking * stack can properly free resources. */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 8e7e6928c936..e2480d196276 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -89,9 +89,9 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); - /* redirect, configure and enable io for interrupt signal */ + /* redirect, configure ane enable io for interrupt signal */ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; - if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH) + if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) data |= SDIO_SEPINT_ACT_HI; brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); diff --git a/trunk/drivers/net/wireless/ipw2x00/ipw2100.c b/trunk/drivers/net/wireless/ipw2x00/ipw2100.c index 95aa8e1683ec..9cfae0c08707 100644 --- a/trunk/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2x00/ipw2100.c @@ -1903,6 +1903,14 @@ static void ipw2100_down(struct ipw2100_priv *priv) netif_stop_queue(priv->net_dev); } +/* Called by register_netdev() */ +static int ipw2100_net_init(struct net_device *dev) +{ + struct ipw2100_priv *priv = libipw_priv(dev); + + return ipw2100_up(priv, 1); +} + static int ipw2100_wdev_init(struct net_device *dev) { struct ipw2100_priv *priv = libipw_priv(dev); @@ -6079,6 +6087,7 @@ static const struct net_device_ops ipw2100_netdev_ops = { .ndo_stop = ipw2100_close, .ndo_start_xmit = libipw_xmit, .ndo_change_mtu = libipw_change_mtu, + .ndo_init = ipw2100_net_init, .ndo_tx_timeout = ipw2100_tx_timeout, .ndo_set_mac_address = ipw2100_set_address, .ndo_validate_addr = eth_validate_addr, @@ -6320,10 +6329,6 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2100 Network Connection\n"); - err = ipw2100_up(priv, 1); - if (err) - goto fail; - err = ipw2100_wdev_init(dev); if (err) goto fail; @@ -6333,7 +6338,12 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, * network device we would call ipw2100_up. This introduced a race * condition with newer hotplug configurations (network was coming * up and making calls before the device was initialized). - */ + * + * If we called ipw2100_up before we registered the device, then the + * device name wasn't registered. So, we instead use the net_dev->init + * member to call a function that then just turns and calls ipw2100_up. + * net_dev->init is called after name allocation but before the + * notifier chain is called */ err = register_netdev(dev); if (err) { printk(KERN_WARNING DRV_NAME diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c index e5e8ada4aaf6..19f7ee84ae89 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -35,20 +35,17 @@ #define IWL6000_UCODE_API_MAX 6 #define IWL6050_UCODE_API_MAX 5 #define IWL6000G2_UCODE_API_MAX 6 -#define IWL6035_UCODE_API_MAX 6 /* Oldest version we won't warn about */ #define IWL6000_UCODE_API_OK 4 #define IWL6000G2_UCODE_API_OK 5 #define IWL6050_UCODE_API_OK 5 #define IWL6000G2B_UCODE_API_OK 6 -#define IWL6035_UCODE_API_OK 6 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 #define IWL6050_UCODE_API_MIN 4 -#define IWL6000G2_UCODE_API_MIN 5 -#define IWL6035_UCODE_API_MIN 6 +#define IWL6000G2_UCODE_API_MIN 4 /* EEPROM versions */ #define EEPROM_6000_TX_POWER_VERSION (4) @@ -230,25 +227,9 @@ const struct iwl_cfg iwl6030_2bg_cfg = { IWL_DEVICE_6030, }; -#define IWL_DEVICE_6035 \ - .fw_name_pre = IWL6030_FW_PRE, \ - .ucode_api_max = IWL6035_UCODE_API_MAX, \ - .ucode_api_ok = IWL6035_UCODE_API_OK, \ - .ucode_api_min = IWL6035_UCODE_API_MIN, \ - .device_family = IWL_DEVICE_FAMILY_6030, \ - .max_inst_size = IWL60_RTC_INST_SIZE, \ - .max_data_size = IWL60_RTC_DATA_SIZE, \ - .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ - .base_params = &iwl6000_g2_base_params, \ - .bt_params = &iwl6000_bt_params, \ - .need_temp_offset_calib = true, \ - .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true - const struct iwl_cfg iwl6035_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", - IWL_DEVICE_6035, + IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, }; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index eb6a8eaf42fc..aea07aab3c9e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1267,7 +1267,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, key_flags |= STA_KEY_MULTICAST_MSK; sta_cmd.key.key_flags = key_flags; - sta_cmd.key.key_offset = keyconf->hw_key_idx; + sta_cmd.key.key_offset = WEP_INVALID_OFFSET; sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; sta_cmd.mode = STA_CONTROL_MODIFY_MSK; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c index fac67a526a30..d742900969ea 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -861,18 +861,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); + complete(&drv->request_firmware_complete); drv->op_mode = iwl_dvm_ops.start(drv->trans, drv->cfg, &drv->fw); if (!drv->op_mode) - goto out_unbind; + goto out_free_fw; - /* - * Complete the firmware request last so that - * a driver unbind (stop) doesn't run while we - * are doing the start() above. - */ - complete(&drv->request_firmware_complete); return; try_again: diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c index b8e2b223ac36..50c58911e718 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -568,28 +568,28 @@ static int iwl_find_otp_image(struct iwl_trans *trans, * iwl_get_max_txpower_avg - get the highest tx power from all chains. * find the highest tx power from all chains for the channel */ -static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, +static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg, struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element, s8 *max_txpower_in_half_dbm) { s8 max_txpower_avg = 0; /* (dBm) */ /* Take the highest tx power from any valid chains */ - if ((priv->hw_params.valid_tx_ant & ANT_A) && + if ((cfg->valid_tx_ant & ANT_A) && (enhanced_txpower[element].chain_a_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_a_max; - if ((priv->hw_params.valid_tx_ant & ANT_B) && + if ((cfg->valid_tx_ant & ANT_B) && (enhanced_txpower[element].chain_b_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_b_max; - if ((priv->hw_params.valid_tx_ant & ANT_C) && + if ((cfg->valid_tx_ant & ANT_C) && (enhanced_txpower[element].chain_c_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_c_max; - if (((priv->hw_params.valid_tx_ant == ANT_AB) | - (priv->hw_params.valid_tx_ant == ANT_BC) | - (priv->hw_params.valid_tx_ant == ANT_AC)) && + if (((cfg->valid_tx_ant == ANT_AB) | + (cfg->valid_tx_ant == ANT_BC) | + (cfg->valid_tx_ant == ANT_AC)) && (enhanced_txpower[element].mimo2_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].mimo2_max; - if ((priv->hw_params.valid_tx_ant == ANT_ABC) && + if ((cfg->valid_tx_ant == ANT_ABC) && (enhanced_txpower[element].mimo3_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].mimo3_max; @@ -691,7 +691,7 @@ static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) ((txp->delta_20_in_40 & 0xf0) >> 4), (txp->delta_20_in_40 & 0x0f)); - max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, + max_txp_avg = iwl_get_max_txpower_avg(priv->cfg, txp_array, idx, &max_txp_avg_halfdbm); /* diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 3ee23134c02b..ab2f4d7500a4 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -199,7 +199,6 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_DISABLE_BEACON_HINTS | WIPHY_FLAG_IBSS_RSN; -#ifdef CONFIG_PM_SLEEP if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && priv->trans->ops->wowlan_suspend && device_can_wakeup(priv->trans->dev)) { @@ -218,7 +217,6 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, hw->wiphy->wowlan.pattern_max_len = IWLAGN_WOWLAN_MAX_PATTERN_LEN; } -#endif if (iwlwifi_mod_params.power_save) hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -251,7 +249,6 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, ret = ieee80211_register_hw(priv->hw); if (ret) { IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); - iwl_leds_exit(priv); return ret; } priv->mac80211_registered = 1; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h index dfd54662e3e6..3b1069290fa9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -224,7 +224,6 @@ #define SCD_TXFACT (SCD_BASE + 0x10) #define SCD_ACTIVE (SCD_BASE + 0x14) #define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) -#define SCD_CHAINEXT_EN (SCD_BASE + 0x244) #define SCD_AGGR_SEL (SCD_BASE + 0x248) #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 79c6b91417f9..ec6fb395b84d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1058,11 +1058,6 @@ static void iwl_tx_start(struct iwl_trans *trans) iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, trans_pcie->scd_bc_tbls.dma >> 10); - /* The chain extension of the SCD doesn't work well. This feature is - * enabled by default by the HW, so we need to disable it manually. - */ - iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); - /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index a0b7cfd34685..fb787df01666 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -1555,7 +1555,6 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, hdr = (struct ieee80211_hdr *) skb->data; mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2); } - txi->flags |= IEEE80211_TX_STAT_ACK; } ieee80211_tx_status_irqsafe(data2->hw, skb); return 0; @@ -1722,24 +1721,6 @@ static void hwsim_exit_netlink(void) "unregister family %i\n", ret); } -static const struct ieee80211_iface_limit hwsim_if_limits[] = { - { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, - { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_GO) }, -}; - -static const struct ieee80211_iface_combination hwsim_if_comb = { - .limits = hwsim_if_limits, - .n_limits = ARRAY_SIZE(hwsim_if_limits), - .max_interfaces = 2048, - .num_different_channels = 1, -}; - static int __init init_mac80211_hwsim(void) { int i, err = 0; @@ -1801,9 +1782,6 @@ static int __init init_mac80211_hwsim(void) hw->wiphy->n_addresses = 2; hw->wiphy->addresses = data->addresses; - hw->wiphy->iface_combinations = &hwsim_if_comb; - hw->wiphy->n_iface_combinations = 1; - if (fake_hw_scan) { hw->wiphy->max_scan_ssids = 255; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index 015fec3371a0..87671446e24b 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -948,19 +948,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, bss_cfg->ssid.ssid_len = params->ssid_len; } - switch (params->hidden_ssid) { - case NL80211_HIDDEN_SSID_NOT_IN_USE: - bss_cfg->bcast_ssid_ctl = 1; - break; - case NL80211_HIDDEN_SSID_ZERO_LEN: - bss_cfg->bcast_ssid_ctl = 0; - break; - case NL80211_HIDDEN_SSID_ZERO_CONTENTS: - /* firmware doesn't support this type of hidden SSID */ - default: - return -EINVAL; - } - if (mwifiex_set_secure_params(priv, bss_cfg, params)) { kfree(bss_cfg); wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); diff --git a/trunk/drivers/net/wireless/mwifiex/fw.h b/trunk/drivers/net/wireless/mwifiex/fw.h index 561452a5c818..9f674bbebe65 100644 --- a/trunk/drivers/net/wireless/mwifiex/fw.h +++ b/trunk/drivers/net/wireless/mwifiex/fw.h @@ -122,7 +122,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) #define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) -#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) @@ -1210,11 +1209,6 @@ struct host_cmd_tlv_ssid { u8 ssid[0]; } __packed; -struct host_cmd_tlv_bcast_ssid { - struct host_cmd_tlv tlv; - u8 bcast_ctl; -} __packed; - struct host_cmd_tlv_beacon_period { struct host_cmd_tlv tlv; __le16 period; diff --git a/trunk/drivers/net/wireless/mwifiex/uap_cmd.c b/trunk/drivers/net/wireless/mwifiex/uap_cmd.c index 8173ab66066d..76dfbc42a732 100644 --- a/trunk/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/trunk/drivers/net/wireless/mwifiex/uap_cmd.c @@ -132,7 +132,6 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) struct host_cmd_tlv_dtim_period *dtim_period; struct host_cmd_tlv_beacon_period *beacon_period; struct host_cmd_tlv_ssid *ssid; - struct host_cmd_tlv_bcast_ssid *bcast_ssid; struct host_cmd_tlv_channel_band *chan_band; struct host_cmd_tlv_frag_threshold *frag_threshold; struct host_cmd_tlv_rts_threshold *rts_threshold; @@ -154,14 +153,6 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) cmd_size += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; - - bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv; - bcast_ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID); - bcast_ssid->tlv.len = - cpu_to_le16(sizeof(bcast_ssid->bcast_ctl)); - bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl; - cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid); - tlv += sizeof(struct host_cmd_tlv_bcast_ssid); } if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { chan_band = (struct host_cmd_tlv_channel_band *)tlv; @@ -425,7 +416,6 @@ int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel) if (!bss_cfg) return -ENOMEM; - mwifiex_set_sys_config_invalid_data(bss_cfg); bss_cfg->band_cfg = BAND_CONFIG_MANUAL; bss_cfg->channel = channel; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h index 8f754025b06e..ca36cccaba31 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h @@ -396,7 +396,8 @@ struct rt2x00_intf { * for hardware which doesn't support hardware * sequence counting. */ - atomic_t seqno; + spinlock_t seqlock; + u16 seqno; }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c index dd24b2663b5e..b49773ef72f2 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -277,6 +277,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, else rt2x00dev->intf_sta_count++; + spin_lock_init(&intf->seqlock); mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c index 2fd830103415..4c662eccf53c 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -207,7 +207,6 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - u16 seqno; if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) return; @@ -239,13 +238,15 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ - if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) - seqno = atomic_add_return(0x10, &intf->seqno); - else - seqno = atomic_read(&intf->seqno); + spin_lock(&intf->seqlock); + if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) + intf->seqno += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(seqno); + hdr->seq_ctrl |= cpu_to_le16(intf->seqno); + + spin_unlock(&intf->seqlock); + } static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187/leds.c b/trunk/drivers/net/wireless/rtl818x/rtl8187/leds.c index c2d5b495c179..2e0de2f5f0f9 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187/leds.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187/leds.c @@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, radio_on = true; } else if (radio_on) { radio_on = false; - cancel_delayed_work(&priv->led_on); + cancel_delayed_work_sync(&priv->led_on); ieee80211_queue_delayed_work(hw, &priv->led_off, 0); } } else if (radio_on) { diff --git a/trunk/drivers/pci/pci.c b/trunk/drivers/pci/pci.c index 77cb54a65cde..447e83472c01 100644 --- a/trunk/drivers/pci/pci.c +++ b/trunk/drivers/pci/pci.c @@ -1744,11 +1744,6 @@ int pci_prepare_to_sleep(struct pci_dev *dev) if (target_state == PCI_POWER_ERROR) return -EIO; - /* Some devices mustn't be in D3 during system sleep */ - if (target_state == PCI_D3hot && - (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)) - return 0; - pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev)); error = pci_set_power_state(dev, target_state); diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 194b243a2817..2a7521677541 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -2929,32 +2929,6 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); -/* - * The Intel 6 Series/C200 Series chipset's EHCI controllers on many - * ASUS motherboards will cause memory corruption or a system crash - * if they are in D3 while the system is put into S3 sleep. - */ -static void __devinit asus_ehci_no_d3(struct pci_dev *dev) -{ - const char *sys_info; - static const char good_Asus_board[] = "P8Z68-V"; - - if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP) - return; - if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK) - return; - sys_info = dmi_get_system_info(DMI_BOARD_NAME); - if (sys_info && memcmp(sys_info, good_Asus_board, - sizeof(good_Asus_board) - 1) == 0) - return; - - dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n"); - dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP; - device_set_wakeup_capable(&dev->dev, false); -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3); - static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { diff --git a/trunk/drivers/pinctrl/core.c b/trunk/drivers/pinctrl/core.c index 0cc053af70bd..c3b331b74fa0 100644 --- a/trunk/drivers/pinctrl/core.c +++ b/trunk/drivers/pinctrl/core.c @@ -61,7 +61,7 @@ static LIST_HEAD(pinctrl_maps); list_for_each_entry(_maps_node_, &pinctrl_maps, node) \ for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \ _i_ < _maps_node_->num_maps; \ - _i_++, _map_ = &_maps_node_->maps[_i_]) + i++, _map_ = &_maps_node_->maps[_i_]) /** * pinctrl_provide_dummies() - indicate if pinctrl provides dummy state support diff --git a/trunk/drivers/pinctrl/pinctrl-imx.c b/trunk/drivers/pinctrl/pinctrl-imx.c index dd6d93aa5334..f6e7c670906c 100644 --- a/trunk/drivers/pinctrl/pinctrl-imx.c +++ b/trunk/drivers/pinctrl/pinctrl-imx.c @@ -27,16 +27,16 @@ #include "core.h" #include "pinctrl-imx.h" -#define IMX_PMX_DUMP(info, p, m, c, n) \ -{ \ - int i, j; \ - printk(KERN_DEBUG "Format: Pin Mux Config\n"); \ - for (i = 0; i < n; i++) { \ - j = p[i]; \ - printk(KERN_DEBUG "%s %d 0x%lx\n", \ - info->pins[j].name, \ - m[i], c[i]); \ - } \ +#define IMX_PMX_DUMP(info, p, m, c, n) \ +{ \ + int i, j; \ + printk("Format: Pin Mux Config\n"); \ + for (i = 0; i < n; i++) { \ + j = p[i]; \ + printk("%s %d 0x%lx\n", \ + info->pins[j].name, \ + m[i], c[i]); \ + } \ } /* The bits in CONFIG cell defined in binding doc*/ @@ -173,10 +173,8 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, /* create mux map */ parent = of_get_parent(np); - if (!parent) { - kfree(new_map); + if (!parent) return -EINVAL; - } new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; new_map[0].data.mux.function = parent->name; new_map[0].data.mux.group = np->name; @@ -195,7 +193,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, } dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", - (*map)->data.mux.function, (*map)->data.mux.group, map_num); + new_map->data.mux.function, new_map->data.mux.group, map_num); return 0; } @@ -203,7 +201,10 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, static void imx_dt_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps) { - kfree(map); + int i; + + for (i = 0; i < num_maps; i++) + kfree(map); } static struct pinctrl_ops imx_pctrl_ops = { @@ -474,8 +475,9 @@ static int __devinit imx_pinctrl_parse_groups(struct device_node *np, grp->configs[j] = config & ~IMX_PAD_SION; } +#ifdef DEBUG IMX_PMX_DUMP(info, grp->pins, grp->mux_mode, grp->configs, grp->npins); - +#endif return 0; } diff --git a/trunk/drivers/pinctrl/pinctrl-mxs.c b/trunk/drivers/pinctrl/pinctrl-mxs.c index afb50ee64598..556e45a213eb 100644 --- a/trunk/drivers/pinctrl/pinctrl-mxs.c +++ b/trunk/drivers/pinctrl/pinctrl-mxs.c @@ -107,10 +107,8 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, /* Compose group name */ group = kzalloc(length, GFP_KERNEL); - if (!group) { - ret = -ENOMEM; - goto free; - } + if (!group) + return -ENOMEM; snprintf(group, length, "%s.%d", np->name, reg); new_map[i].data.mux.group = group; i++; @@ -120,7 +118,7 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, pconfig = kmemdup(&config, sizeof(config), GFP_KERNEL); if (!pconfig) { ret = -ENOMEM; - goto free_group; + goto free; } new_map[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; @@ -135,9 +133,6 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, return 0; -free_group: - if (!purecfg) - free(group); free: kfree(new_map); return ret; @@ -516,7 +511,6 @@ int __devinit mxs_pinctrl_probe(struct platform_device *pdev, return 0; err: - platform_set_drvdata(pdev, NULL); iounmap(d->base); return ret; } @@ -526,7 +520,6 @@ int __devexit mxs_pinctrl_remove(struct platform_device *pdev) { struct mxs_pinctrl_data *d = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); pinctrl_unregister(d->pctl); iounmap(d->base); diff --git a/trunk/drivers/pinctrl/pinctrl-nomadik.c b/trunk/drivers/pinctrl/pinctrl-nomadik.c index e8937e7e4999..b8e01c3eaa95 100644 --- a/trunk/drivers/pinctrl/pinctrl-nomadik.c +++ b/trunk/drivers/pinctrl/pinctrl-nomadik.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -673,7 +672,7 @@ static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, * wakeup is anyhow controlled by the RIMSC and FIMSC registers. */ if (nmk_chip->sleepmode && on) { - __nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP, + __nmk_gpio_set_slpm(nmk_chip, gpio % nmk_chip->chip.base, NMK_GPIO_SLPM_WAKEUP_ENABLE); } @@ -1246,7 +1245,6 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) ret = PTR_ERR(clk); goto out_unmap; } - clk_prepare(clk); nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); if (!nmk_chip) { @@ -1690,34 +1688,18 @@ static struct pinctrl_desc nmk_pinctrl_desc = { .owner = THIS_MODULE, }; -static const struct of_device_id nmk_pinctrl_match[] = { - { - .compatible = "stericsson,nmk_pinctrl", - .data = (void *)PINCTRL_NMK_DB8500, - }, - {}, -}; - static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) { const struct platform_device_id *platid = platform_get_device_id(pdev); - struct device_node *np = pdev->dev.of_node; struct nmk_pinctrl *npct; - unsigned int version = 0; int i; npct = devm_kzalloc(&pdev->dev, sizeof(*npct), GFP_KERNEL); if (!npct) return -ENOMEM; - if (platid) - version = platid->driver_data; - else if (np) - version = (unsigned int) - of_match_device(nmk_pinctrl_match, &pdev->dev)->data; - /* Poke in other ASIC variants here */ - if (version == PINCTRL_NMK_DB8500) + if (platid->driver_data == PINCTRL_NMK_DB8500) nmk_pinctrl_db8500_init(&npct->soc); /* @@ -1776,7 +1758,6 @@ static struct platform_driver nmk_pinctrl_driver = { .driver = { .owner = THIS_MODULE, .name = "pinctrl-nomadik", - .of_match_table = nmk_pinctrl_match, }, .probe = nmk_pinctrl_probe, .id_table = nmk_pinctrl_id, diff --git a/trunk/drivers/pinctrl/pinctrl-sirf.c b/trunk/drivers/pinctrl/pinctrl-sirf.c index e9f8e7d11001..ba15b1a29e52 100644 --- a/trunk/drivers/pinctrl/pinctrl-sirf.c +++ b/trunk/drivers/pinctrl/pinctrl-sirf.c @@ -1184,7 +1184,7 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev) return ret; } -static const struct of_device_id pinmux_ids[] __devinitconst = { +static const struct of_device_id pinmux_ids[] = { { .compatible = "sirf,prima2-gpio-pinmux" }, {} }; diff --git a/trunk/drivers/platform/x86/acer-wmi.c b/trunk/drivers/platform/x86/acer-wmi.c index ce875dc365e5..c1a3fd8e1243 100644 --- a/trunk/drivers/platform/x86/acer-wmi.c +++ b/trunk/drivers/platform/x86/acer-wmi.c @@ -523,30 +523,6 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"), }, }, - { - .callback = video_set_backlight_video_vendor, - .ident = "Acer Extensa 5235", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"), - }, - }, - { - .callback = video_set_backlight_video_vendor, - .ident = "Acer TravelMate 5760", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"), - }, - }, - { - .callback = video_set_backlight_video_vendor, - .ident = "Acer Aspire 5750", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), - }, - }, {} }; diff --git a/trunk/drivers/platform/x86/acerhdf.c b/trunk/drivers/platform/x86/acerhdf.c index 2fd9d36acd15..639db4d0aa76 100644 --- a/trunk/drivers/platform/x86/acerhdf.c +++ b/trunk/drivers/platform/x86/acerhdf.c @@ -5,7 +5,7 @@ * * (C) 2009 - Peter Feuerer peter (a) piie.net * http://piie.net - * 2009 Borislav Petkov bp (a) alien8.de + * 2009 Borislav Petkov * * Inspired by and many thanks to: * o acerfand - Rachel Greenham diff --git a/trunk/drivers/platform/x86/apple-gmux.c b/trunk/drivers/platform/x86/apple-gmux.c index 694a15a56230..8a582bdfdc76 100644 --- a/trunk/drivers/platform/x86/apple-gmux.c +++ b/trunk/drivers/platform/x86/apple-gmux.c @@ -87,9 +87,6 @@ static int gmux_update_status(struct backlight_device *bd) struct apple_gmux_data *gmux_data = bl_get_data(bd); u32 brightness = bd->props.brightness; - if (bd->props.state & BL_CORE_SUSPENDED) - return 0; - /* * Older gmux versions require writing out lower bytes first then * setting the upper byte to 0 to flush the values. Newer versions @@ -105,7 +102,6 @@ static int gmux_update_status(struct backlight_device *bd) } static const struct backlight_ops gmux_bl_ops = { - .options = BL_CORE_SUSPENDRESUME, .get_brightness = gmux_get_brightness, .update_status = gmux_update_status, }; diff --git a/trunk/drivers/platform/x86/dell-laptop.c b/trunk/drivers/platform/x86/dell-laptop.c index 5f78aac9b163..e6c08ee8d46c 100644 --- a/trunk/drivers/platform/x86/dell-laptop.c +++ b/trunk/drivers/platform/x86/dell-laptop.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -89,8 +90,11 @@ static struct platform_driver platform_driver = { static struct platform_device *platform_device; static struct backlight_device *dell_backlight_device; +static struct rfkill *wifi_rfkill; +static struct rfkill *bluetooth_rfkill; +static struct rfkill *wwan_rfkill; -static const struct dmi_system_id dell_device_table[] __initconst = { +static const struct dmi_system_id __initdata dell_device_table[] = { { .ident = "Dell laptop", .matches = { @@ -115,94 +119,96 @@ static const struct dmi_system_id dell_device_table[] __initconst = { }; MODULE_DEVICE_TABLE(dmi, dell_device_table); -static struct dmi_system_id __devinitdata dell_quirks[] = { +static struct dmi_system_id __devinitdata dell_blacklist[] = { + /* Supported by compal-laptop */ { - .callback = dmi_matched, - .ident = "Dell Vostro V130", + .ident = "Dell Mini 9", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"), }, - .driver_data = &quirk_dell_vostro_v130, }, { - .callback = dmi_matched, - .ident = "Dell Vostro V131", + .ident = "Dell Mini 10", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"), }, - .driver_data = &quirk_dell_vostro_v130, }, { - .callback = dmi_matched, - .ident = "Dell Vostro 3350", + .ident = "Dell Mini 10v", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3350"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"), }, - .driver_data = &quirk_dell_vostro_v130, }, { - .callback = dmi_matched, - .ident = "Dell Vostro 3555", + .ident = "Dell Mini 1012", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), }, - .driver_data = &quirk_dell_vostro_v130, }, { - .callback = dmi_matched, - .ident = "Dell Inspiron N311z", + .ident = "Dell Inspiron 11z", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"), + }, + }, + { + .ident = "Dell Mini 12", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"), }, - .driver_data = &quirk_dell_vostro_v130, }, + {} +}; + +static struct dmi_system_id __devinitdata dell_quirks[] = { { .callback = dmi_matched, - .ident = "Dell Inspiron M5110", + .ident = "Dell Vostro V130", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"), }, .driver_data = &quirk_dell_vostro_v130, }, { .callback = dmi_matched, - .ident = "Dell Vostro 3360", + .ident = "Dell Vostro V131", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3360"), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"), }, .driver_data = &quirk_dell_vostro_v130, }, { .callback = dmi_matched, - .ident = "Dell Vostro 3460", + .ident = "Dell Vostro 3555", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3460"), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"), }, .driver_data = &quirk_dell_vostro_v130, }, { .callback = dmi_matched, - .ident = "Dell Vostro 3560", + .ident = "Dell Inspiron N311z", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3560"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"), }, .driver_data = &quirk_dell_vostro_v130, }, { .callback = dmi_matched, - .ident = "Dell Vostro 3450", + .ident = "Dell Inspiron M5110", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Dell System Vostro 3450"), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"), }, .driver_data = &quirk_dell_vostro_v130, }, @@ -299,6 +305,94 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, return buffer; } +/* Derived from information in DellWirelessCtl.cpp: + Class 17, select 11 is radio control. It returns an array of 32-bit values. + + Input byte 0 = 0: Wireless information + + result[0]: return code + result[1]: + Bit 0: Hardware switch supported + Bit 1: Wifi locator supported + Bit 2: Wifi is supported + Bit 3: Bluetooth is supported + Bit 4: WWAN is supported + Bit 5: Wireless keyboard supported + Bits 6-7: Reserved + Bit 8: Wifi is installed + Bit 9: Bluetooth is installed + Bit 10: WWAN is installed + Bits 11-15: Reserved + Bit 16: Hardware switch is on + Bit 17: Wifi is blocked + Bit 18: Bluetooth is blocked + Bit 19: WWAN is blocked + Bits 20-31: Reserved + result[2]: NVRAM size in bytes + result[3]: NVRAM format version number + + Input byte 0 = 2: Wireless switch configuration + result[0]: return code + result[1]: + Bit 0: Wifi controlled by switch + Bit 1: Bluetooth controlled by switch + Bit 2: WWAN controlled by switch + Bits 3-6: Reserved + Bit 7: Wireless switch config locked + Bit 8: Wifi locator enabled + Bits 9-14: Reserved + Bit 15: Wifi locator setting locked + Bits 16-31: Reserved +*/ + +static int dell_rfkill_set(void *data, bool blocked) +{ + int disable = blocked ? 1 : 0; + unsigned long radio = (unsigned long)data; + int hwswitch_bit = (unsigned long)data - 1; + int ret = 0; + + get_buffer(); + dell_send_request(buffer, 17, 11); + + /* If the hardware switch controls this radio, and the hardware + switch is disabled, don't allow changing the software state */ + if ((hwswitch_state & BIT(hwswitch_bit)) && + !(buffer->output[1] & BIT(16))) { + ret = -EINVAL; + goto out; + } + + buffer->input[0] = (1 | (radio<<8) | (disable << 16)); + dell_send_request(buffer, 17, 11); + +out: + release_buffer(); + return ret; +} + +static void dell_rfkill_query(struct rfkill *rfkill, void *data) +{ + int status; + int bit = (unsigned long)data + 16; + int hwswitch_bit = (unsigned long)data - 1; + + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; + release_buffer(); + + rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); + + if (hwswitch_state & (BIT(hwswitch_bit))) + rfkill_set_hw_state(rfkill, !(status & BIT(16))); +} + +static const struct rfkill_ops dell_rfkill_ops = { + .set_block = dell_rfkill_set, + .query = dell_rfkill_query, +}; + static struct dentry *dell_laptop_dir; static int dell_debugfs_show(struct seq_file *s, void *data) @@ -368,6 +462,108 @@ static const struct file_operations dell_debugfs_fops = { .release = single_release, }; +static void dell_update_rfkill(struct work_struct *ignored) +{ + if (wifi_rfkill) + dell_rfkill_query(wifi_rfkill, (void *)1); + if (bluetooth_rfkill) + dell_rfkill_query(bluetooth_rfkill, (void *)2); + if (wwan_rfkill) + dell_rfkill_query(wwan_rfkill, (void *)3); +} +static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); + + +static int __init dell_setup_rfkill(void) +{ + int status; + int ret; + + if (dmi_check_system(dell_blacklist)) { + pr_info("Blacklisted hardware detected - not enabling rfkill\n"); + return 0; + } + + get_buffer(); + dell_send_request(buffer, 17, 11); + status = buffer->output[1]; + buffer->input[0] = 0x2; + dell_send_request(buffer, 17, 11); + hwswitch_state = buffer->output[1]; + release_buffer(); + + if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { + wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, + RFKILL_TYPE_WLAN, + &dell_rfkill_ops, (void *) 1); + if (!wifi_rfkill) { + ret = -ENOMEM; + goto err_wifi; + } + ret = rfkill_register(wifi_rfkill); + if (ret) + goto err_wifi; + } + + if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { + bluetooth_rfkill = rfkill_alloc("dell-bluetooth", + &platform_device->dev, + RFKILL_TYPE_BLUETOOTH, + &dell_rfkill_ops, (void *) 2); + if (!bluetooth_rfkill) { + ret = -ENOMEM; + goto err_bluetooth; + } + ret = rfkill_register(bluetooth_rfkill); + if (ret) + goto err_bluetooth; + } + + if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { + wwan_rfkill = rfkill_alloc("dell-wwan", + &platform_device->dev, + RFKILL_TYPE_WWAN, + &dell_rfkill_ops, (void *) 3); + if (!wwan_rfkill) { + ret = -ENOMEM; + goto err_wwan; + } + ret = rfkill_register(wwan_rfkill); + if (ret) + goto err_wwan; + } + + return 0; +err_wwan: + rfkill_destroy(wwan_rfkill); + if (bluetooth_rfkill) + rfkill_unregister(bluetooth_rfkill); +err_bluetooth: + rfkill_destroy(bluetooth_rfkill); + if (wifi_rfkill) + rfkill_unregister(wifi_rfkill); +err_wifi: + rfkill_destroy(wifi_rfkill); + + return ret; +} + +static void dell_cleanup_rfkill(void) +{ + if (wifi_rfkill) { + rfkill_unregister(wifi_rfkill); + rfkill_destroy(wifi_rfkill); + } + if (bluetooth_rfkill) { + rfkill_unregister(bluetooth_rfkill); + rfkill_destroy(bluetooth_rfkill); + } + if (wwan_rfkill) { + rfkill_unregister(wwan_rfkill); + rfkill_destroy(wwan_rfkill); + } +} + static int dell_send_intensity(struct backlight_device *bd) { int ret = 0; @@ -459,6 +655,30 @@ static void touchpad_led_exit(void) led_classdev_unregister(&touchpad_led); } +static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, + struct serio *port) +{ + static bool extended; + + if (str & 0x20) + return false; + + if (unlikely(data == 0xe0)) { + extended = true; + return false; + } else if (unlikely(extended)) { + switch (data) { + case 0x8: + schedule_delayed_work(&dell_rfkill_work, + round_jiffies_relative(HZ)); + break; + } + extended = false; + } + + return false; +} + static int __init dell_init(void) { int max_intensity = 0; @@ -500,10 +720,26 @@ static int __init dell_init(void) goto fail_buffer; buffer = page_address(bufferpage); + ret = dell_setup_rfkill(); + + if (ret) { + pr_warn("Unable to setup rfkill\n"); + goto fail_rfkill; + } + + ret = i8042_install_filter(dell_laptop_i8042_filter); + if (ret) { + pr_warn("Unable to install key filter\n"); + goto fail_filter; + } + if (quirks && quirks->touchpad_led) touchpad_led_init(&platform_device->dev); dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); + if (dell_laptop_dir != NULL) + debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, + &dell_debugfs_fops); #ifdef CONFIG_ACPI /* In the event of an ACPI backlight being available, don't @@ -546,6 +782,11 @@ static int __init dell_init(void) return 0; fail_backlight: + i8042_remove_filter(dell_laptop_i8042_filter); + cancel_delayed_work_sync(&dell_rfkill_work); +fail_filter: + dell_cleanup_rfkill(); +fail_rfkill: free_page((unsigned long)bufferpage); fail_buffer: platform_device_del(platform_device); @@ -563,7 +804,10 @@ static void __exit dell_exit(void) debugfs_remove_recursive(dell_laptop_dir); if (quirks && quirks->touchpad_led) touchpad_led_exit(); + i8042_remove_filter(dell_laptop_i8042_filter); + cancel_delayed_work_sync(&dell_rfkill_work); backlight_device_unregister(dell_backlight_device); + dell_cleanup_rfkill(); if (platform_device) { platform_device_unregister(platform_device); platform_driver_unregister(&platform_driver); diff --git a/trunk/drivers/platform/x86/fujitsu-tablet.c b/trunk/drivers/platform/x86/fujitsu-tablet.c index da267eae8ba8..580d80a73c3a 100644 --- a/trunk/drivers/platform/x86/fujitsu-tablet.c +++ b/trunk/drivers/platform/x86/fujitsu-tablet.c @@ -16,8 +16,6 @@ * 59 Temple Place Suite 330, Boston, MA 02111-1307, USA. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -36,8 +34,7 @@ #define ACPI_FUJITSU_CLASS "fujitsu" #define INVERT_TABLET_MODE_BIT 0x01 -#define INVERT_DOCK_STATE_BIT 0x02 -#define FORCE_TABLET_MODE_IF_UNDOCK 0x04 +#define FORCE_TABLET_MODE_IF_UNDOCK 0x02 #define KEYMAP_LEN 16 @@ -164,8 +161,6 @@ static void fujitsu_send_state(void) state = fujitsu_read_register(0xdd); dock = state & 0x02; - if (fujitsu.config.quirks & INVERT_DOCK_STATE_BIT) - dock = !dock; if ((fujitsu.config.quirks & FORCE_TABLET_MODE_IF_UNDOCK) && (!dock)) { tablet_mode = 1; @@ -226,6 +221,9 @@ static int __devinit input_fujitsu_setup(struct device *parent, input_set_capability(idev, EV_SW, SW_DOCK); input_set_capability(idev, EV_SW, SW_TABLET_MODE); + input_set_capability(idev, EV_SW, SW_DOCK); + input_set_capability(idev, EV_SW, SW_TABLET_MODE); + error = input_register_device(idev); if (error) { input_free_device(idev); @@ -277,31 +275,25 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void __devinit fujitsu_dmi_common(const struct dmi_system_id *dmi) +static int __devinit fujitsu_dmi_default(const struct dmi_system_id *dmi) { - pr_info("%s\n", dmi->ident); + printk(KERN_INFO MODULENAME ": %s\n", dmi->ident); memcpy(fujitsu.config.keymap, dmi->driver_data, sizeof(fujitsu.config.keymap)); -} - -static int __devinit fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) -{ - fujitsu_dmi_common(dmi); - fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; return 1; } static int __devinit fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) { - fujitsu_dmi_common(dmi); + fujitsu_dmi_default(dmi); fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; - fujitsu.config.quirks |= INVERT_DOCK_STATE_BIT; + fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; return 1; } static struct dmi_system_id dmi_ids[] __initconst = { { - .callback = fujitsu_dmi_lifebook, + .callback = fujitsu_dmi_default, .ident = "Fujitsu Siemens P/T Series", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), @@ -310,7 +302,7 @@ static struct dmi_system_id dmi_ids[] __initconst = { .driver_data = keymap_Lifebook_Tseries }, { - .callback = fujitsu_dmi_lifebook, + .callback = fujitsu_dmi_default, .ident = "Fujitsu Lifebook T Series", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), @@ -328,7 +320,7 @@ static struct dmi_system_id dmi_ids[] __initconst = { .driver_data = keymap_Stylistic_Tseries }, { - .callback = fujitsu_dmi_lifebook, + .callback = fujitsu_dmi_default, .ident = "Fujitsu LifeBook U810", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), @@ -355,7 +347,7 @@ static struct dmi_system_id dmi_ids[] __initconst = { .driver_data = keymap_Stylistic_ST5xxx }, { - .callback = fujitsu_dmi_lifebook, + .callback = fujitsu_dmi_default, .ident = "Unknown (using defaults)", .matches = { DMI_MATCH(DMI_SYS_VENDOR, ""), @@ -481,6 +473,6 @@ module_exit(fujitsu_module_exit); MODULE_AUTHOR("Robert Gerlach "); MODULE_DESCRIPTION("Fujitsu tablet pc extras driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("2.5"); +MODULE_VERSION("2.4"); MODULE_DEVICE_TABLE(acpi, fujitsu_ids); diff --git a/trunk/drivers/platform/x86/hdaps.c b/trunk/drivers/platform/x86/hdaps.c index 24a3ae065f1b..7387f97a2941 100644 --- a/trunk/drivers/platform/x86/hdaps.c +++ b/trunk/drivers/platform/x86/hdaps.c @@ -2,7 +2,7 @@ * hdaps.c - driver for IBM's Hard Drive Active Protection System * * Copyright (C) 2005 Robert Love - * Copyright (C) 2005 Jesper Juhl + * Copyright (C) 2005 Jesper Juhl * * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads * starting with the R40, T41, and X40. It provides a basic two-axis diff --git a/trunk/drivers/platform/x86/hp-wmi.c b/trunk/drivers/platform/x86/hp-wmi.c index 387183a2d6dd..e2faa3cbb792 100644 --- a/trunk/drivers/platform/x86/hp-wmi.c +++ b/trunk/drivers/platform/x86/hp-wmi.c @@ -634,8 +634,6 @@ static int __devinit hp_wmi_rfkill_setup(struct platform_device *device) RFKILL_TYPE_WLAN, &hp_wmi_rfkill_ops, (void *) HPWMI_WIFI); - if (!wifi_rfkill) - return -ENOMEM; rfkill_init_sw_state(wifi_rfkill, hp_wmi_get_sw_state(HPWMI_WIFI)); rfkill_set_hw_state(wifi_rfkill, @@ -650,10 +648,6 @@ static int __devinit hp_wmi_rfkill_setup(struct platform_device *device) RFKILL_TYPE_BLUETOOTH, &hp_wmi_rfkill_ops, (void *) HPWMI_BLUETOOTH); - if (!bluetooth_rfkill) { - err = -ENOMEM; - goto register_wifi_error; - } rfkill_init_sw_state(bluetooth_rfkill, hp_wmi_get_sw_state(HPWMI_BLUETOOTH)); rfkill_set_hw_state(bluetooth_rfkill, @@ -668,10 +662,6 @@ static int __devinit hp_wmi_rfkill_setup(struct platform_device *device) RFKILL_TYPE_WWAN, &hp_wmi_rfkill_ops, (void *) HPWMI_WWAN); - if (!wwan_rfkill) { - err = -ENOMEM; - goto register_bluetooth_error; - } rfkill_init_sw_state(wwan_rfkill, hp_wmi_get_sw_state(HPWMI_WWAN)); rfkill_set_hw_state(wwan_rfkill, diff --git a/trunk/drivers/platform/x86/ideapad-laptop.c b/trunk/drivers/platform/x86/ideapad-laptop.c index 4f20f8dd3d7c..ac902f7a9baa 100644 --- a/trunk/drivers/platform/x86/ideapad-laptop.c +++ b/trunk/drivers/platform/x86/ideapad-laptop.c @@ -194,6 +194,7 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data) /* * debugfs */ +#define DEBUGFS_EVENT_LEN (4096) static int debugfs_status_show(struct seq_file *s, void *data) { unsigned long value; @@ -314,7 +315,7 @@ static int __devinit ideapad_debugfs_init(struct ideapad_private *priv) node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL, &debugfs_status_fops); if (!node) { - pr_err("failed to create status in debugfs"); + pr_err("failed to create event in debugfs"); goto errout; } @@ -784,10 +785,6 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) case 9: ideapad_sync_rfk_state(priv); break; - case 13: - case 6: - ideapad_input_report(priv, vpc_bit); - break; case 4: ideapad_backlight_notify_brightness(priv); break; @@ -798,7 +795,7 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) ideapad_backlight_notify_power(priv); break; default: - pr_info("Unknown event: %lu\n", vpc_bit); + ideapad_input_report(priv, vpc_bit); } } } diff --git a/trunk/drivers/platform/x86/sony-laptop.c b/trunk/drivers/platform/x86/sony-laptop.c index 210d4ae547c2..8a51795aa02a 100644 --- a/trunk/drivers/platform/x86/sony-laptop.c +++ b/trunk/drivers/platform/x86/sony-laptop.c @@ -141,27 +141,6 @@ MODULE_PARM_DESC(kbd_backlight_timeout, "(default: 0)"); static void sony_nc_kbd_backlight_resume(void); -static int sony_nc_kbd_backlight_setup(struct platform_device *pd, - unsigned int handle); -static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd); - -static int sony_nc_battery_care_setup(struct platform_device *pd, - unsigned int handle); -static void sony_nc_battery_care_cleanup(struct platform_device *pd); - -static int sony_nc_thermal_setup(struct platform_device *pd); -static void sony_nc_thermal_cleanup(struct platform_device *pd); -static void sony_nc_thermal_resume(void); - -static int sony_nc_lid_resume_setup(struct platform_device *pd); -static void sony_nc_lid_resume_cleanup(struct platform_device *pd); - -static int sony_nc_highspeed_charging_setup(struct platform_device *pd); -static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); - -static int sony_nc_touchpad_setup(struct platform_device *pd, - unsigned int handle); -static void sony_nc_touchpad_cleanup(struct platform_device *pd); enum sony_nc_rfkill { SONY_WIFI, @@ -174,9 +153,6 @@ enum sony_nc_rfkill { static int sony_rfkill_handle; static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; -static int sony_nc_rfkill_setup(struct acpi_device *device, - unsigned int handle); -static void sony_nc_rfkill_cleanup(void); static void sony_nc_rfkill_update(void); /*********** Input Devices ***********/ @@ -715,97 +691,59 @@ static struct acpi_device *sony_nc_acpi_device = NULL; /* * acpi_evaluate_object wrappers - * all useful calls into SNC methods take one or zero parameters and return - * integers or arrays. */ -static union acpi_object *__call_snc_method(acpi_handle handle, char *method, - u64 *value) +static int acpi_callgetfunc(acpi_handle handle, char *name, int *result) { - union acpi_object *result = NULL; - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer output; + union acpi_object out_obj; acpi_status status; - if (value) { - struct acpi_object_list params; - union acpi_object in; - in.type = ACPI_TYPE_INTEGER; - in.integer.value = *value; - params.count = 1; - params.pointer = ∈ - status = acpi_evaluate_object(handle, method, ¶ms, &output); - dprintk("__call_snc_method: [%s:0x%.8x%.8x]\n", method, - (unsigned int)(*value >> 32), - (unsigned int)*value & 0xffffffff); - } else { - status = acpi_evaluate_object(handle, method, NULL, &output); - dprintk("__call_snc_method: [%s]\n", method); - } - - if (ACPI_FAILURE(status)) { - pr_err("Failed to evaluate [%s]\n", method); - return NULL; - } - - result = (union acpi_object *) output.pointer; - if (!result) - dprintk("No return object [%s]\n", method); - - return result; -} - -static int sony_nc_int_call(acpi_handle handle, char *name, int *value, - int *result) -{ - union acpi_object *object = NULL; - if (value) { - u64 v = *value; - object = __call_snc_method(handle, name, &v); - } else - object = __call_snc_method(handle, name, NULL); - - if (!object) - return -EINVAL; + output.length = sizeof(out_obj); + output.pointer = &out_obj; - if (object->type != ACPI_TYPE_INTEGER) { - pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", - ACPI_TYPE_INTEGER, object->type); - kfree(object); - return -EINVAL; + status = acpi_evaluate_object(handle, name, NULL, &output); + if ((status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER)) { + *result = out_obj.integer.value; + return 0; } - if (result) - *result = object->integer.value; + pr_warn("acpi_callreadfunc failed\n"); - kfree(object); - return 0; + return -1; } -#define MIN(a, b) (a > b ? b : a) -static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, - void *buffer, size_t buflen) +static int acpi_callsetfunc(acpi_handle handle, char *name, int value, + int *result) { - size_t len = len; - union acpi_object *object = __call_snc_method(handle, name, value); - - if (!object) - return -EINVAL; + struct acpi_object_list params; + union acpi_object in_obj; + struct acpi_buffer output; + union acpi_object out_obj; + acpi_status status; - if (object->type == ACPI_TYPE_BUFFER) - len = MIN(buflen, object->buffer.length); + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = value; - else if (object->type == ACPI_TYPE_INTEGER) - len = MIN(buflen, sizeof(object->integer.value)); + output.length = sizeof(out_obj); + output.pointer = &out_obj; - else { - pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", - ACPI_TYPE_BUFFER, object->type); - kfree(object); - return -EINVAL; + status = acpi_evaluate_object(handle, name, ¶ms, &output); + if (status == AE_OK) { + if (result != NULL) { + if (out_obj.type != ACPI_TYPE_INTEGER) { + pr_warn("acpi_evaluate_object bad return type\n"); + return -1; + } + *result = out_obj.integer.value; + } + return 0; } - memcpy(buffer, object->buffer.pointer, len); - kfree(object); - return 0; + pr_warn("acpi_evaluate_object failed\n"); + + return -1; } struct sony_nc_handles { @@ -832,17 +770,16 @@ static ssize_t sony_nc_handles_show(struct device *dev, static int sony_nc_handles_setup(struct platform_device *pd) { - int i, r, result, arg; + int i; + int result; handles = kzalloc(sizeof(*handles), GFP_KERNEL); if (!handles) return -ENOMEM; for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - arg = i + 0x20; - r = sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, - &result); - if (!r) { + if (!acpi_callsetfunc(sony_nc_acpi_handle, + "SN00", i + 0x20, &result)) { dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n", result, i); handles->cap[i] = result; @@ -882,8 +819,8 @@ static int sony_find_snc_handle(int handle) int i; /* not initialized yet, return early */ - if (!handles || !handle) - return -EINVAL; + if (!handles) + return -1; for (i = 0; i < 0x10; i++) { if (handles->cap[i] == handle) { @@ -893,20 +830,21 @@ static int sony_find_snc_handle(int handle) } } dprintk("handle 0x%.4x not found\n", handle); - return -EINVAL; + return -1; } static int sony_call_snc_handle(int handle, int argument, int *result) { - int arg, ret = 0; + int ret = 0; int offset = sony_find_snc_handle(handle); if (offset < 0) - return offset; + return -1; - arg = offset | argument; - ret = sony_nc_int_call(sony_nc_acpi_handle, "SN07", &arg, result); - dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", arg, *result); + ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, + result); + dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument, + *result); return ret; } @@ -951,16 +889,14 @@ static int boolean_validate(const int direction, const int value) static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr, char *buffer) { - int value, ret = 0; + int value; struct sony_nc_value *item = container_of(attr, struct sony_nc_value, devattr); if (!*item->acpiget) return -EIO; - ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiget, NULL, - &value); - if (ret < 0) + if (acpi_callgetfunc(sony_nc_acpi_handle, *item->acpiget, &value) < 0) return -EIO; if (item->validate) @@ -973,8 +909,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev, struct device_attribute *attr, const char *buffer, size_t count) { - unsigned long value = 0; - int ret = 0; + int value; struct sony_nc_value *item = container_of(attr, struct sony_nc_value, devattr); @@ -984,8 +919,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; + value = simple_strtoul(buffer, NULL, 10); if (item->validate) value = item->validate(SNC_VALIDATE_IN, value); @@ -993,11 +927,8 @@ static ssize_t sony_nc_sysfs_store(struct device *dev, if (value < 0) return value; - ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset, - (int *)&value, NULL); - if (ret < 0) + if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0) return -EIO; - item->value = value; item->valid = 1; return count; @@ -1017,15 +948,15 @@ struct sony_backlight_props sony_bl_props; static int sony_backlight_update_status(struct backlight_device *bd) { - int arg = bd->props.brightness + 1; - return sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &arg, NULL); + return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", + bd->props.brightness + 1, NULL); } static int sony_backlight_get_brightness(struct backlight_device *bd) { int value; - if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL, &value)) + if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) return 0; /* brightness levels are 1-based, while backlight ones are 0-based */ return value - 1; @@ -1093,14 +1024,10 @@ static struct sony_nc_event sony_100_events[] = { { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, { 0x87, SONYPI_EVENT_FNKEY_F7 }, { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, - { 0x88, SONYPI_EVENT_FNKEY_F8 }, - { 0x08, SONYPI_EVENT_FNKEY_RELEASED }, { 0x89, SONYPI_EVENT_FNKEY_F9 }, { 0x09, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8A, SONYPI_EVENT_FNKEY_F10 }, { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, - { 0x8B, SONYPI_EVENT_FNKEY_F11 }, - { 0x0B, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8C, SONYPI_EVENT_FNKEY_F12 }, { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, { 0x9d, SONYPI_EVENT_ZOOM_PRESSED }, @@ -1136,116 +1063,63 @@ static struct sony_nc_event sony_127_events[] = { { 0, 0 }, }; -static int sony_nc_hotkeys_decode(u32 event, unsigned int handle) -{ - int ret = -EINVAL; - unsigned int result = 0; - struct sony_nc_event *key_event; - - if (sony_call_snc_handle(handle, 0x200, &result)) { - dprintk("Unable to decode event 0x%.2x 0x%.2x\n", handle, - event); - return -EINVAL; - } - - result &= 0xFF; - - if (handle == 0x0100) - key_event = sony_100_events; - else - key_event = sony_127_events; - - for (; key_event->data; key_event++) { - if (key_event->data == result) { - ret = key_event->event; - break; - } - } - - if (!key_event->data) - pr_info("Unknown hotkey 0x%.2x/0x%.2x (handle 0x%.2x)\n", - event, result, handle); - - return ret; -} - /* * ACPI callbacks */ static void sony_nc_notify(struct acpi_device *device, u32 event) { - u32 real_ev = event; - u8 ev_type = 0; - dprintk("sony_nc_notify, event: 0x%.2x\n", event); - - if (event >= 0x90) { - unsigned int result = 0; - unsigned int arg = 0; - unsigned int handle = 0; - unsigned int offset = event - 0x90; - - if (offset >= ARRAY_SIZE(handles->cap)) { - pr_err("Event 0x%x outside of capabilities list\n", - event); - return; - } - handle = handles->cap[offset]; - - /* list of handles known for generating events */ - switch (handle) { - /* hotkey event */ - case 0x0100: - case 0x0127: - ev_type = 1; - real_ev = sony_nc_hotkeys_decode(event, handle); - - if (real_ev > 0) - sony_laptop_report_input_event(real_ev); - else - /* restore the original event for reporting */ - real_ev = event; - - break; + u32 ev = event; - /* wlan switch */ - case 0x0124: - case 0x0135: - /* events on this handle are reported when the - * switch changes position or for battery - * events. We'll notify both of them but only - * update the rfkill device status when the - * switch is moved. - */ - ev_type = 2; - sony_call_snc_handle(handle, 0x0100, &result); - real_ev = result & 0x03; - - /* hw switch event */ - if (real_ev == 1) - sony_nc_rfkill_update(); - - break; + if (ev >= 0x90) { + /* New-style event */ + int result; + int key_handle = 0; + ev -= 0x90; + + if (sony_find_snc_handle(0x100) == ev) + key_handle = 0x100; + if (sony_find_snc_handle(0x127) == ev) + key_handle = 0x127; + + if (key_handle) { + struct sony_nc_event *key_event; + + if (sony_call_snc_handle(key_handle, 0x200, &result)) { + dprintk("sony_nc_notify, unable to decode" + " event 0x%.2x 0x%.2x\n", key_handle, + ev); + /* restore the original event */ + ev = event; + } else { + ev = result & 0xFF; + + if (key_handle == 0x100) + key_event = sony_100_events; + else + key_event = sony_127_events; + + for (; key_event->data; key_event++) { + if (key_event->data == ev) { + ev = key_event->event; + break; + } + } - default: - dprintk("Unknown event 0x%x for handle 0x%x\n", - event, handle); - break; + if (!key_event->data) + pr_info("Unknown event: 0x%x 0x%x\n", + key_handle, ev); + else + sony_laptop_report_input_event(ev); + } + } else if (sony_find_snc_handle(sony_rfkill_handle) == ev) { + sony_nc_rfkill_update(); + return; } + } else + sony_laptop_report_input_event(ev); - /* clear the event (and the event reason when present) */ - arg = 1 << offset; - sony_nc_int_call(sony_nc_acpi_handle, "SN05", &arg, &result); - - } else { - /* old style event */ - ev_type = 1; - sony_laptop_report_input_event(real_ev); - } - - acpi_bus_generate_proc_event(sony_nc_acpi_device, ev_type, real_ev); - - acpi_bus_generate_netlink_event(sony_nc_acpi_device->pnp.device_class, - dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev); + dprintk("sony_nc_notify, event: 0x%.2x\n", ev); + acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); } static acpi_status sony_walk_callback(acpi_handle handle, u32 level, @@ -1266,190 +1140,20 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, /* * ACPI device */ -static void sony_nc_function_setup(struct acpi_device *device, - struct platform_device *pf_device) +static int sony_nc_function_setup(struct acpi_device *device) { - unsigned int i, result, bitmask, arg; - - if (!handles) - return; - - /* setup found handles here */ - for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - unsigned int handle = handles->cap[i]; - - if (!handle) - continue; - - dprintk("setting up handle 0x%.4x\n", handle); - - switch (handle) { - case 0x0100: - case 0x0101: - case 0x0127: - /* setup hotkeys */ - sony_call_snc_handle(handle, 0, &result); - break; - case 0x0102: - /* setup hotkeys */ - sony_call_snc_handle(handle, 0x100, &result); - break; - case 0x0105: - case 0x0148: - /* touchpad enable/disable */ - result = sony_nc_touchpad_setup(pf_device, handle); - if (result) - pr_err("couldn't set up touchpad control function (%d)\n", - result); - break; - case 0x0115: - case 0x0136: - case 0x013f: - result = sony_nc_battery_care_setup(pf_device, handle); - if (result) - pr_err("couldn't set up battery care function (%d)\n", - result); - break; - case 0x0119: - result = sony_nc_lid_resume_setup(pf_device); - if (result) - pr_err("couldn't set up lid resume function (%d)\n", - result); - break; - case 0x0122: - result = sony_nc_thermal_setup(pf_device); - if (result) - pr_err("couldn't set up thermal profile function (%d)\n", - result); - break; - case 0x0131: - result = sony_nc_highspeed_charging_setup(pf_device); - if (result) - pr_err("couldn't set up high speed charging function (%d)\n", - result); - break; - case 0x0124: - case 0x0135: - result = sony_nc_rfkill_setup(device, handle); - if (result) - pr_err("couldn't set up rfkill support (%d)\n", - result); - break; - case 0x0137: - case 0x0143: - result = sony_nc_kbd_backlight_setup(pf_device, handle); - if (result) - pr_err("couldn't set up keyboard backlight function (%d)\n", - result); - break; - default: - continue; - } - } + int result; /* Enable all events */ - arg = 0x10; - if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask)) - sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask, - &result); -} - -static void sony_nc_function_cleanup(struct platform_device *pd) -{ - unsigned int i, result, bitmask, handle; - - /* get enabled events and disable them */ - sony_nc_int_call(sony_nc_acpi_handle, "SN01", NULL, &bitmask); - sony_nc_int_call(sony_nc_acpi_handle, "SN03", &bitmask, &result); - - /* cleanup handles here */ - for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - - handle = handles->cap[i]; - - if (!handle) - continue; - - switch (handle) { - case 0x0105: - case 0x0148: - sony_nc_touchpad_cleanup(pd); - break; - case 0x0115: - case 0x0136: - case 0x013f: - sony_nc_battery_care_cleanup(pd); - break; - case 0x0119: - sony_nc_lid_resume_cleanup(pd); - break; - case 0x0122: - sony_nc_thermal_cleanup(pd); - break; - case 0x0131: - sony_nc_highspeed_charging_cleanup(pd); - break; - case 0x0124: - case 0x0135: - sony_nc_rfkill_cleanup(); - break; - case 0x0137: - case 0x0143: - sony_nc_kbd_backlight_cleanup(pd); - break; - default: - continue; - } - } - - /* finally cleanup the handles list */ - sony_nc_handles_cleanup(pd); -} - -static void sony_nc_function_resume(void) -{ - unsigned int i, result, bitmask, arg; - - dprintk("Resuming SNC device\n"); + acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result); - for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { - unsigned int handle = handles->cap[i]; - - if (!handle) - continue; - - switch (handle) { - case 0x0100: - case 0x0101: - case 0x0127: - /* re-enable hotkeys */ - sony_call_snc_handle(handle, 0, &result); - break; - case 0x0102: - /* re-enable hotkeys */ - sony_call_snc_handle(handle, 0x100, &result); - break; - case 0x0122: - sony_nc_thermal_resume(); - break; - case 0x0124: - case 0x0135: - sony_nc_rfkill_update(); - break; - case 0x0137: - case 0x0143: - sony_nc_kbd_backlight_resume(); - break; - default: - continue; - } - } + /* Setup hotkeys */ + sony_call_snc_handle(0x0100, 0, &result); + sony_call_snc_handle(0x0101, 0, &result); + sony_call_snc_handle(0x0102, 0x100, &result); + sony_call_snc_handle(0x0127, 0, &result); - /* Enable all events */ - arg = 0x10; - if (!sony_nc_int_call(sony_nc_acpi_handle, "SN00", &arg, &bitmask)) - sony_nc_int_call(sony_nc_acpi_handle, "SN02", &bitmask, - &result); + return 0; } static int sony_nc_resume(struct acpi_device *device) @@ -1462,8 +1166,8 @@ static int sony_nc_resume(struct acpi_device *device) if (!item->valid) continue; - ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset, - &item->value, NULL); + ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, + item->value, NULL); if (ret < 0) { pr_err("%s: %d\n", __func__, ret); break; @@ -1472,14 +1176,21 @@ static int sony_nc_resume(struct acpi_device *device) if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", &handle))) { - int arg = 1; - if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL)) + if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) dprintk("ECON Method failed\n"); } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", - &handle))) - sony_nc_function_resume(); + &handle))) { + dprintk("Doing SNC setup\n"); + sony_nc_function_setup(device); + } + + /* re-read rfkill state */ + sony_nc_rfkill_update(); + + /* restore kbd backlight states */ + sony_nc_kbd_backlight_resume(); return 0; } @@ -1502,7 +1213,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked) int argument = sony_rfkill_address[(long) data] + 0x100; if (!blocked) - argument |= 0x030000; + argument |= 0xff0000; return sony_call_snc_handle(sony_rfkill_handle, argument, &result); } @@ -1519,7 +1230,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, enum rfkill_type type; const char *name; int result; - bool hwblock, swblock; + bool hwblock; switch (nc_type) { case SONY_WIFI: @@ -1547,21 +1258,8 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, if (!rfk) return -ENOMEM; - if (sony_call_snc_handle(sony_rfkill_handle, 0x200, &result) < 0) { - rfkill_destroy(rfk); - return -1; - } + sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); hwblock = !(result & 0x1); - - if (sony_call_snc_handle(sony_rfkill_handle, - sony_rfkill_address[nc_type], - &result) < 0) { - rfkill_destroy(rfk); - return -1; - } - swblock = !(result & 0x2); - - rfkill_init_sw_state(rfk, swblock); rfkill_set_hw_state(rfk, hwblock); err = rfkill_register(rfk); @@ -1597,79 +1295,101 @@ static void sony_nc_rfkill_update(void) sony_call_snc_handle(sony_rfkill_handle, argument, &result); rfkill_set_states(sony_rfkill_devices[i], - !(result & 0x2), false); + !(result & 0xf), false); } } -static int sony_nc_rfkill_setup(struct acpi_device *device, - unsigned int handle) +static void sony_nc_rfkill_setup(struct acpi_device *device) { - u64 offset; - int i; - unsigned char buffer[32] = { 0 }; + int offset; + u8 dev_code, i; + acpi_status status; + struct acpi_object_list params; + union acpi_object in_obj; + union acpi_object *device_enum; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + offset = sony_find_snc_handle(0x124); + if (offset == -1) { + offset = sony_find_snc_handle(0x135); + if (offset == -1) + return; + else + sony_rfkill_handle = 0x135; + } else + sony_rfkill_handle = 0x124; + dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle); - offset = sony_find_snc_handle(handle); - sony_rfkill_handle = handle; - - i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer, - 32); - if (i < 0) - return i; - - /* The buffer is filled with magic numbers describing the devices - * available, 0xff terminates the enumeration. - * Known codes: - * 0x00 WLAN - * 0x10 BLUETOOTH - * 0x20 WWAN GPRS-EDGE - * 0x21 WWAN HSDPA - * 0x22 WWAN EV-DO - * 0x23 WWAN GPS - * 0x25 Gobi WWAN no GPS - * 0x26 Gobi WWAN + GPS - * 0x28 Gobi WWAN no GPS - * 0x29 Gobi WWAN + GPS - * 0x30 WIMAX - * 0x50 Gobi WWAN no GPS - * 0x51 Gobi WWAN + GPS - * 0x70 no SIM card slot - * 0x71 SIM card slot + /* need to read the whole buffer returned by the acpi call to SN06 + * here otherwise we may miss some features + */ + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = offset; + status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, + &buffer); + if (ACPI_FAILURE(status)) { + dprintk("Radio device enumeration failed\n"); + return; + } + + device_enum = (union acpi_object *) buffer.pointer; + if (!device_enum) { + pr_err("No SN06 return object\n"); + goto out_no_enum; + } + if (device_enum->type != ACPI_TYPE_BUFFER) { + pr_err("Invalid SN06 return object 0x%.2x\n", + device_enum->type); + goto out_no_enum; + } + + /* the buffer is filled with magic numbers describing the devices + * available, 0xff terminates the enumeration */ - for (i = 0; i < ARRAY_SIZE(buffer); i++) { + for (i = 0; i < device_enum->buffer.length; i++) { - if (buffer[i] == 0xff) + dev_code = *(device_enum->buffer.pointer + i); + if (dev_code == 0xff) break; - dprintk("Radio devices, found 0x%.2x\n", buffer[i]); + dprintk("Radio devices, looking at 0x%.2x\n", dev_code); - if (buffer[i] == 0 && !sony_rfkill_devices[SONY_WIFI]) + if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) sony_nc_setup_rfkill(device, SONY_WIFI); - if (buffer[i] == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) + if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) sony_nc_setup_rfkill(device, SONY_BLUETOOTH); - if (((0xf0 & buffer[i]) == 0x20 || - (0xf0 & buffer[i]) == 0x50) && + if ((0xf0 & dev_code) == 0x20 && !sony_rfkill_devices[SONY_WWAN]) sony_nc_setup_rfkill(device, SONY_WWAN); - if (buffer[i] == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) + if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) sony_nc_setup_rfkill(device, SONY_WIMAX); } - return 0; + +out_no_enum: + kfree(buffer.pointer); + return; } /* Keyboard backlight feature */ +#define KBDBL_HANDLER 0x137 +#define KBDBL_PRESENT 0xB00 +#define SET_MODE 0xC00 +#define SET_STATE 0xD00 +#define SET_TIMEOUT 0xE00 + struct kbd_backlight { - unsigned int handle; - unsigned int base; - unsigned int mode; - unsigned int timeout; + int mode; + int timeout; struct device_attribute mode_attr; struct device_attribute timeout_attr; }; -static struct kbd_backlight *kbdbl_ctl; +static struct kbd_backlight *kbdbl_handle; static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) { @@ -1678,15 +1398,15 @@ static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) if (value > 1) return -EINVAL; - if (sony_call_snc_handle(kbdbl_ctl->handle, - (value << 0x10) | (kbdbl_ctl->base), &result)) + if (sony_call_snc_handle(KBDBL_HANDLER, + (value << 0x10) | SET_MODE, &result)) return -EIO; /* Try to turn the light on/off immediately */ - sony_call_snc_handle(kbdbl_ctl->handle, - (value << 0x10) | (kbdbl_ctl->base + 0x100), &result); + sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE, + &result); - kbdbl_ctl->mode = value; + kbdbl_handle->mode = value; return 0; } @@ -1701,7 +1421,7 @@ static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) + if (strict_strtoul(buffer, 10, &value)) return -EINVAL; ret = __sony_nc_kbd_backlight_mode_set(value); @@ -1715,7 +1435,7 @@ static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev, struct device_attribute *attr, char *buffer) { ssize_t count = 0; - count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->mode); + count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode); return count; } @@ -1726,11 +1446,11 @@ static int __sony_nc_kbd_backlight_timeout_set(u8 value) if (value > 3) return -EINVAL; - if (sony_call_snc_handle(kbdbl_ctl->handle, (value << 0x10) | - (kbdbl_ctl->base + 0x200), &result)) + if (sony_call_snc_handle(KBDBL_HANDLER, + (value << 0x10) | SET_TIMEOUT, &result)) return -EIO; - kbdbl_ctl->timeout = value; + kbdbl_handle->timeout = value; return 0; } @@ -1745,7 +1465,7 @@ static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) + if (strict_strtoul(buffer, 10, &value)) return -EINVAL; ret = __sony_nc_kbd_backlight_timeout_set(value); @@ -1759,58 +1479,39 @@ static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev, struct device_attribute *attr, char *buffer) { ssize_t count = 0; - count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_ctl->timeout); + count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout); return count; } -static int sony_nc_kbd_backlight_setup(struct platform_device *pd, - unsigned int handle) +static int sony_nc_kbd_backlight_setup(struct platform_device *pd) { int result; - int ret = 0; - - /* verify the kbd backlight presence, these handles are not used for - * keyboard backlight only - */ - ret = sony_call_snc_handle(handle, handle == 0x0137 ? 0x0B00 : 0x0100, - &result); - if (ret) - return ret; - if ((handle == 0x0137 && !(result & 0x02)) || - !(result & 0x01)) { - dprintk("no backlight keyboard found\n"); + if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result)) + return 0; + if (!(result & 0x02)) return 0; - } - kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL); - if (!kbdbl_ctl) + kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL); + if (!kbdbl_handle) return -ENOMEM; - kbdbl_ctl->handle = handle; - if (handle == 0x0137) - kbdbl_ctl->base = 0x0C00; - else - kbdbl_ctl->base = 0x4000; - - sysfs_attr_init(&kbdbl_ctl->mode_attr.attr); - kbdbl_ctl->mode_attr.attr.name = "kbd_backlight"; - kbdbl_ctl->mode_attr.attr.mode = S_IRUGO | S_IWUSR; - kbdbl_ctl->mode_attr.show = sony_nc_kbd_backlight_mode_show; - kbdbl_ctl->mode_attr.store = sony_nc_kbd_backlight_mode_store; + sysfs_attr_init(&kbdbl_handle->mode_attr.attr); + kbdbl_handle->mode_attr.attr.name = "kbd_backlight"; + kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR; + kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show; + kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store; - sysfs_attr_init(&kbdbl_ctl->timeout_attr.attr); - kbdbl_ctl->timeout_attr.attr.name = "kbd_backlight_timeout"; - kbdbl_ctl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR; - kbdbl_ctl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; - kbdbl_ctl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; + sysfs_attr_init(&kbdbl_handle->timeout_attr.attr); + kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout"; + kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR; + kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show; + kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store; - ret = device_create_file(&pd->dev, &kbdbl_ctl->mode_attr); - if (ret) + if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr)) goto outkzalloc; - ret = device_create_file(&pd->dev, &kbdbl_ctl->timeout_attr); - if (ret) + if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr)) goto outmode; __sony_nc_kbd_backlight_mode_set(kbd_backlight); @@ -1819,711 +1520,126 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd, return 0; outmode: - device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); + device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); outkzalloc: - kfree(kbdbl_ctl); - kbdbl_ctl = NULL; - return ret; + kfree(kbdbl_handle); + kbdbl_handle = NULL; + return -1; } -static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd) +static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) { - if (kbdbl_ctl) { + if (kbdbl_handle) { int result; - device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); - device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr); + device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); + device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr); /* restore the default hw behaviour */ - sony_call_snc_handle(kbdbl_ctl->handle, - kbdbl_ctl->base | 0x10000, &result); - sony_call_snc_handle(kbdbl_ctl->handle, - kbdbl_ctl->base + 0x200, &result); + sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result); + sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result); - kfree(kbdbl_ctl); - kbdbl_ctl = NULL; + kfree(kbdbl_handle); } + return 0; } static void sony_nc_kbd_backlight_resume(void) { int ignore = 0; - if (!kbdbl_ctl) + if (!kbdbl_handle) return; - if (kbdbl_ctl->mode == 0) - sony_call_snc_handle(kbdbl_ctl->handle, kbdbl_ctl->base, - &ignore); + if (kbdbl_handle->mode == 0) + sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore); - if (kbdbl_ctl->timeout != 0) - sony_call_snc_handle(kbdbl_ctl->handle, - (kbdbl_ctl->base + 0x200) | - (kbdbl_ctl->timeout << 0x10), &ignore); + if (kbdbl_handle->timeout != 0) + sony_call_snc_handle(KBDBL_HANDLER, + (kbdbl_handle->timeout << 0x10) | SET_TIMEOUT, + &ignore); } -struct battery_care_control { - struct device_attribute attrs[2]; - unsigned int handle; -}; -static struct battery_care_control *bcare_ctl; - -static ssize_t sony_nc_battery_care_limit_store(struct device *dev, - struct device_attribute *attr, - const char *buffer, size_t count) +static void sony_nc_backlight_ng_read_limits(int handle, + struct sony_backlight_props *props) { - unsigned int result, cmd; - unsigned long value; - - if (count > 31) - return -EINVAL; + int offset; + acpi_status status; + u8 brlvl, i; + u8 min = 0xff, max = 0x00; + struct acpi_object_list params; + union acpi_object in_obj; + union acpi_object *lvl_enum; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; + props->handle = handle; + props->offset = 0; + props->maxlvl = 0xff; - /* limit values (2 bits): - * 00 - none - * 01 - 80% - * 10 - 50% - * 11 - 100% - * - * bit 0: 0 disable BCL, 1 enable BCL - * bit 1: 1 tell to store the battery limit (see bits 6,7) too - * bits 2,3: reserved - * bits 4,5: store the limit into the EC - * bits 6,7: store the limit into the battery - */ + offset = sony_find_snc_handle(handle); + if (offset < 0) + return; - /* - * handle 0x0115 should allow storing on battery too; - * handle 0x0136 same as 0x0115 + health status; - * handle 0x013f, same as 0x0136 but no storing on the battery - * - * Store only inside the EC for now, regardless the handle number + /* try to read the boundaries from ACPI tables, if we fail the above + * defaults should be reasonable */ - if (value == 0) - /* disable limits */ - cmd = 0x0; + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = offset; + status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, + &buffer); + if (ACPI_FAILURE(status)) + return; - else if (value <= 50) - cmd = 0x21; + lvl_enum = (union acpi_object *) buffer.pointer; + if (!lvl_enum) { + pr_err("No SN06 return object."); + return; + } + if (lvl_enum->type != ACPI_TYPE_BUFFER) { + pr_err("Invalid SN06 return object 0x%.2x\n", + lvl_enum->type); + goto out_invalid; + } - else if (value <= 80) - cmd = 0x11; + /* the buffer lists brightness levels available, brightness levels are + * from 0 to 8 in the array, other values are used by ALS control. + */ + for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) { - else if (value <= 100) - cmd = 0x31; + brlvl = *(lvl_enum->buffer.pointer + i); + dprintk("Brightness level: %d\n", brlvl); - else - return -EINVAL; + if (!brlvl) + break; - if (sony_call_snc_handle(bcare_ctl->handle, (cmd << 0x10) | 0x0100, - &result)) - return -EIO; + if (brlvl > max) + max = brlvl; + if (brlvl < min) + min = brlvl; + } + props->offset = min; + props->maxlvl = max; + dprintk("Brightness levels: min=%d max=%d\n", props->offset, + props->maxlvl); - return count; +out_invalid: + kfree(buffer.pointer); + return; } -static ssize_t sony_nc_battery_care_limit_show(struct device *dev, - struct device_attribute *attr, char *buffer) +static void sony_nc_backlight_setup(void) { - unsigned int result, status; + acpi_handle unused; + int max_brightness = 0; + const struct backlight_ops *ops = NULL; + struct backlight_properties props; - if (sony_call_snc_handle(bcare_ctl->handle, 0x0000, &result)) - return -EIO; - - status = (result & 0x01) ? ((result & 0x30) >> 0x04) : 0; - switch (status) { - case 1: - status = 80; - break; - case 2: - status = 50; - break; - case 3: - status = 100; - break; - default: - status = 0; - break; - } - - return snprintf(buffer, PAGE_SIZE, "%d\n", status); -} - -static ssize_t sony_nc_battery_care_health_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - ssize_t count = 0; - unsigned int health; - - if (sony_call_snc_handle(bcare_ctl->handle, 0x0200, &health)) - return -EIO; - - count = snprintf(buffer, PAGE_SIZE, "%d\n", health & 0xff); - - return count; -} - -static int sony_nc_battery_care_setup(struct platform_device *pd, - unsigned int handle) -{ - int ret = 0; - - bcare_ctl = kzalloc(sizeof(struct battery_care_control), GFP_KERNEL); - if (!bcare_ctl) - return -ENOMEM; - - bcare_ctl->handle = handle; - - sysfs_attr_init(&bcare_ctl->attrs[0].attr); - bcare_ctl->attrs[0].attr.name = "battery_care_limiter"; - bcare_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR; - bcare_ctl->attrs[0].show = sony_nc_battery_care_limit_show; - bcare_ctl->attrs[0].store = sony_nc_battery_care_limit_store; - - ret = device_create_file(&pd->dev, &bcare_ctl->attrs[0]); - if (ret) - goto outkzalloc; - - /* 0x0115 is for models with no health reporting capability */ - if (handle == 0x0115) - return 0; - - sysfs_attr_init(&bcare_ctl->attrs[1].attr); - bcare_ctl->attrs[1].attr.name = "battery_care_health"; - bcare_ctl->attrs[1].attr.mode = S_IRUGO; - bcare_ctl->attrs[1].show = sony_nc_battery_care_health_show; - - ret = device_create_file(&pd->dev, &bcare_ctl->attrs[1]); - if (ret) - goto outlimiter; - - return 0; - -outlimiter: - device_remove_file(&pd->dev, &bcare_ctl->attrs[0]); - -outkzalloc: - kfree(bcare_ctl); - bcare_ctl = NULL; - - return ret; -} - -static void sony_nc_battery_care_cleanup(struct platform_device *pd) -{ - if (bcare_ctl) { - device_remove_file(&pd->dev, &bcare_ctl->attrs[0]); - if (bcare_ctl->handle != 0x0115) - device_remove_file(&pd->dev, &bcare_ctl->attrs[1]); - - kfree(bcare_ctl); - bcare_ctl = NULL; - } -} - -struct snc_thermal_ctrl { - unsigned int mode; - unsigned int profiles; - struct device_attribute mode_attr; - struct device_attribute profiles_attr; -}; -static struct snc_thermal_ctrl *th_handle; - -#define THM_PROFILE_MAX 3 -static const char * const snc_thermal_profiles[] = { - "balanced", - "silent", - "performance" -}; - -static int sony_nc_thermal_mode_set(unsigned short mode) -{ - unsigned int result; - - /* the thermal profile seems to be a two bit bitmask: - * lsb -> silent - * msb -> performance - * no bit set is the normal operation and is always valid - * Some vaio models only have "balanced" and "performance" - */ - if ((mode && !(th_handle->profiles & mode)) || mode >= THM_PROFILE_MAX) - return -EINVAL; - - if (sony_call_snc_handle(0x0122, mode << 0x10 | 0x0200, &result)) - return -EIO; - - th_handle->mode = mode; - - return 0; -} - -static int sony_nc_thermal_mode_get(void) -{ - unsigned int result; - - if (sony_call_snc_handle(0x0122, 0x0100, &result)) - return -EIO; - - return result & 0xff; -} - -static ssize_t sony_nc_thermal_profiles_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - short cnt; - size_t idx = 0; - - for (cnt = 0; cnt < THM_PROFILE_MAX; cnt++) { - if (!cnt || (th_handle->profiles & cnt)) - idx += snprintf(buffer + idx, PAGE_SIZE - idx, "%s ", - snc_thermal_profiles[cnt]); - } - idx += snprintf(buffer + idx, PAGE_SIZE - idx, "\n"); - - return idx; -} - -static ssize_t sony_nc_thermal_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buffer, size_t count) -{ - unsigned short cmd; - size_t len = count; - - if (count == 0) - return -EINVAL; - - /* skip the newline if present */ - if (buffer[len - 1] == '\n') - len--; - - for (cmd = 0; cmd < THM_PROFILE_MAX; cmd++) - if (strncmp(buffer, snc_thermal_profiles[cmd], len) == 0) - break; - - if (sony_nc_thermal_mode_set(cmd)) - return -EIO; - - return count; -} - -static ssize_t sony_nc_thermal_mode_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - ssize_t count = 0; - unsigned int mode = sony_nc_thermal_mode_get(); - - if (mode < 0) - return mode; - - count = snprintf(buffer, PAGE_SIZE, "%s\n", snc_thermal_profiles[mode]); - - return count; -} - -static int sony_nc_thermal_setup(struct platform_device *pd) -{ - int ret = 0; - th_handle = kzalloc(sizeof(struct snc_thermal_ctrl), GFP_KERNEL); - if (!th_handle) - return -ENOMEM; - - ret = sony_call_snc_handle(0x0122, 0x0000, &th_handle->profiles); - if (ret) { - pr_warn("couldn't to read the thermal profiles\n"); - goto outkzalloc; - } - - ret = sony_nc_thermal_mode_get(); - if (ret < 0) { - pr_warn("couldn't to read the current thermal profile"); - goto outkzalloc; - } - th_handle->mode = ret; - - sysfs_attr_init(&th_handle->profiles_attr.attr); - th_handle->profiles_attr.attr.name = "thermal_profiles"; - th_handle->profiles_attr.attr.mode = S_IRUGO; - th_handle->profiles_attr.show = sony_nc_thermal_profiles_show; - - sysfs_attr_init(&th_handle->mode_attr.attr); - th_handle->mode_attr.attr.name = "thermal_control"; - th_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR; - th_handle->mode_attr.show = sony_nc_thermal_mode_show; - th_handle->mode_attr.store = sony_nc_thermal_mode_store; - - ret = device_create_file(&pd->dev, &th_handle->profiles_attr); - if (ret) - goto outkzalloc; - - ret = device_create_file(&pd->dev, &th_handle->mode_attr); - if (ret) - goto outprofiles; - - return 0; - -outprofiles: - device_remove_file(&pd->dev, &th_handle->profiles_attr); -outkzalloc: - kfree(th_handle); - th_handle = NULL; - return ret; -} - -static void sony_nc_thermal_cleanup(struct platform_device *pd) -{ - if (th_handle) { - device_remove_file(&pd->dev, &th_handle->profiles_attr); - device_remove_file(&pd->dev, &th_handle->mode_attr); - kfree(th_handle); - th_handle = NULL; - } -} - -static void sony_nc_thermal_resume(void) -{ - unsigned int status = sony_nc_thermal_mode_get(); - - if (status != th_handle->mode) - sony_nc_thermal_mode_set(th_handle->mode); -} - -/* resume on LID open */ -struct snc_lid_resume_control { - struct device_attribute attrs[3]; - unsigned int status; -}; -static struct snc_lid_resume_control *lid_ctl; - -static ssize_t sony_nc_lid_resume_store(struct device *dev, - struct device_attribute *attr, - const char *buffer, size_t count) -{ - unsigned int result, pos; - unsigned long value; - if (count > 31) - return -EINVAL; - - if (kstrtoul(buffer, 10, &value) || value > 1) - return -EINVAL; - - /* the value we have to write to SNC is a bitmask: - * +--------------+ - * | S3 | S4 | S5 | - * +--------------+ - * 2 1 0 - */ - if (strcmp(attr->attr.name, "lid_resume_S3") == 0) - pos = 2; - else if (strcmp(attr->attr.name, "lid_resume_S4") == 0) - pos = 1; - else if (strcmp(attr->attr.name, "lid_resume_S5") == 0) - pos = 0; - else - return -EINVAL; - - if (value) - value = lid_ctl->status | (1 << pos); - else - value = lid_ctl->status & ~(1 << pos); - - if (sony_call_snc_handle(0x0119, value << 0x10 | 0x0100, &result)) - return -EIO; - - lid_ctl->status = value; - - return count; -} - -static ssize_t sony_nc_lid_resume_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - unsigned int pos; - - if (strcmp(attr->attr.name, "lid_resume_S3") == 0) - pos = 2; - else if (strcmp(attr->attr.name, "lid_resume_S4") == 0) - pos = 1; - else if (strcmp(attr->attr.name, "lid_resume_S5") == 0) - pos = 0; - else - return -EINVAL; - - return snprintf(buffer, PAGE_SIZE, "%d\n", - (lid_ctl->status >> pos) & 0x01); -} - -static int sony_nc_lid_resume_setup(struct platform_device *pd) -{ - unsigned int result; - int i; - - if (sony_call_snc_handle(0x0119, 0x0000, &result)) - return -EIO; - - lid_ctl = kzalloc(sizeof(struct snc_lid_resume_control), GFP_KERNEL); - if (!lid_ctl) - return -ENOMEM; - - lid_ctl->status = result & 0x7; - - sysfs_attr_init(&lid_ctl->attrs[0].attr); - lid_ctl->attrs[0].attr.name = "lid_resume_S3"; - lid_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR; - lid_ctl->attrs[0].show = sony_nc_lid_resume_show; - lid_ctl->attrs[0].store = sony_nc_lid_resume_store; - - sysfs_attr_init(&lid_ctl->attrs[1].attr); - lid_ctl->attrs[1].attr.name = "lid_resume_S4"; - lid_ctl->attrs[1].attr.mode = S_IRUGO | S_IWUSR; - lid_ctl->attrs[1].show = sony_nc_lid_resume_show; - lid_ctl->attrs[1].store = sony_nc_lid_resume_store; - - sysfs_attr_init(&lid_ctl->attrs[2].attr); - lid_ctl->attrs[2].attr.name = "lid_resume_S5"; - lid_ctl->attrs[2].attr.mode = S_IRUGO | S_IWUSR; - lid_ctl->attrs[2].show = sony_nc_lid_resume_show; - lid_ctl->attrs[2].store = sony_nc_lid_resume_store; - - for (i = 0; i < 3; i++) { - result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); - if (result) - goto liderror; - } - - return 0; - -liderror: - for (; i > 0; i--) - device_remove_file(&pd->dev, &lid_ctl->attrs[i]); - - kfree(lid_ctl); - lid_ctl = NULL; - - return result; -} - -static void sony_nc_lid_resume_cleanup(struct platform_device *pd) -{ - int i; - - if (lid_ctl) { - for (i = 0; i < 3; i++) - device_remove_file(&pd->dev, &lid_ctl->attrs[i]); - - kfree(lid_ctl); - lid_ctl = NULL; - } -} - -/* High speed charging function */ -static struct device_attribute *hsc_handle; - -static ssize_t sony_nc_highspeed_charging_store(struct device *dev, - struct device_attribute *attr, - const char *buffer, size_t count) -{ - unsigned int result; - unsigned long value; - - if (count > 31) - return -EINVAL; - - if (kstrtoul(buffer, 10, &value) || value > 1) - return -EINVAL; - - if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result)) - return -EIO; - - return count; -} - -static ssize_t sony_nc_highspeed_charging_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - unsigned int result; - - if (sony_call_snc_handle(0x0131, 0x0100, &result)) - return -EIO; - - return snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01); -} - -static int sony_nc_highspeed_charging_setup(struct platform_device *pd) -{ - unsigned int result; - - if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) { - /* some models advertise the handle but have no implementation - * for it - */ - pr_info("No High Speed Charging capability found\n"); - return 0; - } - - hsc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL); - if (!hsc_handle) - return -ENOMEM; - - sysfs_attr_init(&hsc_handle->attr); - hsc_handle->attr.name = "battery_highspeed_charging"; - hsc_handle->attr.mode = S_IRUGO | S_IWUSR; - hsc_handle->show = sony_nc_highspeed_charging_show; - hsc_handle->store = sony_nc_highspeed_charging_store; - - result = device_create_file(&pd->dev, hsc_handle); - if (result) { - kfree(hsc_handle); - hsc_handle = NULL; - return result; - } - - return 0; -} - -static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd) -{ - if (hsc_handle) { - device_remove_file(&pd->dev, hsc_handle); - kfree(hsc_handle); - hsc_handle = NULL; - } -} - -/* Touchpad enable/disable */ -struct touchpad_control { - struct device_attribute attr; - int handle; -}; -static struct touchpad_control *tp_ctl; - -static ssize_t sony_nc_touchpad_store(struct device *dev, - struct device_attribute *attr, const char *buffer, size_t count) -{ - unsigned int result; - unsigned long value; - - if (count > 31) - return -EINVAL; - - if (kstrtoul(buffer, 10, &value) || value > 1) - return -EINVAL; - - /* sysfs: 0 disabled, 1 enabled - * EC: 0 enabled, 1 disabled - */ - if (sony_call_snc_handle(tp_ctl->handle, - (!value << 0x10) | 0x100, &result)) - return -EIO; - - return count; -} - -static ssize_t sony_nc_touchpad_show(struct device *dev, - struct device_attribute *attr, char *buffer) -{ - unsigned int result; - - if (sony_call_snc_handle(tp_ctl->handle, 0x000, &result)) - return -EINVAL; - - return snprintf(buffer, PAGE_SIZE, "%d\n", !(result & 0x01)); -} - -static int sony_nc_touchpad_setup(struct platform_device *pd, - unsigned int handle) -{ - int ret = 0; - - tp_ctl = kzalloc(sizeof(struct touchpad_control), GFP_KERNEL); - if (!tp_ctl) - return -ENOMEM; - - tp_ctl->handle = handle; - - sysfs_attr_init(&tp_ctl->attr.attr); - tp_ctl->attr.attr.name = "touchpad"; - tp_ctl->attr.attr.mode = S_IRUGO | S_IWUSR; - tp_ctl->attr.show = sony_nc_touchpad_show; - tp_ctl->attr.store = sony_nc_touchpad_store; - - ret = device_create_file(&pd->dev, &tp_ctl->attr); - if (ret) { - kfree(tp_ctl); - tp_ctl = NULL; - } - - return ret; -} - -static void sony_nc_touchpad_cleanup(struct platform_device *pd) -{ - if (tp_ctl) { - device_remove_file(&pd->dev, &tp_ctl->attr); - kfree(tp_ctl); - tp_ctl = NULL; - } -} - -static void sony_nc_backlight_ng_read_limits(int handle, - struct sony_backlight_props *props) -{ - u64 offset; - int i; - u8 min = 0xff, max = 0x00; - unsigned char buffer[32] = { 0 }; - - props->handle = handle; - props->offset = 0; - props->maxlvl = 0xff; - - offset = sony_find_snc_handle(handle); - if (offset < 0) - return; - - /* try to read the boundaries from ACPI tables, if we fail the above - * defaults should be reasonable - */ - i = sony_nc_buffer_call(sony_nc_acpi_handle, "SN06", &offset, buffer, - 32); - if (i < 0) - return; - - /* the buffer lists brightness levels available, brightness levels are - * from position 0 to 8 in the array, other values are used by ALS - * control. - */ - for (i = 0; i < 9 && i < ARRAY_SIZE(buffer); i++) { - - dprintk("Brightness level: %d\n", buffer[i]); - - if (!buffer[i]) - break; - - if (buffer[i] > max) - max = buffer[i]; - if (buffer[i] < min) - min = buffer[i]; - } - props->offset = min; - props->maxlvl = max; - dprintk("Brightness levels: min=%d max=%d\n", props->offset, - props->maxlvl); -} - -static void sony_nc_backlight_setup(void) -{ - acpi_handle unused; - int max_brightness = 0; - const struct backlight_ops *ops = NULL; - struct backlight_properties props; - - if (sony_find_snc_handle(0x12f) != -1) { - ops = &sony_backlight_ng_ops; - sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props); - max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + if (sony_find_snc_handle(0x12f) != -1) { + ops = &sony_backlight_ng_ops; + sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props); + max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; } else if (sony_find_snc_handle(0x137) != -1) { ops = &sony_backlight_ng_ops; @@ -2599,25 +1715,28 @@ static int sony_nc_add(struct acpi_device *device) if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", &handle))) { - int arg = 1; - if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL)) + if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) dprintk("ECON Method failed\n"); } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); - /* retrieve the available handles */ result = sony_nc_handles_setup(sony_pf_device); - if (!result) - sony_nc_function_setup(device, sony_pf_device); + if (result) + goto outpresent; + result = sony_nc_kbd_backlight_setup(sony_pf_device); + if (result) + goto outsnc; + sony_nc_function_setup(device); + sony_nc_rfkill_setup(device); } /* setup input devices and helper fifo */ result = sony_laptop_setup_input(device); if (result) { pr_err("Unable to create input devices\n"); - goto outsnc; + goto outkbdbacklight; } if (acpi_video_backlight_support()) { @@ -2675,8 +1794,10 @@ static int sony_nc_add(struct acpi_device *device) sony_laptop_remove_input(); + outkbdbacklight: + sony_nc_kbd_backlight_cleanup(sony_pf_device); + outsnc: - sony_nc_function_cleanup(sony_pf_device); sony_nc_handles_cleanup(sony_pf_device); outpresent: @@ -2699,10 +1820,11 @@ static int sony_nc_remove(struct acpi_device *device, int type) device_remove_file(&sony_pf_device->dev, &item->devattr); } - sony_nc_function_cleanup(sony_pf_device); + sony_nc_kbd_backlight_cleanup(sony_pf_device); sony_nc_handles_cleanup(sony_pf_device); sony_pf_remove(); sony_laptop_remove_input(); + sony_nc_rfkill_cleanup(); dprintk(SONY_NC_DRIVER_NAME " removed.\n"); return 0; @@ -3315,9 +2437,7 @@ static ssize_t sony_pic_wwanpower_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; - + value = simple_strtoul(buffer, NULL, 10); mutex_lock(&spic_dev.lock); __sony_pic_set_wwanpower(value); mutex_unlock(&spic_dev.lock); @@ -3354,9 +2474,7 @@ static ssize_t sony_pic_bluetoothpower_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; - + value = simple_strtoul(buffer, NULL, 10); mutex_lock(&spic_dev.lock); __sony_pic_set_bluetoothpower(value); mutex_unlock(&spic_dev.lock); @@ -3395,9 +2513,7 @@ static ssize_t sony_pic_fanspeed_store(struct device *dev, if (count > 31) return -EINVAL; - if (kstrtoul(buffer, 10, &value)) - return -EINVAL; - + value = simple_strtoul(buffer, NULL, 10); if (sony_pic_set_fanspeed(value)) return -EIO; @@ -3555,8 +2671,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, ret = -EIO; break; } - if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL, - &value)) { + if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value)) { ret = -EIO; break; } @@ -3573,9 +2688,8 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, ret = -EFAULT; break; } - value = (val8 >> 5) + 1; - if (sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &value, - NULL)) { + if (acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", + (val8 >> 5) + 1, NULL)) { ret = -EIO; break; } diff --git a/trunk/drivers/platform/x86/thinkpad_acpi.c b/trunk/drivers/platform/x86/thinkpad_acpi.c index 8b5610d88418..d68c0002f4a2 100644 --- a/trunk/drivers/platform/x86/thinkpad_acpi.c +++ b/trunk/drivers/platform/x86/thinkpad_acpi.c @@ -3402,7 +3402,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) /* Do not issue duplicate brightness change events to * userspace. tpacpi_detect_brightness_capabilities() must have * been called before this point */ - if (acpi_video_backlight_support()) { + if (tp_features.bright_acpimode && acpi_video_backlight_support()) { pr_info("This ThinkPad has standard ACPI backlight " "brightness control, supported by the ACPI " "video driver\n"); diff --git a/trunk/drivers/platform/x86/toshiba_acpi.c b/trunk/drivers/platform/x86/toshiba_acpi.c index dab10f6edcd4..57787d87d9a4 100644 --- a/trunk/drivers/platform/x86/toshiba_acpi.c +++ b/trunk/drivers/platform/x86/toshiba_acpi.c @@ -95,7 +95,6 @@ MODULE_LICENSE("GPL"); /* registers */ #define HCI_FAN 0x0004 -#define HCI_TR_BACKLIGHT 0x0005 #define HCI_SYSTEM_EVENT 0x0016 #define HCI_VIDEO_OUT 0x001c #define HCI_HOTKEY_EVENT 0x001e @@ -135,7 +134,6 @@ struct toshiba_acpi_dev { unsigned int system_event_supported:1; unsigned int ntfy_supported:1; unsigned int info_supported:1; - unsigned int tr_backlight_supported:1; struct mutex mutex; }; @@ -480,70 +478,34 @@ static const struct rfkill_ops toshiba_rfk_ops = { .poll = bt_rfkill_poll, }; -static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled) -{ - u32 hci_result; - u32 status; - - hci_read1(dev, HCI_TR_BACKLIGHT, &status, &hci_result); - *enabled = !status; - return hci_result == HCI_SUCCESS ? 0 : -EIO; -} - -static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable) -{ - u32 hci_result; - u32 value = !enable; - - hci_write1(dev, HCI_TR_BACKLIGHT, value, &hci_result); - return hci_result == HCI_SUCCESS ? 0 : -EIO; -} - static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ; -static int __get_lcd_brightness(struct toshiba_acpi_dev *dev) +static int get_lcd(struct backlight_device *bd) { + struct toshiba_acpi_dev *dev = bl_get_data(bd); u32 hci_result; u32 value; - int brightness = 0; - - if (dev->tr_backlight_supported) { - bool enabled; - int ret = get_tr_backlight_status(dev, &enabled); - if (ret) - return ret; - if (enabled) - return 0; - brightness++; - } hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result); if (hci_result == HCI_SUCCESS) - return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT); + return (value >> HCI_LCD_BRIGHTNESS_SHIFT); return -EIO; } -static int get_lcd_brightness(struct backlight_device *bd) -{ - struct toshiba_acpi_dev *dev = bl_get_data(bd); - return __get_lcd_brightness(dev); -} - static int lcd_proc_show(struct seq_file *m, void *v) { struct toshiba_acpi_dev *dev = m->private; int value; - int levels; if (!dev->backlight_dev) return -ENODEV; - levels = dev->backlight_dev->props.max_brightness + 1; - value = get_lcd_brightness(dev->backlight_dev); + value = get_lcd(dev->backlight_dev); if (value >= 0) { seq_printf(m, "brightness: %d\n", value); - seq_printf(m, "brightness_levels: %d\n", levels); + seq_printf(m, "brightness_levels: %d\n", + HCI_LCD_BRIGHTNESS_LEVELS); return 0; } @@ -556,19 +518,10 @@ static int lcd_proc_open(struct inode *inode, struct file *file) return single_open(file, lcd_proc_show, PDE(inode)->data); } -static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) +static int set_lcd(struct toshiba_acpi_dev *dev, int value) { u32 hci_result; - if (dev->tr_backlight_supported) { - bool enable = !value; - int ret = set_tr_backlight_status(dev, enable); - if (ret) - return ret; - if (value) - value--; - } - value = value << HCI_LCD_BRIGHTNESS_SHIFT; hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); return hci_result == HCI_SUCCESS ? 0 : -EIO; @@ -577,7 +530,7 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) static int set_lcd_status(struct backlight_device *bd) { struct toshiba_acpi_dev *dev = bl_get_data(bd); - return set_lcd_brightness(dev, bd->props.brightness); + return set_lcd(dev, bd->props.brightness); } static ssize_t lcd_proc_write(struct file *file, const char __user *buf, @@ -588,7 +541,6 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf, size_t len; int value; int ret; - int levels = dev->backlight_dev->props.max_brightness + 1; len = min(count, sizeof(cmd) - 1); if (copy_from_user(cmd, buf, len)) @@ -596,8 +548,8 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf, cmd[len] = '\0'; if (sscanf(cmd, " brightness : %i", &value) == 1 && - value >= 0 && value < levels) { - ret = set_lcd_brightness(dev, value); + value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { + ret = set_lcd(dev, value); if (ret == 0) ret = count; } else { @@ -908,9 +860,8 @@ static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev) } static const struct backlight_ops toshiba_backlight_data = { - .options = BL_CORE_SUSPENDRESUME, - .get_brightness = get_lcd_brightness, - .update_status = set_lcd_status, + .get_brightness = get_lcd, + .update_status = set_lcd_status, }; static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str, @@ -1069,56 +1020,6 @@ static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) return error; } -static int __devinit toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev) -{ - struct backlight_properties props; - int brightness; - int ret; - bool enabled; - - /* - * Some machines don't support the backlight methods at all, and - * others support it read-only. Either of these is pretty useless, - * so only register the backlight device if the backlight method - * supports both reads and writes. - */ - brightness = __get_lcd_brightness(dev); - if (brightness < 0) - return 0; - ret = set_lcd_brightness(dev, brightness); - if (ret) { - pr_debug("Backlight method is read-only, disabling backlight support\n"); - return 0; - } - - /* Determine whether or not BIOS supports transflective backlight */ - ret = get_tr_backlight_status(dev, &enabled); - dev->tr_backlight_supported = !ret; - - memset(&props, 0, sizeof(props)); - props.type = BACKLIGHT_PLATFORM; - props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; - - /* adding an extra level and having 0 change to transflective mode */ - if (dev->tr_backlight_supported) - props.max_brightness++; - - dev->backlight_dev = backlight_device_register("toshiba", - &dev->acpi_dev->dev, - dev, - &toshiba_backlight_data, - &props); - if (IS_ERR(dev->backlight_dev)) { - ret = PTR_ERR(dev->backlight_dev); - pr_err("Could not register toshiba backlight device\n"); - dev->backlight_dev = NULL; - return ret; - } - - dev->backlight_dev->props.brightness = brightness; - return 0; -} - static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type) { struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); @@ -1177,6 +1078,7 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) u32 dummy; bool bt_present; int ret = 0; + struct backlight_properties props; if (toshiba_acpi) return -EBUSY; @@ -1202,9 +1104,22 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) mutex_init(&dev->mutex); - ret = toshiba_acpi_setup_backlight(dev); - if (ret) + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_PLATFORM; + props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; + dev->backlight_dev = backlight_device_register("toshiba", + &acpi_dev->dev, + dev, + &toshiba_backlight_data, + &props); + if (IS_ERR(dev->backlight_dev)) { + ret = PTR_ERR(dev->backlight_dev); + + pr_err("Could not register toshiba backlight device\n"); + dev->backlight_dev = NULL; goto error; + } + dev->backlight_dev->props.brightness = get_lcd(dev->backlight_dev); /* Register rfkill switch for Bluetooth */ if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) { diff --git a/trunk/drivers/platform/x86/xo1-rfkill.c b/trunk/drivers/platform/x86/xo1-rfkill.c index b57ad8641480..41781ed8301c 100644 --- a/trunk/drivers/platform/x86/xo1-rfkill.c +++ b/trunk/drivers/platform/x86/xo1-rfkill.c @@ -15,26 +15,15 @@ #include -static bool card_blocked; - static int rfkill_set_block(void *data, bool blocked) { unsigned char cmd; - int r; - - if (blocked == card_blocked) - return 0; - if (blocked) cmd = EC_WLAN_ENTER_RESET; else cmd = EC_WLAN_LEAVE_RESET; - r = olpc_ec_cmd(cmd, NULL, 0, NULL, 0); - if (r == 0) - card_blocked = blocked; - - return r; + return olpc_ec_cmd(cmd, NULL, 0, NULL, 0); } static const struct rfkill_ops rfkill_ops = { diff --git a/trunk/drivers/power/Kconfig b/trunk/drivers/power/Kconfig index e3a3b4956f08..99dc29f2f2f2 100644 --- a/trunk/drivers/power/Kconfig +++ b/trunk/drivers/power/Kconfig @@ -1,5 +1,5 @@ menuconfig POWER_SUPPLY - bool "Power supply class support" + tristate "Power supply class support" help Say Y here to enable power supply class support. This allows power supply (batteries, AC, USB) monitoring by userspace @@ -77,7 +77,7 @@ config BATTERY_DS2780 Say Y here to enable support for batteries with ds2780 chip. config BATTERY_DS2781 - tristate "DS2781 battery driver" + tristate "2781 battery driver" depends on HAS_IOMEM select W1 select W1_SLAVE_DS2781 @@ -181,15 +181,14 @@ config BATTERY_MAX17040 to operate with a single lithium cell config BATTERY_MAX17042 - tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge" + tristate "Maxim MAX17042/8997/8966 Fuel Gauge" depends on I2C help MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries in handheld and portable equipment. The MAX17042 is configured to operate with a single lithium cell. MAX8997 and MAX8966 are multi-function devices that include fuel gauages that are compatible - with MAX17042. This driver also supports max17047/50 chips which are - improved version of max17042. + with MAX17042. config BATTERY_Z2 tristate "Z2 battery driver" @@ -292,7 +291,6 @@ config CHARGER_MAX8998 config CHARGER_SMB347 tristate "Summit Microelectronics SMB347 Battery Charger" depends on I2C - select REGMAP_I2C help Say Y to include support for Summit Microelectronics SMB347 Battery Charger. diff --git a/trunk/drivers/power/ab8500_btemp.c b/trunk/drivers/power/ab8500_btemp.c index bba3ccac72fe..d8bb99394ac0 100644 --- a/trunk/drivers/power/ab8500_btemp.c +++ b/trunk/drivers/power/ab8500_btemp.c @@ -964,15 +964,10 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) { int irq, i, ret = 0; u8 val; - struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; - struct ab8500_btemp *di; - - if (!plat_data) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; - } + struct abx500_bm_plat_data *plat_data; - di = kzalloc(sizeof(*di), GFP_KERNEL); + struct ab8500_btemp *di = + kzalloc(sizeof(struct ab8500_btemp), GFP_KERNEL); if (!di) return -ENOMEM; @@ -982,6 +977,7 @@ static int __devinit ab8500_btemp_probe(struct platform_device *pdev) di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); /* get btemp specific platform data */ + plat_data = pdev->dev.platform_data; di->pdata = plat_data->btemp; if (!di->pdata) { dev_err(di->dev, "no btemp platform data supplied\n"); diff --git a/trunk/drivers/power/ab8500_charger.c b/trunk/drivers/power/ab8500_charger.c index d2303d0b7c75..e2b4accbec88 100644 --- a/trunk/drivers/power/ab8500_charger.c +++ b/trunk/drivers/power/ab8500_charger.c @@ -2534,15 +2534,10 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev) static int __devinit ab8500_charger_probe(struct platform_device *pdev) { int irq, i, charger_status, ret = 0; - struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; - struct ab8500_charger *di; - - if (!plat_data) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; - } + struct abx500_bm_plat_data *plat_data; - di = kzalloc(sizeof(*di), GFP_KERNEL); + struct ab8500_charger *di = + kzalloc(sizeof(struct ab8500_charger), GFP_KERNEL); if (!di) return -ENOMEM; @@ -2555,7 +2550,9 @@ static int __devinit ab8500_charger_probe(struct platform_device *pdev) spin_lock_init(&di->usb_state.usb_lock); /* get charger specific platform data */ + plat_data = pdev->dev.platform_data; di->pdata = plat_data->charger; + if (!di->pdata) { dev_err(di->dev, "no charger platform data supplied\n"); ret = -EINVAL; diff --git a/trunk/drivers/power/ab8500_fg.c b/trunk/drivers/power/ab8500_fg.c index bf022255994c..c22f2f05657e 100644 --- a/trunk/drivers/power/ab8500_fg.c +++ b/trunk/drivers/power/ab8500_fg.c @@ -2446,15 +2446,10 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) { int i, irq; int ret = 0; - struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; - struct ab8500_fg *di; - - if (!plat_data) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; - } + struct abx500_bm_plat_data *plat_data; - di = kzalloc(sizeof(*di), GFP_KERNEL); + struct ab8500_fg *di = + kzalloc(sizeof(struct ab8500_fg), GFP_KERNEL); if (!di) return -ENOMEM; @@ -2466,6 +2461,7 @@ static int __devinit ab8500_fg_probe(struct platform_device *pdev) di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); /* get fg specific platform data */ + plat_data = pdev->dev.platform_data; di->pdata = plat_data->fg; if (!di->pdata) { dev_err(di->dev, "no fg platform data supplied\n"); diff --git a/trunk/drivers/power/charger-manager.c b/trunk/drivers/power/charger-manager.c index 86935ec18954..9eca9f1ff0ea 100644 --- a/trunk/drivers/power/charger-manager.c +++ b/trunk/drivers/power/charger-manager.c @@ -23,16 +23,6 @@ #include #include -static const char * const default_event_names[] = { - [CM_EVENT_UNKNOWN] = "Unknown", - [CM_EVENT_BATT_FULL] = "Battery Full", - [CM_EVENT_BATT_IN] = "Battery Inserted", - [CM_EVENT_BATT_OUT] = "Battery Pulled Out", - [CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach", - [CM_EVENT_CHG_START_STOP] = "Charging Start/Stop", - [CM_EVENT_OTHERS] = "Other battery events" -}; - /* * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for * delayed works so that we can run delayed works with CM_JIFFIES_SMALL @@ -67,12 +57,6 @@ static bool cm_suspended; static bool cm_rtc_set; static unsigned long cm_suspend_duration_ms; -/* About normal (not suspended) monitoring */ -static unsigned long polling_jiffy = ULONG_MAX; /* ULONG_MAX: no polling */ -static unsigned long next_polling; /* Next appointed polling time */ -static struct workqueue_struct *cm_wq; /* init at driver add */ -static struct delayed_work cm_monitor_work; /* init at driver add */ - /* Global charger-manager description */ static struct charger_global_desc *g_desc; /* init with setup_charger_manager */ @@ -87,11 +71,6 @@ static bool is_batt_present(struct charger_manager *cm) int i, ret; switch (cm->desc->battery_present) { - case CM_BATTERY_PRESENT: - present = true; - break; - case CM_NO_BATTERY: - break; case CM_FUEL_GAUGE: ret = cm->fuel_gauge->get_property(cm->fuel_gauge, POWER_SUPPLY_PROP_PRESENT, &val); @@ -299,26 +278,6 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) return err; } -/** - * try_charger_restart - Restart charging. - * @cm: the Charger Manager representing the battery. - * - * Restart charging by turning off and on the charger. - */ -static int try_charger_restart(struct charger_manager *cm) -{ - int err; - - if (cm->emergency_stop) - return -EAGAIN; - - err = try_charger_enable(cm, false); - if (err) - return err; - - return try_charger_enable(cm, true); -} - /** * uevent_notify - Let users know something has changed. * @cm: the Charger Manager representing the battery. @@ -374,46 +333,6 @@ static void uevent_notify(struct charger_manager *cm, const char *event) dev_info(cm->dev, event); } -/** - * fullbatt_vchk - Check voltage drop some times after "FULL" event. - * @work: the work_struct appointing the function - * - * If a user has designated "fullbatt_vchkdrop_ms/uV" values with - * charger_desc, Charger Manager checks voltage drop after the battery - * "FULL" event. It checks whether the voltage has dropped more than - * fullbatt_vchkdrop_uV by calling this function after fullbatt_vchkrop_ms. - */ -static void fullbatt_vchk(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct charger_manager *cm = container_of(dwork, - struct charger_manager, fullbatt_vchk_work); - struct charger_desc *desc = cm->desc; - int batt_uV, err, diff; - - /* remove the appointment for fullbatt_vchk */ - cm->fullbatt_vchk_jiffies_at = 0; - - if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms) - return; - - err = get_batt_uV(cm, &batt_uV); - if (err) { - dev_err(cm->dev, "%s: get_batt_uV error(%d).\n", __func__, err); - return; - } - - diff = cm->fullbatt_vchk_uV; - diff -= batt_uV; - - dev_dbg(cm->dev, "VBATT dropped %duV after full-batt.\n", diff); - - if (diff > desc->fullbatt_vchkdrop_uV) { - try_charger_restart(cm); - uevent_notify(cm, "Recharge"); - } -} - /** * _cm_monitor - Monitor the temperature and return true for exceptions. * @cm: the Charger Manager representing the battery. @@ -473,131 +392,6 @@ static bool cm_monitor(void) return stop; } -/** - * _setup_polling - Setup the next instance of polling. - * @work: work_struct of the function _setup_polling. - */ -static void _setup_polling(struct work_struct *work) -{ - unsigned long min = ULONG_MAX; - struct charger_manager *cm; - bool keep_polling = false; - unsigned long _next_polling; - - mutex_lock(&cm_list_mtx); - - list_for_each_entry(cm, &cm_list, entry) { - if (is_polling_required(cm) && cm->desc->polling_interval_ms) { - keep_polling = true; - - if (min > cm->desc->polling_interval_ms) - min = cm->desc->polling_interval_ms; - } - } - - polling_jiffy = msecs_to_jiffies(min); - if (polling_jiffy <= CM_JIFFIES_SMALL) - polling_jiffy = CM_JIFFIES_SMALL + 1; - - if (!keep_polling) - polling_jiffy = ULONG_MAX; - if (polling_jiffy == ULONG_MAX) - goto out; - - WARN(cm_wq == NULL, "charger-manager: workqueue not initialized" - ". try it later. %s\n", __func__); - - _next_polling = jiffies + polling_jiffy; - - if (!delayed_work_pending(&cm_monitor_work) || - (delayed_work_pending(&cm_monitor_work) && - time_after(next_polling, _next_polling))) { - cancel_delayed_work_sync(&cm_monitor_work); - next_polling = jiffies + polling_jiffy; - queue_delayed_work(cm_wq, &cm_monitor_work, polling_jiffy); - } - -out: - mutex_unlock(&cm_list_mtx); -} -static DECLARE_WORK(setup_polling, _setup_polling); - -/** - * cm_monitor_poller - The Monitor / Poller. - * @work: work_struct of the function cm_monitor_poller - * - * During non-suspended state, cm_monitor_poller is used to poll and monitor - * the batteries. - */ -static void cm_monitor_poller(struct work_struct *work) -{ - cm_monitor(); - schedule_work(&setup_polling); -} - -/** - * fullbatt_handler - Event handler for CM_EVENT_BATT_FULL - * @cm: the Charger Manager representing the battery. - */ -static void fullbatt_handler(struct charger_manager *cm) -{ - struct charger_desc *desc = cm->desc; - - if (!desc->fullbatt_vchkdrop_uV || !desc->fullbatt_vchkdrop_ms) - goto out; - - if (cm_suspended) - device_set_wakeup_capable(cm->dev, true); - - if (delayed_work_pending(&cm->fullbatt_vchk_work)) - cancel_delayed_work(&cm->fullbatt_vchk_work); - queue_delayed_work(cm_wq, &cm->fullbatt_vchk_work, - msecs_to_jiffies(desc->fullbatt_vchkdrop_ms)); - cm->fullbatt_vchk_jiffies_at = jiffies + msecs_to_jiffies( - desc->fullbatt_vchkdrop_ms); - - if (cm->fullbatt_vchk_jiffies_at == 0) - cm->fullbatt_vchk_jiffies_at = 1; - -out: - dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged.\n"); - uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]); -} - -/** - * battout_handler - Event handler for CM_EVENT_BATT_OUT - * @cm: the Charger Manager representing the battery. - */ -static void battout_handler(struct charger_manager *cm) -{ - if (cm_suspended) - device_set_wakeup_capable(cm->dev, true); - - if (!is_batt_present(cm)) { - dev_emerg(cm->dev, "Battery Pulled Out!\n"); - uevent_notify(cm, default_event_names[CM_EVENT_BATT_OUT]); - } else { - uevent_notify(cm, "Battery Reinserted?"); - } -} - -/** - * misc_event_handler - Handler for other evnets - * @cm: the Charger Manager representing the battery. - * @type: the Charger Manager representing the battery. - */ -static void misc_event_handler(struct charger_manager *cm, - enum cm_event_types type) -{ - if (cm_suspended) - device_set_wakeup_capable(cm->dev, true); - - if (!delayed_work_pending(&cm_monitor_work) && - is_polling_required(cm) && cm->desc->polling_interval_ms) - schedule_work(&setup_polling); - uevent_notify(cm, default_event_names[type]); -} - static int charger_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -819,21 +613,6 @@ static bool cm_setup_timer(void) mutex_lock(&cm_list_mtx); list_for_each_entry(cm, &cm_list, entry) { - unsigned int fbchk_ms = 0; - - /* fullbatt_vchk is required. setup timer for that */ - if (cm->fullbatt_vchk_jiffies_at) { - fbchk_ms = jiffies_to_msecs(cm->fullbatt_vchk_jiffies_at - - jiffies); - if (time_is_before_eq_jiffies( - cm->fullbatt_vchk_jiffies_at) || - msecs_to_jiffies(fbchk_ms) < CM_JIFFIES_SMALL) { - fullbatt_vchk(&cm->fullbatt_vchk_work.work); - fbchk_ms = 0; - } - } - CM_MIN_VALID(wakeup_ms, fbchk_ms); - /* Skip if polling is not required for this CM */ if (!is_polling_required(cm) && !cm->emergency_stop) continue; @@ -893,23 +672,6 @@ static bool cm_setup_timer(void) return false; } -static void _cm_fbchk_in_suspend(struct charger_manager *cm) -{ - unsigned long jiffy_now = jiffies; - - if (!cm->fullbatt_vchk_jiffies_at) - return; - - if (g_desc && g_desc->assume_timer_stops_in_suspend) - jiffy_now += msecs_to_jiffies(cm_suspend_duration_ms); - - /* Execute now if it's going to be executed not too long after */ - jiffy_now += CM_JIFFIES_SMALL; - - if (time_after_eq(jiffy_now, cm->fullbatt_vchk_jiffies_at)) - fullbatt_vchk(&cm->fullbatt_vchk_work.work); -} - /** * cm_suspend_again - Determine whether suspend again or not * @@ -931,8 +693,6 @@ bool cm_suspend_again(void) ret = true; mutex_lock(&cm_list_mtx); list_for_each_entry(cm, &cm_list, entry) { - _cm_fbchk_in_suspend(cm); - if (cm->status_save_ext_pwr_inserted != is_ext_pwr_online(cm) || cm->status_save_batt != is_batt_present(cm)) { ret = false; @@ -1036,21 +796,6 @@ static int charger_manager_probe(struct platform_device *pdev) memcpy(cm->desc, desc, sizeof(struct charger_desc)); cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */ - /* - * The following two do not need to be errors. - * Users may intentionally ignore those two features. - */ - if (desc->fullbatt_uV == 0) { - dev_info(&pdev->dev, "Ignoring full-battery voltage threshold" - " as it is not supplied."); - } - if (!desc->fullbatt_vchkdrop_ms || !desc->fullbatt_vchkdrop_uV) { - dev_info(&pdev->dev, "Disabling full-battery voltage drop " - "checking mechanism as it is not supplied."); - desc->fullbatt_vchkdrop_ms = 0; - desc->fullbatt_vchkdrop_uV = 0; - } - if (!desc->charger_regulators || desc->num_charger_regulators < 1) { ret = -EINVAL; dev_err(&pdev->dev, "charger_regulators undefined.\n"); @@ -1158,8 +903,6 @@ static int charger_manager_probe(struct platform_device *pdev) cm->charger_psy.num_properties++; } - INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk); - ret = power_supply_register(NULL, &cm->charger_psy); if (ret) { dev_err(&pdev->dev, "Cannot register charger-manager with" @@ -1185,15 +928,6 @@ static int charger_manager_probe(struct platform_device *pdev) list_add(&cm->entry, &cm_list); mutex_unlock(&cm_list_mtx); - /* - * Charger-manager is capable of waking up the systme from sleep - * when event is happend through cm_notify_event() - */ - device_init_wakeup(&pdev->dev, true); - device_set_wakeup_capable(&pdev->dev, false); - - schedule_work(&setup_polling); - return 0; err_chg_enable: @@ -1224,17 +958,9 @@ static int __devexit charger_manager_remove(struct platform_device *pdev) list_del(&cm->entry); mutex_unlock(&cm_list_mtx); - if (work_pending(&setup_polling)) - cancel_work_sync(&setup_polling); - if (delayed_work_pending(&cm_monitor_work)) - cancel_delayed_work_sync(&cm_monitor_work); - regulator_bulk_free(desc->num_charger_regulators, desc->charger_regulators); power_supply_unregister(&cm->charger_psy); - - try_charger_enable(cm, false); - kfree(cm->charger_psy.properties); kfree(cm->charger_stat); kfree(cm->desc); @@ -1249,18 +975,6 @@ static const struct platform_device_id charger_manager_id[] = { }; MODULE_DEVICE_TABLE(platform, charger_manager_id); -static int cm_suspend_noirq(struct device *dev) -{ - int ret = 0; - - if (device_may_wakeup(dev)) { - device_set_wakeup_capable(dev, false); - ret = -EAGAIN; - } - - return ret; -} - static int cm_suspend_prepare(struct device *dev) { struct charger_manager *cm = dev_get_drvdata(dev); @@ -1286,8 +1000,6 @@ static int cm_suspend_prepare(struct device *dev) cm_suspended = true; } - if (delayed_work_pending(&cm->fullbatt_vchk_work)) - cancel_delayed_work(&cm->fullbatt_vchk_work); cm->status_save_ext_pwr_inserted = is_ext_pwr_online(cm); cm->status_save_batt = is_batt_present(cm); @@ -1315,40 +1027,11 @@ static void cm_suspend_complete(struct device *dev) cm_rtc_set = false; } - /* Re-enqueue delayed work (fullbatt_vchk_work) */ - if (cm->fullbatt_vchk_jiffies_at) { - unsigned long delay = 0; - unsigned long now = jiffies + CM_JIFFIES_SMALL; - - if (time_after_eq(now, cm->fullbatt_vchk_jiffies_at)) { - delay = (unsigned long)((long)now - - (long)(cm->fullbatt_vchk_jiffies_at)); - delay = jiffies_to_msecs(delay); - } else { - delay = 0; - } - - /* - * Account for cm_suspend_duration_ms if - * assume_timer_stops_in_suspend is active - */ - if (g_desc && g_desc->assume_timer_stops_in_suspend) { - if (delay > cm_suspend_duration_ms) - delay -= cm_suspend_duration_ms; - else - delay = 0; - } - - queue_delayed_work(cm_wq, &cm->fullbatt_vchk_work, - msecs_to_jiffies(delay)); - } - device_set_wakeup_capable(cm->dev, false); uevent_notify(cm, NULL); } static const struct dev_pm_ops charger_manager_pm = { .prepare = cm_suspend_prepare, - .suspend_noirq = cm_suspend_noirq, .complete = cm_suspend_complete, }; @@ -1365,91 +1048,16 @@ static struct platform_driver charger_manager_driver = { static int __init charger_manager_init(void) { - cm_wq = create_freezable_workqueue("charger_manager"); - INIT_DELAYED_WORK(&cm_monitor_work, cm_monitor_poller); - return platform_driver_register(&charger_manager_driver); } late_initcall(charger_manager_init); static void __exit charger_manager_cleanup(void) { - destroy_workqueue(cm_wq); - cm_wq = NULL; - platform_driver_unregister(&charger_manager_driver); } module_exit(charger_manager_cleanup); -/** - * find_power_supply - find the associated power_supply of charger - * @cm: the Charger Manager representing the battery - * @psy: pointer to instance of charger's power_supply - */ -static bool find_power_supply(struct charger_manager *cm, - struct power_supply *psy) -{ - int i; - bool found = false; - - for (i = 0; cm->charger_stat[i]; i++) { - if (psy == cm->charger_stat[i]) { - found = true; - break; - } - } - - return found; -} - -/** - * cm_notify_event - charger driver notify Charger Manager of charger event - * @psy: pointer to instance of charger's power_supply - * @type: type of charger event - * @msg: optional message passed to uevent_notify fuction - */ -void cm_notify_event(struct power_supply *psy, enum cm_event_types type, - char *msg) -{ - struct charger_manager *cm; - bool found_power_supply = false; - - if (psy == NULL) - return; - - mutex_lock(&cm_list_mtx); - list_for_each_entry(cm, &cm_list, entry) { - found_power_supply = find_power_supply(cm, psy); - if (found_power_supply) - break; - } - mutex_unlock(&cm_list_mtx); - - if (!found_power_supply) - return; - - switch (type) { - case CM_EVENT_BATT_FULL: - fullbatt_handler(cm); - break; - case CM_EVENT_BATT_OUT: - battout_handler(cm); - break; - case CM_EVENT_BATT_IN: - case CM_EVENT_EXT_PWR_IN_OUT ... CM_EVENT_CHG_START_STOP: - misc_event_handler(cm, type); - break; - case CM_EVENT_UNKNOWN: - case CM_EVENT_OTHERS: - uevent_notify(cm, msg ? msg : default_event_names[type]); - break; - default: - dev_err(cm->dev, "%s type not specified.\n", __func__); - break; - } -} -EXPORT_SYMBOL_GPL(cm_notify_event); - MODULE_AUTHOR("MyungJoo Ham "); MODULE_DESCRIPTION("Charger Manager"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/power/ds2781_battery.c b/trunk/drivers/power/ds2781_battery.c index 975684a40f15..ca0d653d0a7a 100644 --- a/trunk/drivers/power/ds2781_battery.c +++ b/trunk/drivers/power/ds2781_battery.c @@ -643,7 +643,9 @@ static ssize_t ds2781_read_param_eeprom_bin(struct file *filp, struct power_supply *psy = to_power_supply(dev); struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); - count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off); + count = min_t(loff_t, count, + DS2781_EEPROM_BLOCK1_END - + DS2781_EEPROM_BLOCK1_START + 1 - off); return ds2781_read_block(dev_info, buf, DS2781_EEPROM_BLOCK1_START + off, count); @@ -659,7 +661,9 @@ static ssize_t ds2781_write_param_eeprom_bin(struct file *filp, struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); int ret; - count = min_t(loff_t, count, DS2781_PARAM_EEPROM_SIZE - off); + count = min_t(loff_t, count, + DS2781_EEPROM_BLOCK1_END - + DS2781_EEPROM_BLOCK1_START + 1 - off); ret = ds2781_write(dev_info, buf, DS2781_EEPROM_BLOCK1_START + off, count); @@ -678,7 +682,7 @@ static struct bin_attribute ds2781_param_eeprom_bin_attr = { .name = "param_eeprom", .mode = S_IRUGO | S_IWUSR, }, - .size = DS2781_PARAM_EEPROM_SIZE, + .size = DS2781_EEPROM_BLOCK1_END - DS2781_EEPROM_BLOCK1_START + 1, .read = ds2781_read_param_eeprom_bin, .write = ds2781_write_param_eeprom_bin, }; @@ -692,7 +696,9 @@ static ssize_t ds2781_read_user_eeprom_bin(struct file *filp, struct power_supply *psy = to_power_supply(dev); struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); - count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off); + count = min_t(loff_t, count, + DS2781_EEPROM_BLOCK0_END - + DS2781_EEPROM_BLOCK0_START + 1 - off); return ds2781_read_block(dev_info, buf, DS2781_EEPROM_BLOCK0_START + off, count); @@ -709,7 +715,9 @@ static ssize_t ds2781_write_user_eeprom_bin(struct file *filp, struct ds2781_device_info *dev_info = to_ds2781_device_info(psy); int ret; - count = min_t(loff_t, count, DS2781_USER_EEPROM_SIZE - off); + count = min_t(loff_t, count, + DS2781_EEPROM_BLOCK0_END - + DS2781_EEPROM_BLOCK0_START + 1 - off); ret = ds2781_write(dev_info, buf, DS2781_EEPROM_BLOCK0_START + off, count); @@ -728,7 +736,7 @@ static struct bin_attribute ds2781_user_eeprom_bin_attr = { .name = "user_eeprom", .mode = S_IRUGO | S_IWUSR, }, - .size = DS2781_USER_EEPROM_SIZE, + .size = DS2781_EEPROM_BLOCK0_END - DS2781_EEPROM_BLOCK0_START + 1, .read = ds2781_read_user_eeprom_bin, .write = ds2781_write_user_eeprom_bin, }; diff --git a/trunk/drivers/power/isp1704_charger.c b/trunk/drivers/power/isp1704_charger.c index e5ccd2979773..39eb50f35f09 100644 --- a/trunk/drivers/power/isp1704_charger.c +++ b/trunk/drivers/power/isp1704_charger.c @@ -474,13 +474,13 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) fail2: power_supply_unregister(&isp->psy); fail1: - isp1704_charger_set_power(isp, 0); usb_put_transceiver(isp->phy); fail0: kfree(isp); dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret); + isp1704_charger_set_power(isp, 0); return ret; } diff --git a/trunk/drivers/power/max17042_battery.c b/trunk/drivers/power/max17042_battery.c index 140788b309f8..04620c2cb388 100644 --- a/trunk/drivers/power/max17042_battery.c +++ b/trunk/drivers/power/max17042_battery.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -62,13 +61,9 @@ #define dP_ACC_100 0x1900 #define dP_ACC_200 0x3200 -#define MAX17042_IC_VERSION 0x0092 -#define MAX17047_IC_VERSION 0x00AC /* same for max17050 */ - struct max17042_chip { struct i2c_client *client; struct power_supply battery; - enum max170xx_chip_type chip_type; struct max17042_platform_data *pdata; struct work_struct work; int init_complete; @@ -110,7 +105,6 @@ static enum power_supply_property max17042_battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_AVG, - POWER_SUPPLY_PROP_VOLTAGE_OCV, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_TEMP, @@ -156,10 +150,7 @@ static int max17042_get_property(struct power_supply *psy, val->intval *= 20000; /* Units of LSB = 20mV */ break; case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: - if (chip->chip_type == MAX17042) - ret = max17042_read_reg(chip->client, MAX17042_V_empty); - else - ret = max17042_read_reg(chip->client, MAX17047_V_empty); + ret = max17042_read_reg(chip->client, MAX17042_V_empty); if (ret < 0) return ret; @@ -178,13 +169,6 @@ static int max17042_get_property(struct power_supply *psy, if (ret < 0) return ret; - val->intval = ret * 625 / 8; - break; - case POWER_SUPPLY_PROP_VOLTAGE_OCV: - ret = max17042_read_reg(chip->client, MAX17042_OCVInternal); - if (ret < 0) - return ret; - val->intval = ret * 625 / 8; break; case POWER_SUPPLY_PROP_CAPACITY: @@ -341,10 +325,11 @@ static inline int max17042_model_data_compare(struct max17042_chip *chip, static int max17042_init_model(struct max17042_chip *chip) { int ret; - int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); + int table_size = + sizeof(chip->pdata->config_data->cell_char_tbl)/sizeof(u16); u16 *temp_data; - temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); + temp_data = kzalloc(table_size, GFP_KERNEL); if (!temp_data) return -ENOMEM; @@ -369,11 +354,12 @@ static int max17042_init_model(struct max17042_chip *chip) static int max17042_verify_model_lock(struct max17042_chip *chip) { int i; - int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); + int table_size = + sizeof(chip->pdata->config_data->cell_char_tbl); u16 *temp_data; int ret = 0; - temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); + temp_data = kzalloc(table_size, GFP_KERNEL); if (!temp_data) return -ENOMEM; @@ -396,9 +382,6 @@ static void max17042_write_config_regs(struct max17042_chip *chip) max17042_write_reg(chip->client, MAX17042_FilterCFG, config->filter_cfg); max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg); - if (chip->chip_type == MAX17047) - max17042_write_reg(chip->client, MAX17047_FullSOCThr, - config->full_soc_thresh); } static void max17042_write_custom_regs(struct max17042_chip *chip) @@ -409,23 +392,12 @@ static void max17042_write_custom_regs(struct max17042_chip *chip) config->rcomp0); max17042_write_verify_reg(chip->client, MAX17042_TempCo, config->tcompc0); + max17042_write_reg(chip->client, MAX17042_EmptyTempCo, + config->empty_tempco); + max17042_write_verify_reg(chip->client, MAX17042_K_empty0, + config->kempty0); max17042_write_verify_reg(chip->client, MAX17042_ICHGTerm, config->ichgt_term); - if (chip->chip_type == MAX17042) { - max17042_write_reg(chip->client, MAX17042_EmptyTempCo, - config->empty_tempco); - max17042_write_verify_reg(chip->client, MAX17042_K_empty0, - config->kempty0); - } else { - max17042_write_verify_reg(chip->client, MAX17047_QRTbl00, - config->qrtbl00); - max17042_write_verify_reg(chip->client, MAX17047_QRTbl10, - config->qrtbl10); - max17042_write_verify_reg(chip->client, MAX17047_QRTbl20, - config->qrtbl20); - max17042_write_verify_reg(chip->client, MAX17047_QRTbl30, - config->qrtbl30); - } } static void max17042_update_capacity_regs(struct max17042_chip *chip) @@ -481,8 +453,6 @@ static void max17042_load_new_capacity_params(struct max17042_chip *chip) config->design_cap); max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom, config->fullcapnom); - /* Update SOC register with new SOC */ - max17042_write_reg(chip->client, MAX17042_RepSOC, vfSoc); } /* @@ -519,28 +489,20 @@ static inline void max17042_override_por_values(struct max17042_chip *chip) max17042_override_por(client, MAX17042_FullCAP, config->fullcap); max17042_override_por(client, MAX17042_FullCAPNom, config->fullcapnom); - if (chip->chip_type == MAX17042) - max17042_override_por(client, MAX17042_SOC_empty, - config->socempty); + max17042_override_por(client, MAX17042_SOC_empty, config->socempty); max17042_override_por(client, MAX17042_LAvg_empty, config->lavg_empty); max17042_override_por(client, MAX17042_dQacc, config->dqacc); max17042_override_por(client, MAX17042_dPacc, config->dpacc); - if (chip->chip_type == MAX17042) - max17042_override_por(client, MAX17042_V_empty, config->vempty); - else - max17042_override_por(client, MAX17047_V_empty, config->vempty); + max17042_override_por(client, MAX17042_V_empty, config->vempty); max17042_override_por(client, MAX17042_TempNom, config->temp_nom); max17042_override_por(client, MAX17042_TempLim, config->temp_lim); max17042_override_por(client, MAX17042_FCTC, config->fctc); max17042_override_por(client, MAX17042_RCOMP0, config->rcomp0); max17042_override_por(client, MAX17042_TempCo, config->tcompc0); - if (chip->chip_type) { - max17042_override_por(client, MAX17042_EmptyTempCo, - config->empty_tempco); - max17042_override_por(client, MAX17042_K_empty0, - config->kempty0); - } + max17042_override_por(client, MAX17042_EmptyTempCo, + config->empty_tempco); + max17042_override_por(client, MAX17042_K_empty0, config->kempty0); } static int max17042_init_chip(struct max17042_chip *chip) @@ -697,19 +659,7 @@ static int __devinit max17042_probe(struct i2c_client *client, i2c_set_clientdata(client, chip); - ret = max17042_read_reg(chip->client, MAX17042_DevName); - if (ret == MAX17042_IC_VERSION) { - dev_dbg(&client->dev, "chip type max17042 detected\n"); - chip->chip_type = MAX17042; - } else if (ret == MAX17047_IC_VERSION) { - dev_dbg(&client->dev, "chip type max17047/50 detected\n"); - chip->chip_type = MAX17047; - } else { - dev_err(&client->dev, "device version mismatch: %x\n", ret); - return -EIO; - } - - chip->battery.name = "max170xx_battery"; + chip->battery.name = "max17042_battery"; chip->battery.type = POWER_SUPPLY_TYPE_BATTERY; chip->battery.get_property = max17042_get_property; chip->battery.properties = max17042_battery_props; @@ -733,12 +683,6 @@ static int __devinit max17042_probe(struct i2c_client *client, max17042_write_reg(client, MAX17042_LearnCFG, 0x0007); } - ret = power_supply_register(&client->dev, &chip->battery); - if (ret) { - dev_err(&client->dev, "failed: power supply register\n"); - return ret; - } - if (client->irq) { ret = request_threaded_irq(client->irq, NULL, max17042_thread_handler, @@ -749,14 +693,13 @@ static int __devinit max17042_probe(struct i2c_client *client, reg |= CONFIG_ALRT_BIT_ENBL; max17042_write_reg(client, MAX17042_CONFIG, reg); max17042_set_soc_threshold(chip, 1); - } else { - client->irq = 0; + } else dev_err(&client->dev, "%s(): cannot get IRQ\n", __func__); - } } reg = max17042_read_reg(chip->client, MAX17042_STATUS); + if (reg & STATUS_POR_BIT) { INIT_WORK(&chip->work, max17042_init_worker); schedule_work(&chip->work); @@ -764,65 +707,23 @@ static int __devinit max17042_probe(struct i2c_client *client, chip->init_complete = 1; } - return 0; + ret = power_supply_register(&client->dev, &chip->battery); + if (ret) + dev_err(&client->dev, "failed: power supply register\n"); + return ret; } static int __devexit max17042_remove(struct i2c_client *client) { struct max17042_chip *chip = i2c_get_clientdata(client); - if (client->irq) - free_irq(client->irq, chip); power_supply_unregister(&chip->battery); return 0; } -#ifdef CONFIG_PM -static int max17042_suspend(struct device *dev) -{ - struct max17042_chip *chip = dev_get_drvdata(dev); - - /* - * disable the irq and enable irq_wake - * capability to the interrupt line. - */ - if (chip->client->irq) { - disable_irq(chip->client->irq); - enable_irq_wake(chip->client->irq); - } - - return 0; -} - -static int max17042_resume(struct device *dev) -{ - struct max17042_chip *chip = dev_get_drvdata(dev); - - if (chip->client->irq) { - disable_irq_wake(chip->client->irq); - enable_irq(chip->client->irq); - /* re-program the SOC thresholds to 1% change */ - max17042_set_soc_threshold(chip, 1); - } - - return 0; -} - -static const struct dev_pm_ops max17042_pm_ops = { - .suspend = max17042_suspend, - .resume = max17042_resume, -}; - -#define MAX17042_PM_OPS (&max17042_pm_ops) -#else -#define MAX17042_PM_OPS NULL -#endif - #ifdef CONFIG_OF static const struct of_device_id max17042_dt_match[] = { { .compatible = "maxim,max17042" }, - { .compatible = "maxim,max17047" }, - { .compatible = "maxim,max17050" }, { }, }; MODULE_DEVICE_TABLE(of, max17042_dt_match); @@ -830,8 +731,6 @@ MODULE_DEVICE_TABLE(of, max17042_dt_match); static const struct i2c_device_id max17042_id[] = { { "max17042", 0 }, - { "max17047", 1 }, - { "max17050", 2 }, { } }; MODULE_DEVICE_TABLE(i2c, max17042_id); @@ -840,7 +739,6 @@ static struct i2c_driver max17042_i2c_driver = { .driver = { .name = "max17042", .of_match_table = of_match_ptr(max17042_dt_match), - .pm = MAX17042_PM_OPS, }, .probe = max17042_probe, .remove = __devexit_p(max17042_remove), diff --git a/trunk/drivers/power/power_supply_sysfs.c b/trunk/drivers/power/power_supply_sysfs.c index 4150747f9186..4368e7d61316 100644 --- a/trunk/drivers/power/power_supply_sysfs.c +++ b/trunk/drivers/power/power_supply_sysfs.c @@ -146,7 +146,6 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(voltage_min_design), POWER_SUPPLY_ATTR(voltage_now), POWER_SUPPLY_ATTR(voltage_avg), - POWER_SUPPLY_ATTR(voltage_ocv), POWER_SUPPLY_ATTR(current_max), POWER_SUPPLY_ATTR(current_now), POWER_SUPPLY_ATTR(current_avg), diff --git a/trunk/drivers/power/sbs-battery.c b/trunk/drivers/power/sbs-battery.c index a5b6849d4123..06b659d91790 100644 --- a/trunk/drivers/power/sbs-battery.c +++ b/trunk/drivers/power/sbs-battery.c @@ -89,7 +89,7 @@ static const struct chip_data { [REG_CURRENT] = SBS_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 32767), [REG_CAPACITY] = - SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0D, 0, 100), + SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100), [REG_REMAINING_CAPACITY] = SBS_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535), [REG_REMAINING_CAPACITY_CHARGE] = diff --git a/trunk/drivers/power/smb347-charger.c b/trunk/drivers/power/smb347-charger.c index f8eedd8a676f..ce1694d1a365 100644 --- a/trunk/drivers/power/smb347-charger.c +++ b/trunk/drivers/power/smb347-charger.c @@ -11,7 +11,7 @@ * published by the Free Software Foundation. */ -#include +#include #include #include #include @@ -21,7 +21,7 @@ #include #include #include -#include +#include /* * Configuration registers. These are mirrored to volatile RAM and can be @@ -39,7 +39,6 @@ #define CFG_CURRENT_LIMIT_DC_SHIFT 4 #define CFG_CURRENT_LIMIT_USB_MASK 0x0f #define CFG_FLOAT_VOLTAGE 0x03 -#define CFG_FLOAT_VOLTAGE_FLOAT_MASK 0x3f #define CFG_FLOAT_VOLTAGE_THRESHOLD_MASK 0xc0 #define CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT 6 #define CFG_STAT 0x05 @@ -114,31 +113,29 @@ #define STAT_C_CHARGER_ERROR BIT(6) #define STAT_E 0x3f -#define SMB347_MAX_REGISTER 0x3f - /** * struct smb347_charger - smb347 charger instance * @lock: protects concurrent access to online variables - * @dev: pointer to device - * @regmap: pointer to driver regmap + * @client: pointer to i2c client * @mains: power_supply instance for AC/DC power * @usb: power_supply instance for USB power * @battery: power_supply instance for battery * @mains_online: is AC/DC input connected * @usb_online: is USB input connected * @charging_enabled: is charging enabled + * @dentry: for debugfs * @pdata: pointer to platform data */ struct smb347_charger { struct mutex lock; - struct device *dev; - struct regmap *regmap; + struct i2c_client *client; struct power_supply mains; struct power_supply usb; struct power_supply battery; bool mains_online; bool usb_online; bool charging_enabled; + struct dentry *dentry; const struct smb347_charger_platform_data *pdata; }; @@ -196,6 +193,14 @@ static const unsigned int ccc_tbl[] = { 1200000, }; +/* Convert register value to current using lookup table */ +static int hw_to_current(const unsigned int *tbl, size_t size, unsigned int val) +{ + if (val >= size) + return -EINVAL; + return tbl[val]; +} + /* Convert current to register value using lookup table */ static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val) { @@ -207,22 +212,43 @@ static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val) return i > 0 ? i - 1 : -EINVAL; } +static int smb347_read(struct smb347_charger *smb, u8 reg) +{ + int ret; + + ret = i2c_smbus_read_byte_data(smb->client, reg); + if (ret < 0) + dev_warn(&smb->client->dev, "failed to read reg 0x%x: %d\n", + reg, ret); + return ret; +} + +static int smb347_write(struct smb347_charger *smb, u8 reg, u8 val) +{ + int ret; + + ret = i2c_smbus_write_byte_data(smb->client, reg, val); + if (ret < 0) + dev_warn(&smb->client->dev, "failed to write reg 0x%x: %d\n", + reg, ret); + return ret; +} + /** - * smb347_update_ps_status - refreshes the power source status + * smb347_update_status - updates the charging status * @smb: pointer to smb347 charger instance * - * Function checks whether any power source is connected to the charger and - * updates internal state accordingly. If there is a change to previous state - * function returns %1, otherwise %0 and negative errno in case of errror. + * Function checks status of the charging and updates internal state + * accordingly. Returns %0 if there is no change in status, %1 if the + * status has changed and negative errno in case of failure. */ -static int smb347_update_ps_status(struct smb347_charger *smb) +static int smb347_update_status(struct smb347_charger *smb) { bool usb = false; bool dc = false; - unsigned int val; int ret; - ret = regmap_read(smb->regmap, IRQSTAT_E, &val); + ret = smb347_read(smb, IRQSTAT_E); if (ret < 0) return ret; @@ -231,9 +257,9 @@ static int smb347_update_ps_status(struct smb347_charger *smb) * platform data _and_ whether corresponding undervoltage is set. */ if (smb->pdata->use_mains) - dc = !(val & IRQSTAT_E_DCIN_UV_STAT); + dc = !(ret & IRQSTAT_E_DCIN_UV_STAT); if (smb->pdata->use_usb) - usb = !(val & IRQSTAT_E_USBIN_UV_STAT); + usb = !(ret & IRQSTAT_E_USBIN_UV_STAT); mutex_lock(&smb->lock); ret = smb->mains_online != dc || smb->usb_online != usb; @@ -245,15 +271,15 @@ static int smb347_update_ps_status(struct smb347_charger *smb) } /* - * smb347_is_ps_online - returns whether input power source is connected + * smb347_is_online - returns whether input power source is connected * @smb: pointer to smb347 charger instance * * Returns %true if input power source is connected. Note that this is * dependent on what platform has configured for usable power sources. For - * example if USB is disabled, this will return %false even if the USB cable - * is connected. + * example if USB is disabled, this will return %false even if the USB + * cable is connected. */ -static bool smb347_is_ps_online(struct smb347_charger *smb) +static bool smb347_is_online(struct smb347_charger *smb) { bool ret; @@ -273,17 +299,16 @@ static bool smb347_is_ps_online(struct smb347_charger *smb) */ static int smb347_charging_status(struct smb347_charger *smb) { - unsigned int val; int ret; - if (!smb347_is_ps_online(smb)) + if (!smb347_is_online(smb)) return 0; - ret = regmap_read(smb->regmap, STAT_C, &val); + ret = smb347_read(smb, STAT_C); if (ret < 0) return 0; - return (val & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT; + return (ret & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT; } static int smb347_charging_set(struct smb347_charger *smb, bool enable) @@ -291,17 +316,27 @@ static int smb347_charging_set(struct smb347_charger *smb, bool enable) int ret = 0; if (smb->pdata->enable_control != SMB347_CHG_ENABLE_SW) { - dev_dbg(smb->dev, "charging enable/disable in SW disabled\n"); + dev_dbg(&smb->client->dev, + "charging enable/disable in SW disabled\n"); return 0; } mutex_lock(&smb->lock); if (smb->charging_enabled != enable) { - ret = regmap_update_bits(smb->regmap, CMD_A, CMD_A_CHG_ENABLED, - enable ? CMD_A_CHG_ENABLED : 0); - if (!ret) - smb->charging_enabled = enable; + ret = smb347_read(smb, CMD_A); + if (ret < 0) + goto out; + + smb->charging_enabled = enable; + + if (enable) + ret |= CMD_A_CHG_ENABLED; + else + ret &= ~CMD_A_CHG_ENABLED; + + ret = smb347_write(smb, CMD_A, ret); } +out: mutex_unlock(&smb->lock); return ret; } @@ -316,7 +351,7 @@ static inline int smb347_charging_disable(struct smb347_charger *smb) return smb347_charging_set(smb, false); } -static int smb347_start_stop_charging(struct smb347_charger *smb) +static int smb347_update_online(struct smb347_charger *smb) { int ret; @@ -325,14 +360,16 @@ static int smb347_start_stop_charging(struct smb347_charger *smb) * disable or enable the charging. We do it manually because it * depends on how the platform has configured the valid inputs. */ - if (smb347_is_ps_online(smb)) { + if (smb347_is_online(smb)) { ret = smb347_charging_enable(smb); if (ret < 0) - dev_err(smb->dev, "failed to enable charging\n"); + dev_err(&smb->client->dev, + "failed to enable charging\n"); } else { ret = smb347_charging_disable(smb); if (ret < 0) - dev_err(smb->dev, "failed to disable charging\n"); + dev_err(&smb->client->dev, + "failed to disable charging\n"); } return ret; @@ -340,120 +377,112 @@ static int smb347_start_stop_charging(struct smb347_charger *smb) static int smb347_set_charge_current(struct smb347_charger *smb) { - int ret; + int ret, val; + + ret = smb347_read(smb, CFG_CHARGE_CURRENT); + if (ret < 0) + return ret; if (smb->pdata->max_charge_current) { - ret = current_to_hw(fcc_tbl, ARRAY_SIZE(fcc_tbl), + val = current_to_hw(fcc_tbl, ARRAY_SIZE(fcc_tbl), smb->pdata->max_charge_current); - if (ret < 0) - return ret; + if (val < 0) + return val; - ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, - CFG_CHARGE_CURRENT_FCC_MASK, - ret << CFG_CHARGE_CURRENT_FCC_SHIFT); - if (ret < 0) - return ret; + ret &= ~CFG_CHARGE_CURRENT_FCC_MASK; + ret |= val << CFG_CHARGE_CURRENT_FCC_SHIFT; } if (smb->pdata->pre_charge_current) { - ret = current_to_hw(pcc_tbl, ARRAY_SIZE(pcc_tbl), + val = current_to_hw(pcc_tbl, ARRAY_SIZE(pcc_tbl), smb->pdata->pre_charge_current); - if (ret < 0) - return ret; + if (val < 0) + return val; - ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, - CFG_CHARGE_CURRENT_PCC_MASK, - ret << CFG_CHARGE_CURRENT_PCC_SHIFT); - if (ret < 0) - return ret; + ret &= ~CFG_CHARGE_CURRENT_PCC_MASK; + ret |= val << CFG_CHARGE_CURRENT_PCC_SHIFT; } if (smb->pdata->termination_current) { - ret = current_to_hw(tc_tbl, ARRAY_SIZE(tc_tbl), + val = current_to_hw(tc_tbl, ARRAY_SIZE(tc_tbl), smb->pdata->termination_current); - if (ret < 0) - return ret; + if (val < 0) + return val; - ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, - CFG_CHARGE_CURRENT_TC_MASK, ret); - if (ret < 0) - return ret; + ret &= ~CFG_CHARGE_CURRENT_TC_MASK; + ret |= val; } - return 0; + return smb347_write(smb, CFG_CHARGE_CURRENT, ret); } static int smb347_set_current_limits(struct smb347_charger *smb) { - int ret; + int ret, val; + + ret = smb347_read(smb, CFG_CURRENT_LIMIT); + if (ret < 0) + return ret; if (smb->pdata->mains_current_limit) { - ret = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), + val = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), smb->pdata->mains_current_limit); - if (ret < 0) - return ret; + if (val < 0) + return val; - ret = regmap_update_bits(smb->regmap, CFG_CURRENT_LIMIT, - CFG_CURRENT_LIMIT_DC_MASK, - ret << CFG_CURRENT_LIMIT_DC_SHIFT); - if (ret < 0) - return ret; + ret &= ~CFG_CURRENT_LIMIT_DC_MASK; + ret |= val << CFG_CURRENT_LIMIT_DC_SHIFT; } if (smb->pdata->usb_hc_current_limit) { - ret = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), + val = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), smb->pdata->usb_hc_current_limit); - if (ret < 0) - return ret; + if (val < 0) + return val; - ret = regmap_update_bits(smb->regmap, CFG_CURRENT_LIMIT, - CFG_CURRENT_LIMIT_USB_MASK, ret); - if (ret < 0) - return ret; + ret &= ~CFG_CURRENT_LIMIT_USB_MASK; + ret |= val; } - return 0; + return smb347_write(smb, CFG_CURRENT_LIMIT, ret); } static int smb347_set_voltage_limits(struct smb347_charger *smb) { - int ret; + int ret, val; + + ret = smb347_read(smb, CFG_FLOAT_VOLTAGE); + if (ret < 0) + return ret; if (smb->pdata->pre_to_fast_voltage) { - ret = smb->pdata->pre_to_fast_voltage; + val = smb->pdata->pre_to_fast_voltage; /* uV */ - ret = clamp_val(ret, 2400000, 3000000) - 2400000; - ret /= 200000; + val = clamp_val(val, 2400000, 3000000) - 2400000; + val /= 200000; - ret = regmap_update_bits(smb->regmap, CFG_FLOAT_VOLTAGE, - CFG_FLOAT_VOLTAGE_THRESHOLD_MASK, - ret << CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT); - if (ret < 0) - return ret; + ret &= ~CFG_FLOAT_VOLTAGE_THRESHOLD_MASK; + ret |= val << CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT; } if (smb->pdata->max_charge_voltage) { - ret = smb->pdata->max_charge_voltage; + val = smb->pdata->max_charge_voltage; /* uV */ - ret = clamp_val(ret, 3500000, 4500000) - 3500000; - ret /= 20000; + val = clamp_val(val, 3500000, 4500000) - 3500000; + val /= 20000; - ret = regmap_update_bits(smb->regmap, CFG_FLOAT_VOLTAGE, - CFG_FLOAT_VOLTAGE_FLOAT_MASK, ret); - if (ret < 0) - return ret; + ret |= val; } - return 0; + return smb347_write(smb, CFG_FLOAT_VOLTAGE, ret); } static int smb347_set_temp_limits(struct smb347_charger *smb) { bool enable_therm_monitor = false; - int ret = 0; - int val; + int ret, val; if (smb->pdata->chip_temp_threshold) { val = smb->pdata->chip_temp_threshold; @@ -462,13 +491,22 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) val = clamp_val(val, 100, 130) - 100; val /= 10; - ret = regmap_update_bits(smb->regmap, CFG_OTG, - CFG_OTG_TEMP_THRESHOLD_MASK, - val << CFG_OTG_TEMP_THRESHOLD_SHIFT); + ret = smb347_read(smb, CFG_OTG); + if (ret < 0) + return ret; + + ret &= ~CFG_OTG_TEMP_THRESHOLD_MASK; + ret |= val << CFG_OTG_TEMP_THRESHOLD_SHIFT; + + ret = smb347_write(smb, CFG_OTG, ret); if (ret < 0) return ret; } + ret = smb347_read(smb, CFG_TEMP_LIMIT); + if (ret < 0) + return ret; + if (smb->pdata->soft_cold_temp_limit != SMB347_TEMP_USE_DEFAULT) { val = smb->pdata->soft_cold_temp_limit; @@ -477,11 +515,8 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) /* this goes from higher to lower so invert the value */ val = ~val & 0x3; - ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, - CFG_TEMP_LIMIT_SOFT_COLD_MASK, - val << CFG_TEMP_LIMIT_SOFT_COLD_SHIFT); - if (ret < 0) - return ret; + ret &= ~CFG_TEMP_LIMIT_SOFT_COLD_MASK; + ret |= val << CFG_TEMP_LIMIT_SOFT_COLD_SHIFT; enable_therm_monitor = true; } @@ -492,11 +527,8 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) val = clamp_val(val, 40, 55) - 40; val /= 5; - ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, - CFG_TEMP_LIMIT_SOFT_HOT_MASK, - val << CFG_TEMP_LIMIT_SOFT_HOT_SHIFT); - if (ret < 0) - return ret; + ret &= ~CFG_TEMP_LIMIT_SOFT_HOT_MASK; + ret |= val << CFG_TEMP_LIMIT_SOFT_HOT_SHIFT; enable_therm_monitor = true; } @@ -509,11 +541,8 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) /* this goes from higher to lower so invert the value */ val = ~val & 0x3; - ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, - CFG_TEMP_LIMIT_HARD_COLD_MASK, - val << CFG_TEMP_LIMIT_HARD_COLD_SHIFT); - if (ret < 0) - return ret; + ret &= ~CFG_TEMP_LIMIT_HARD_COLD_MASK; + ret |= val << CFG_TEMP_LIMIT_HARD_COLD_SHIFT; enable_therm_monitor = true; } @@ -524,15 +553,16 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) val = clamp_val(val, 50, 65) - 50; val /= 5; - ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, - CFG_TEMP_LIMIT_HARD_HOT_MASK, - val << CFG_TEMP_LIMIT_HARD_HOT_SHIFT); - if (ret < 0) - return ret; + ret &= ~CFG_TEMP_LIMIT_HARD_HOT_MASK; + ret |= val << CFG_TEMP_LIMIT_HARD_HOT_SHIFT; enable_therm_monitor = true; } + ret = smb347_write(smb, CFG_TEMP_LIMIT, ret); + if (ret < 0) + return ret; + /* * If any of the temperature limits are set, we also enable the * thermistor monitoring. @@ -544,15 +574,25 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) * depending on the configuration. */ if (enable_therm_monitor) { - ret = regmap_update_bits(smb->regmap, CFG_THERM, - CFG_THERM_MONITOR_DISABLED, 0); + ret = smb347_read(smb, CFG_THERM); + if (ret < 0) + return ret; + + ret &= ~CFG_THERM_MONITOR_DISABLED; + + ret = smb347_write(smb, CFG_THERM, ret); if (ret < 0) return ret; } if (smb->pdata->suspend_on_hard_temp_limit) { - ret = regmap_update_bits(smb->regmap, CFG_SYSOK, - CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED, 0); + ret = smb347_read(smb, CFG_SYSOK); + if (ret < 0) + return ret; + + ret &= ~CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED; + + ret = smb347_write(smb, CFG_SYSOK, ret); if (ret < 0) return ret; } @@ -561,15 +601,17 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) SMB347_SOFT_TEMP_COMPENSATE_DEFAULT) { val = smb->pdata->soft_temp_limit_compensation & 0x3; - ret = regmap_update_bits(smb->regmap, CFG_THERM, - CFG_THERM_SOFT_HOT_COMPENSATION_MASK, - val << CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT); + ret = smb347_read(smb, CFG_THERM); if (ret < 0) return ret; - ret = regmap_update_bits(smb->regmap, CFG_THERM, - CFG_THERM_SOFT_COLD_COMPENSATION_MASK, - val << CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT); + ret &= ~CFG_THERM_SOFT_HOT_COMPENSATION_MASK; + ret |= val << CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT; + + ret &= ~CFG_THERM_SOFT_COLD_COMPENSATION_MASK; + ret |= val << CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT; + + ret = smb347_write(smb, CFG_THERM, ret); if (ret < 0) return ret; } @@ -580,9 +622,14 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) if (val < 0) return val; - ret = regmap_update_bits(smb->regmap, CFG_OTG, - CFG_OTG_CC_COMPENSATION_MASK, - (val & 0x3) << CFG_OTG_CC_COMPENSATION_SHIFT); + ret = smb347_read(smb, CFG_OTG); + if (ret < 0) + return ret; + + ret &= ~CFG_OTG_CC_COMPENSATION_MASK; + ret |= (val & 0x3) << CFG_OTG_CC_COMPENSATION_SHIFT; + + ret = smb347_write(smb, CFG_OTG, ret); if (ret < 0) return ret; } @@ -601,13 +648,22 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) */ static int smb347_set_writable(struct smb347_charger *smb, bool writable) { - return regmap_update_bits(smb->regmap, CMD_A, CMD_A_ALLOW_WRITE, - writable ? CMD_A_ALLOW_WRITE : 0); + int ret; + + ret = smb347_read(smb, CMD_A); + if (ret < 0) + return ret; + + if (writable) + ret |= CMD_A_ALLOW_WRITE; + else + ret &= ~CMD_A_ALLOW_WRITE; + + return smb347_write(smb, CMD_A, ret); } static int smb347_hw_init(struct smb347_charger *smb) { - unsigned int val; int ret; ret = smb347_set_writable(smb, true); @@ -636,19 +692,34 @@ static int smb347_hw_init(struct smb347_charger *smb) /* If USB charging is disabled we put the USB in suspend mode */ if (!smb->pdata->use_usb) { - ret = regmap_update_bits(smb->regmap, CMD_A, - CMD_A_SUSPEND_ENABLED, - CMD_A_SUSPEND_ENABLED); + ret = smb347_read(smb, CMD_A); + if (ret < 0) + goto fail; + + ret |= CMD_A_SUSPEND_ENABLED; + + ret = smb347_write(smb, CMD_A, ret); if (ret < 0) goto fail; } + ret = smb347_read(smb, CFG_OTHER); + if (ret < 0) + goto fail; + /* * If configured by platform data, we enable hardware Auto-OTG * support for driving VBUS. Otherwise we disable it. */ - ret = regmap_update_bits(smb->regmap, CFG_OTHER, CFG_OTHER_RID_MASK, - smb->pdata->use_usb_otg ? CFG_OTHER_RID_ENABLED_AUTO_OTG : 0); + ret &= ~CFG_OTHER_RID_MASK; + if (smb->pdata->use_usb_otg) + ret |= CFG_OTHER_RID_ENABLED_AUTO_OTG; + + ret = smb347_write(smb, CFG_OTHER, ret); + if (ret < 0) + goto fail; + + ret = smb347_read(smb, CFG_PIN); if (ret < 0) goto fail; @@ -657,33 +728,32 @@ static int smb347_hw_init(struct smb347_charger *smb) * command register unless pin control is specified in the platform * data. */ + ret &= ~CFG_PIN_EN_CTRL_MASK; + switch (smb->pdata->enable_control) { + case SMB347_CHG_ENABLE_SW: + /* Do nothing, 0 means i2c control */ + break; case SMB347_CHG_ENABLE_PIN_ACTIVE_LOW: - val = CFG_PIN_EN_CTRL_ACTIVE_LOW; + ret |= CFG_PIN_EN_CTRL_ACTIVE_LOW; break; case SMB347_CHG_ENABLE_PIN_ACTIVE_HIGH: - val = CFG_PIN_EN_CTRL_ACTIVE_HIGH; - break; - default: - val = 0; + ret |= CFG_PIN_EN_CTRL_ACTIVE_HIGH; break; } - ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CTRL_MASK, - val); - if (ret < 0) - goto fail; - /* Disable Automatic Power Source Detection (APSD) interrupt. */ - ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_APSD_IRQ, 0); + ret &= ~CFG_PIN_EN_APSD_IRQ; + + ret = smb347_write(smb, CFG_PIN, ret); if (ret < 0) goto fail; - ret = smb347_update_ps_status(smb); + ret = smb347_update_status(smb); if (ret < 0) goto fail; - ret = smb347_start_stop_charging(smb); + ret = smb347_update_online(smb); fail: smb347_set_writable(smb, false); @@ -693,25 +763,24 @@ static int smb347_hw_init(struct smb347_charger *smb) static irqreturn_t smb347_interrupt(int irq, void *data) { struct smb347_charger *smb = data; - unsigned int stat_c, irqstat_e, irqstat_c; - bool handled = false; - int ret; + int stat_c, irqstat_e, irqstat_c; + irqreturn_t ret = IRQ_NONE; - ret = regmap_read(smb->regmap, STAT_C, &stat_c); - if (ret < 0) { - dev_warn(smb->dev, "reading STAT_C failed\n"); + stat_c = smb347_read(smb, STAT_C); + if (stat_c < 0) { + dev_warn(&smb->client->dev, "reading STAT_C failed\n"); return IRQ_NONE; } - ret = regmap_read(smb->regmap, IRQSTAT_C, &irqstat_c); - if (ret < 0) { - dev_warn(smb->dev, "reading IRQSTAT_C failed\n"); + irqstat_c = smb347_read(smb, IRQSTAT_C); + if (irqstat_c < 0) { + dev_warn(&smb->client->dev, "reading IRQSTAT_C failed\n"); return IRQ_NONE; } - ret = regmap_read(smb->regmap, IRQSTAT_E, &irqstat_e); - if (ret < 0) { - dev_warn(smb->dev, "reading IRQSTAT_E failed\n"); + irqstat_e = smb347_read(smb, IRQSTAT_E); + if (irqstat_e < 0) { + dev_warn(&smb->client->dev, "reading IRQSTAT_E failed\n"); return IRQ_NONE; } @@ -720,11 +789,13 @@ static irqreturn_t smb347_interrupt(int irq, void *data) * disable charging. */ if (stat_c & STAT_C_CHARGER_ERROR) { - dev_err(smb->dev, "error in charger, disabling charging\n"); + dev_err(&smb->client->dev, + "error in charger, disabling charging\n"); smb347_charging_disable(smb); power_supply_changed(&smb->battery); - handled = true; + + ret = IRQ_HANDLED; } /* @@ -735,7 +806,7 @@ static irqreturn_t smb347_interrupt(int irq, void *data) if (irqstat_c & (IRQSTAT_C_TERMINATION_IRQ | IRQSTAT_C_TAPER_IRQ)) { if (irqstat_c & IRQSTAT_C_TERMINATION_STAT) power_supply_changed(&smb->battery); - handled = true; + ret = IRQ_HANDLED; } /* @@ -743,17 +814,15 @@ static irqreturn_t smb347_interrupt(int irq, void *data) * was connected or disconnected. */ if (irqstat_e & (IRQSTAT_E_USBIN_UV_IRQ | IRQSTAT_E_DCIN_UV_IRQ)) { - if (smb347_update_ps_status(smb) > 0) { - smb347_start_stop_charging(smb); - if (smb->pdata->use_mains) - power_supply_changed(&smb->mains); - if (smb->pdata->use_usb) - power_supply_changed(&smb->usb); + if (smb347_update_status(smb) > 0) { + smb347_update_online(smb); + power_supply_changed(&smb->mains); + power_supply_changed(&smb->usb); } - handled = true; + ret = IRQ_HANDLED; } - return handled ? IRQ_HANDLED : IRQ_NONE; + return ret; } static int smb347_irq_set(struct smb347_charger *smb, bool enable) @@ -770,18 +839,41 @@ static int smb347_irq_set(struct smb347_charger *smb, bool enable) * - termination current reached * - charger error */ - ret = regmap_update_bits(smb->regmap, CFG_FAULT_IRQ, 0xff, - enable ? CFG_FAULT_IRQ_DCIN_UV : 0); - if (ret < 0) - goto fail; + if (enable) { + ret = smb347_write(smb, CFG_FAULT_IRQ, CFG_FAULT_IRQ_DCIN_UV); + if (ret < 0) + goto fail; - ret = regmap_update_bits(smb->regmap, CFG_STATUS_IRQ, 0xff, - enable ? CFG_STATUS_IRQ_TERMINATION_OR_TAPER : 0); - if (ret < 0) - goto fail; + ret = smb347_write(smb, CFG_STATUS_IRQ, + CFG_STATUS_IRQ_TERMINATION_OR_TAPER); + if (ret < 0) + goto fail; + + ret = smb347_read(smb, CFG_PIN); + if (ret < 0) + goto fail; + + ret |= CFG_PIN_EN_CHARGER_ERROR; + + ret = smb347_write(smb, CFG_PIN, ret); + } else { + ret = smb347_write(smb, CFG_FAULT_IRQ, 0); + if (ret < 0) + goto fail; + + ret = smb347_write(smb, CFG_STATUS_IRQ, 0); + if (ret < 0) + goto fail; + + ret = smb347_read(smb, CFG_PIN); + if (ret < 0) + goto fail; + + ret &= ~CFG_PIN_EN_CHARGER_ERROR; + + ret = smb347_write(smb, CFG_PIN, ret); + } - ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CHARGER_ERROR, - enable ? CFG_PIN_EN_CHARGER_ERROR : 0); fail: smb347_set_writable(smb, false); return ret; @@ -797,18 +889,18 @@ static inline int smb347_irq_disable(struct smb347_charger *smb) return smb347_irq_set(smb, false); } -static int smb347_irq_init(struct smb347_charger *smb, - struct i2c_client *client) +static int smb347_irq_init(struct smb347_charger *smb) { const struct smb347_charger_platform_data *pdata = smb->pdata; int ret, irq = gpio_to_irq(pdata->irq_gpio); - ret = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); + ret = gpio_request_one(pdata->irq_gpio, GPIOF_IN, smb->client->name); if (ret < 0) goto fail; ret = request_threaded_irq(irq, NULL, smb347_interrupt, - IRQF_TRIGGER_FALLING, client->name, smb); + IRQF_TRIGGER_FALLING, smb->client->name, + smb); if (ret < 0) goto fail_gpio; @@ -820,14 +912,23 @@ static int smb347_irq_init(struct smb347_charger *smb, * Configure the STAT output to be suitable for interrupts: disable * all other output (except interrupts) and make it active low. */ - ret = regmap_update_bits(smb->regmap, CFG_STAT, - CFG_STAT_ACTIVE_HIGH | CFG_STAT_DISABLED, - CFG_STAT_DISABLED); + ret = smb347_read(smb, CFG_STAT); + if (ret < 0) + goto fail_readonly; + + ret &= ~CFG_STAT_ACTIVE_HIGH; + ret |= CFG_STAT_DISABLED; + + ret = smb347_write(smb, CFG_STAT, ret); + if (ret < 0) + goto fail_readonly; + + ret = smb347_irq_enable(smb); if (ret < 0) goto fail_readonly; smb347_set_writable(smb, false); - client->irq = irq; + smb->client->irq = irq; return 0; fail_readonly: @@ -837,7 +938,7 @@ static int smb347_irq_init(struct smb347_charger *smb, fail_gpio: gpio_free(pdata->irq_gpio); fail: - client->irq = 0; + smb->client->irq = 0; return ret; } @@ -886,13 +987,13 @@ static int smb347_battery_get_property(struct power_supply *psy, const struct smb347_charger_platform_data *pdata = smb->pdata; int ret; - ret = smb347_update_ps_status(smb); + ret = smb347_update_status(smb); if (ret < 0) return ret; switch (prop) { case POWER_SUPPLY_PROP_STATUS: - if (!smb347_is_ps_online(smb)) { + if (!smb347_is_online(smb)) { val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; } @@ -903,7 +1004,7 @@ static int smb347_battery_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CHARGE_TYPE: - if (!smb347_is_ps_online(smb)) + if (!smb347_is_online(smb)) return -ENODATA; /* @@ -935,6 +1036,44 @@ static int smb347_battery_get_property(struct power_supply *psy, val->intval = pdata->battery_info.voltage_max_design; break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + if (!smb347_is_online(smb)) + return -ENODATA; + ret = smb347_read(smb, STAT_A); + if (ret < 0) + return ret; + + ret &= STAT_A_FLOAT_VOLTAGE_MASK; + if (ret > 0x3d) + ret = 0x3d; + + val->intval = 3500000 + ret * 20000; + break; + + case POWER_SUPPLY_PROP_CURRENT_NOW: + if (!smb347_is_online(smb)) + return -ENODATA; + + ret = smb347_read(smb, STAT_B); + if (ret < 0) + return ret; + + /* + * The current value is composition of FCC and PCC values + * and we can detect which table to use from bit 5. + */ + if (ret & 0x20) { + val->intval = hw_to_current(fcc_tbl, + ARRAY_SIZE(fcc_tbl), + ret & 7); + } else { + ret >>= 3; + val->intval = hw_to_current(pcc_tbl, + ARRAY_SIZE(pcc_tbl), + ret & 7); + } + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: val->intval = pdata->battery_info.charge_full_design; break; @@ -956,58 +1095,64 @@ static enum power_supply_property smb347_battery_properties[] = { POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_MODEL_NAME, }; -static bool smb347_volatile_reg(struct device *dev, unsigned int reg) +static int smb347_debugfs_show(struct seq_file *s, void *data) { - switch (reg) { - case IRQSTAT_A: - case IRQSTAT_C: - case IRQSTAT_E: - case IRQSTAT_F: - case STAT_A: - case STAT_B: - case STAT_C: - case STAT_E: - return true; + struct smb347_charger *smb = s->private; + int ret; + u8 reg; + + seq_printf(s, "Control registers:\n"); + seq_printf(s, "==================\n"); + for (reg = CFG_CHARGE_CURRENT; reg <= CFG_ADDRESS; reg++) { + ret = smb347_read(smb, reg); + seq_printf(s, "0x%02x:\t0x%02x\n", reg, ret); + } + seq_printf(s, "\n"); + + seq_printf(s, "Command registers:\n"); + seq_printf(s, "==================\n"); + ret = smb347_read(smb, CMD_A); + seq_printf(s, "0x%02x:\t0x%02x\n", CMD_A, ret); + ret = smb347_read(smb, CMD_B); + seq_printf(s, "0x%02x:\t0x%02x\n", CMD_B, ret); + ret = smb347_read(smb, CMD_C); + seq_printf(s, "0x%02x:\t0x%02x\n", CMD_C, ret); + seq_printf(s, "\n"); + + seq_printf(s, "Interrupt status registers:\n"); + seq_printf(s, "===========================\n"); + for (reg = IRQSTAT_A; reg <= IRQSTAT_F; reg++) { + ret = smb347_read(smb, reg); + seq_printf(s, "0x%02x:\t0x%02x\n", reg, ret); + } + seq_printf(s, "\n"); + + seq_printf(s, "Status registers:\n"); + seq_printf(s, "=================\n"); + for (reg = STAT_A; reg <= STAT_E; reg++) { + ret = smb347_read(smb, reg); + seq_printf(s, "0x%02x:\t0x%02x\n", reg, ret); } - return false; + return 0; } -static bool smb347_readable_reg(struct device *dev, unsigned int reg) +static int smb347_debugfs_open(struct inode *inode, struct file *file) { - switch (reg) { - case CFG_CHARGE_CURRENT: - case CFG_CURRENT_LIMIT: - case CFG_FLOAT_VOLTAGE: - case CFG_STAT: - case CFG_PIN: - case CFG_THERM: - case CFG_SYSOK: - case CFG_OTHER: - case CFG_OTG: - case CFG_TEMP_LIMIT: - case CFG_FAULT_IRQ: - case CFG_STATUS_IRQ: - case CFG_ADDRESS: - case CMD_A: - case CMD_B: - case CMD_C: - return true; - } - - return smb347_volatile_reg(dev, reg); + return single_open(file, smb347_debugfs_show, inode->i_private); } -static const struct regmap_config smb347_regmap = { - .reg_bits = 8, - .val_bits = 8, - .max_register = SMB347_MAX_REGISTER, - .volatile_reg = smb347_volatile_reg, - .readable_reg = smb347_readable_reg, +static const struct file_operations smb347_debugfs_fops = { + .open = smb347_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; static int smb347_probe(struct i2c_client *client, @@ -1033,45 +1178,28 @@ static int smb347_probe(struct i2c_client *client, i2c_set_clientdata(client, smb); mutex_init(&smb->lock); - smb->dev = &client->dev; + smb->client = client; smb->pdata = pdata; - smb->regmap = devm_regmap_init_i2c(client, &smb347_regmap); - if (IS_ERR(smb->regmap)) - return PTR_ERR(smb->regmap); - ret = smb347_hw_init(smb); if (ret < 0) return ret; - if (smb->pdata->use_mains) { - smb->mains.name = "smb347-mains"; - smb->mains.type = POWER_SUPPLY_TYPE_MAINS; - smb->mains.get_property = smb347_mains_get_property; - smb->mains.properties = smb347_mains_properties; - smb->mains.num_properties = ARRAY_SIZE(smb347_mains_properties); - smb->mains.supplied_to = battery; - smb->mains.num_supplicants = ARRAY_SIZE(battery); - ret = power_supply_register(dev, &smb->mains); - if (ret < 0) - return ret; - } - - if (smb->pdata->use_usb) { - smb->usb.name = "smb347-usb"; - smb->usb.type = POWER_SUPPLY_TYPE_USB; - smb->usb.get_property = smb347_usb_get_property; - smb->usb.properties = smb347_usb_properties; - smb->usb.num_properties = ARRAY_SIZE(smb347_usb_properties); - smb->usb.supplied_to = battery; - smb->usb.num_supplicants = ARRAY_SIZE(battery); - ret = power_supply_register(dev, &smb->usb); - if (ret < 0) { - if (smb->pdata->use_mains) - power_supply_unregister(&smb->mains); - return ret; - } - } + smb->mains.name = "smb347-mains"; + smb->mains.type = POWER_SUPPLY_TYPE_MAINS; + smb->mains.get_property = smb347_mains_get_property; + smb->mains.properties = smb347_mains_properties; + smb->mains.num_properties = ARRAY_SIZE(smb347_mains_properties); + smb->mains.supplied_to = battery; + smb->mains.num_supplicants = ARRAY_SIZE(battery); + + smb->usb.name = "smb347-usb"; + smb->usb.type = POWER_SUPPLY_TYPE_USB; + smb->usb.get_property = smb347_usb_get_property; + smb->usb.properties = smb347_usb_properties; + smb->usb.num_properties = ARRAY_SIZE(smb347_usb_properties); + smb->usb.supplied_to = battery; + smb->usb.num_supplicants = ARRAY_SIZE(battery); smb->battery.name = "smb347-battery"; smb->battery.type = POWER_SUPPLY_TYPE_BATTERY; @@ -1079,13 +1207,20 @@ static int smb347_probe(struct i2c_client *client, smb->battery.properties = smb347_battery_properties; smb->battery.num_properties = ARRAY_SIZE(smb347_battery_properties); + ret = power_supply_register(dev, &smb->mains); + if (ret < 0) + return ret; + + ret = power_supply_register(dev, &smb->usb); + if (ret < 0) { + power_supply_unregister(&smb->mains); + return ret; + } ret = power_supply_register(dev, &smb->battery); if (ret < 0) { - if (smb->pdata->use_usb) - power_supply_unregister(&smb->usb); - if (smb->pdata->use_mains) - power_supply_unregister(&smb->mains); + power_supply_unregister(&smb->usb); + power_supply_unregister(&smb->mains); return ret; } @@ -1094,15 +1229,15 @@ static int smb347_probe(struct i2c_client *client, * interrupt support here. */ if (pdata->irq_gpio >= 0) { - ret = smb347_irq_init(smb, client); + ret = smb347_irq_init(smb); if (ret < 0) { dev_warn(dev, "failed to initialize IRQ: %d\n", ret); dev_warn(dev, "disabling IRQ support\n"); - } else { - smb347_irq_enable(smb); } } + smb->dentry = debugfs_create_file("smb347-regs", S_IRUSR, NULL, smb, + &smb347_debugfs_fops); return 0; } @@ -1110,6 +1245,9 @@ static int smb347_remove(struct i2c_client *client) { struct smb347_charger *smb = i2c_get_clientdata(client); + if (!IS_ERR_OR_NULL(smb->dentry)) + debugfs_remove(smb->dentry); + if (client->irq) { smb347_irq_disable(smb); free_irq(client->irq, smb); @@ -1117,10 +1255,8 @@ static int smb347_remove(struct i2c_client *client) } power_supply_unregister(&smb->battery); - if (smb->pdata->use_usb) - power_supply_unregister(&smb->usb); - if (smb->pdata->use_mains) - power_supply_unregister(&smb->mains); + power_supply_unregister(&smb->usb); + power_supply_unregister(&smb->mains); return 0; } @@ -1139,7 +1275,17 @@ static struct i2c_driver smb347_driver = { .id_table = smb347_id, }; -module_i2c_driver(smb347_driver); +static int __init smb347_init(void) +{ + return i2c_add_driver(&smb347_driver); +} +module_init(smb347_init); + +static void __exit smb347_exit(void) +{ + i2c_del_driver(&smb347_driver); +} +module_exit(smb347_exit); MODULE_AUTHOR("Bruce E. Robertson "); MODULE_AUTHOR("Mika Westerberg "); diff --git a/trunk/drivers/rapidio/Kconfig b/trunk/drivers/rapidio/Kconfig index 6194d35ebb97..bc8719238793 100644 --- a/trunk/drivers/rapidio/Kconfig +++ b/trunk/drivers/rapidio/Kconfig @@ -22,20 +22,6 @@ config RAPIDIO_ENABLE_RX_TX_PORTS ports for Input/Output direction to allow other traffic than Maintenance transfers. -config RAPIDIO_DMA_ENGINE - bool "DMA Engine support for RapidIO" - depends on RAPIDIO - select DMADEVICES - select DMA_ENGINE - help - Say Y here if you want to use DMA Engine frameork for RapidIO data - transfers to/from target RIO devices. RapidIO uses NREAD and - NWRITE (NWRITE_R, SWRITE) requests to transfer data between local - memory and memory on remote target device. You need a DMA controller - capable to perform data transfers to/from RapidIO. - - If you are unsure about this, say Y here. - config RAPIDIO_DEBUG bool "RapidIO subsystem debug messages" depends on RAPIDIO diff --git a/trunk/drivers/rapidio/devices/Makefile b/trunk/drivers/rapidio/devices/Makefile index 7b62860f34f8..3b7b4e2dff7c 100644 --- a/trunk/drivers/rapidio/devices/Makefile +++ b/trunk/drivers/rapidio/devices/Makefile @@ -3,6 +3,3 @@ # obj-$(CONFIG_RAPIDIO_TSI721) += tsi721.o -ifeq ($(CONFIG_RAPIDIO_DMA_ENGINE),y) -obj-$(CONFIG_RAPIDIO_TSI721) += tsi721_dma.o -endif diff --git a/trunk/drivers/rapidio/devices/tsi721.c b/trunk/drivers/rapidio/devices/tsi721.c index 722246cf20ab..30d2072f480b 100644 --- a/trunk/drivers/rapidio/devices/tsi721.c +++ b/trunk/drivers/rapidio/devices/tsi721.c @@ -108,7 +108,6 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, u16 destid, u8 hopcount, u32 offset, int len, u32 *data, int do_wr) { - void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id); struct tsi721_dma_desc *bd_ptr; u32 rd_count, swr_ptr, ch_stat; int i, err = 0; @@ -117,9 +116,10 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32))) return -EINVAL; - bd_ptr = priv->mdma.bd_base; + bd_ptr = priv->bdma[TSI721_DMACH_MAINT].bd_base; - rd_count = ioread32(regs + TSI721_DMAC_DRDCNT); + rd_count = ioread32( + priv->regs + TSI721_DMAC_DRDCNT(TSI721_DMACH_MAINT)); /* Initialize DMA descriptor */ bd_ptr[0].type_id = cpu_to_le32((DTYPE2 << 29) | (op << 19) | destid); @@ -134,18 +134,19 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, mb(); /* Start DMA operation */ - iowrite32(rd_count + 2, regs + TSI721_DMAC_DWRCNT); - ioread32(regs + TSI721_DMAC_DWRCNT); + iowrite32(rd_count + 2, + priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); + ioread32(priv->regs + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); i = 0; /* Wait until DMA transfer is finished */ - while ((ch_stat = ioread32(regs + TSI721_DMAC_STS)) - & TSI721_DMAC_STS_RUN) { + while ((ch_stat = ioread32(priv->regs + + TSI721_DMAC_STS(TSI721_DMACH_MAINT))) & TSI721_DMAC_STS_RUN) { udelay(1); if (++i >= 5000000) { dev_dbg(&priv->pdev->dev, "%s : DMA[%d] read timeout ch_status=%x\n", - __func__, priv->mdma.ch_id, ch_stat); + __func__, TSI721_DMACH_MAINT, ch_stat); if (!do_wr) *data = 0xffffffff; err = -EIO; @@ -161,10 +162,13 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, __func__, ch_stat); dev_dbg(&priv->pdev->dev, "OP=%d : destid=%x hc=%x off=%x\n", do_wr ? MAINT_WR : MAINT_RD, destid, hopcount, offset); - iowrite32(TSI721_DMAC_INT_ALL, regs + TSI721_DMAC_INT); - iowrite32(TSI721_DMAC_CTL_INIT, regs + TSI721_DMAC_CTL); + iowrite32(TSI721_DMAC_INT_ALL, + priv->regs + TSI721_DMAC_INT(TSI721_DMACH_MAINT)); + iowrite32(TSI721_DMAC_CTL_INIT, + priv->regs + TSI721_DMAC_CTL(TSI721_DMACH_MAINT)); udelay(10); - iowrite32(0, regs + TSI721_DMAC_DWRCNT); + iowrite32(0, priv->regs + + TSI721_DMAC_DWRCNT(TSI721_DMACH_MAINT)); udelay(1); if (!do_wr) *data = 0xffffffff; @@ -180,8 +184,8 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, * NOTE: Skipping check and clear FIFO entries because we are waiting * for transfer to be completed. */ - swr_ptr = ioread32(regs + TSI721_DMAC_DSWP); - iowrite32(swr_ptr, regs + TSI721_DMAC_DSRP); + swr_ptr = ioread32(priv->regs + TSI721_DMAC_DSWP(TSI721_DMACH_MAINT)); + iowrite32(swr_ptr, priv->regs + TSI721_DMAC_DSRP(TSI721_DMACH_MAINT)); err_out: return err; @@ -537,22 +541,6 @@ static irqreturn_t tsi721_irqhandler(int irq, void *ptr) tsi721_pw_handler(mport); } -#ifdef CONFIG_RAPIDIO_DMA_ENGINE - if (dev_int & TSI721_DEV_INT_BDMA_CH) { - int ch; - - if (dev_ch_int & TSI721_INT_BDMA_CHAN_M) { - dev_dbg(&priv->pdev->dev, - "IRQ from DMA channel 0x%08x\n", dev_ch_int); - - for (ch = 0; ch < TSI721_DMA_MAXCH; ch++) { - if (!(dev_ch_int & TSI721_INT_BDMA_CHAN(ch))) - continue; - tsi721_bdma_handler(&priv->bdma[ch]); - } - } - } -#endif return IRQ_HANDLED; } @@ -565,26 +553,18 @@ static void tsi721_interrupts_init(struct tsi721_device *priv) priv->regs + TSI721_SR_CHINT(IDB_QUEUE)); iowrite32(TSI721_SR_CHINT_IDBQRCV, priv->regs + TSI721_SR_CHINTE(IDB_QUEUE)); + iowrite32(TSI721_INT_SR2PC_CHAN(IDB_QUEUE), + priv->regs + TSI721_DEV_CHAN_INTE); /* Enable SRIO MAC interrupts */ iowrite32(TSI721_RIO_EM_DEV_INT_EN_INT, priv->regs + TSI721_RIO_EM_DEV_INT_EN); - /* Enable interrupts from channels in use */ -#ifdef CONFIG_RAPIDIO_DMA_ENGINE - intr = TSI721_INT_SR2PC_CHAN(IDB_QUEUE) | - (TSI721_INT_BDMA_CHAN_M & - ~TSI721_INT_BDMA_CHAN(TSI721_DMACH_MAINT)); -#else - intr = TSI721_INT_SR2PC_CHAN(IDB_QUEUE); -#endif - iowrite32(intr, priv->regs + TSI721_DEV_CHAN_INTE); - if (priv->flags & TSI721_USING_MSIX) intr = TSI721_DEV_INT_SRIO; else intr = TSI721_DEV_INT_SR2PC_CH | TSI721_DEV_INT_SRIO | - TSI721_DEV_INT_SMSG_CH | TSI721_DEV_INT_BDMA_CH; + TSI721_DEV_INT_SMSG_CH; iowrite32(intr, priv->regs + TSI721_DEV_INTE); ioread32(priv->regs + TSI721_DEV_INTE); @@ -735,29 +715,12 @@ static int tsi721_enable_msix(struct tsi721_device *priv) TSI721_MSIX_OMSG_INT(i); } -#ifdef CONFIG_RAPIDIO_DMA_ENGINE - /* - * Initialize MSI-X entries for Block DMA Engine: - * this driver supports XXX DMA channels - * (one is reserved for SRIO maintenance transactions) - */ - for (i = 0; i < TSI721_DMA_CHNUM; i++) { - entries[TSI721_VECT_DMA0_DONE + i].entry = - TSI721_MSIX_DMACH_DONE(i); - entries[TSI721_VECT_DMA0_INT + i].entry = - TSI721_MSIX_DMACH_INT(i); - } -#endif /* CONFIG_RAPIDIO_DMA_ENGINE */ - err = pci_enable_msix(priv->pdev, entries, ARRAY_SIZE(entries)); if (err) { if (err > 0) dev_info(&priv->pdev->dev, "Only %d MSI-X vectors available, " "not using MSI-X\n", err); - else - dev_err(&priv->pdev->dev, - "Failed to enable MSI-X (err=%d)\n", err); return err; } @@ -797,22 +760,6 @@ static int tsi721_enable_msix(struct tsi721_device *priv) i, pci_name(priv->pdev)); } -#ifdef CONFIG_RAPIDIO_DMA_ENGINE - for (i = 0; i < TSI721_DMA_CHNUM; i++) { - priv->msix[TSI721_VECT_DMA0_DONE + i].vector = - entries[TSI721_VECT_DMA0_DONE + i].vector; - snprintf(priv->msix[TSI721_VECT_DMA0_DONE + i].irq_name, - IRQ_DEVICE_NAME_MAX, DRV_NAME "-dmad%d@pci:%s", - i, pci_name(priv->pdev)); - - priv->msix[TSI721_VECT_DMA0_INT + i].vector = - entries[TSI721_VECT_DMA0_INT + i].vector; - snprintf(priv->msix[TSI721_VECT_DMA0_INT + i].irq_name, - IRQ_DEVICE_NAME_MAX, DRV_NAME "-dmai%d@pci:%s", - i, pci_name(priv->pdev)); - } -#endif /* CONFIG_RAPIDIO_DMA_ENGINE */ - return 0; } #endif /* CONFIG_PCI_MSI */ @@ -941,34 +888,20 @@ static void tsi721_doorbell_free(struct tsi721_device *priv) priv->idb_base = NULL; } -/** - * tsi721_bdma_maint_init - Initialize maintenance request BDMA channel. - * @priv: pointer to tsi721 private data - * - * Initialize BDMA channel allocated for RapidIO maintenance read/write - * request generation - * Returns %0 on success or %-ENOMEM on failure. - */ -static int tsi721_bdma_maint_init(struct tsi721_device *priv) +static int tsi721_bdma_ch_init(struct tsi721_device *priv, int chnum) { struct tsi721_dma_desc *bd_ptr; u64 *sts_ptr; dma_addr_t bd_phys, sts_phys; int sts_size; - int bd_num = 2; - void __iomem *regs; + int bd_num = priv->bdma[chnum].bd_num; - dev_dbg(&priv->pdev->dev, - "Init Block DMA Engine for Maintenance requests, CH%d\n", - TSI721_DMACH_MAINT); + dev_dbg(&priv->pdev->dev, "Init Block DMA Engine, CH%d\n", chnum); /* * Initialize DMA channel for maintenance requests */ - priv->mdma.ch_id = TSI721_DMACH_MAINT; - regs = priv->regs + TSI721_DMAC_BASE(TSI721_DMACH_MAINT); - /* Allocate space for DMA descriptors */ bd_ptr = dma_zalloc_coherent(&priv->pdev->dev, bd_num * sizeof(struct tsi721_dma_desc), @@ -976,9 +909,8 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv) if (!bd_ptr) return -ENOMEM; - priv->mdma.bd_num = bd_num; - priv->mdma.bd_phys = bd_phys; - priv->mdma.bd_base = bd_ptr; + priv->bdma[chnum].bd_phys = bd_phys; + priv->bdma[chnum].bd_base = bd_ptr; dev_dbg(&priv->pdev->dev, "DMA descriptors @ %p (phys = %llx)\n", bd_ptr, (unsigned long long)bd_phys); @@ -995,13 +927,13 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv) dma_free_coherent(&priv->pdev->dev, bd_num * sizeof(struct tsi721_dma_desc), bd_ptr, bd_phys); - priv->mdma.bd_base = NULL; + priv->bdma[chnum].bd_base = NULL; return -ENOMEM; } - priv->mdma.sts_phys = sts_phys; - priv->mdma.sts_base = sts_ptr; - priv->mdma.sts_size = sts_size; + priv->bdma[chnum].sts_phys = sts_phys; + priv->bdma[chnum].sts_base = sts_ptr; + priv->bdma[chnum].sts_size = sts_size; dev_dbg(&priv->pdev->dev, "desc status FIFO @ %p (phys = %llx) size=0x%x\n", @@ -1014,61 +946,83 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv) bd_ptr[bd_num - 1].next_hi = cpu_to_le32((u64)bd_phys >> 32); /* Setup DMA descriptor pointers */ - iowrite32(((u64)bd_phys >> 32), regs + TSI721_DMAC_DPTRH); + iowrite32(((u64)bd_phys >> 32), + priv->regs + TSI721_DMAC_DPTRH(chnum)); iowrite32(((u64)bd_phys & TSI721_DMAC_DPTRL_MASK), - regs + TSI721_DMAC_DPTRL); + priv->regs + TSI721_DMAC_DPTRL(chnum)); /* Setup descriptor status FIFO */ - iowrite32(((u64)sts_phys >> 32), regs + TSI721_DMAC_DSBH); + iowrite32(((u64)sts_phys >> 32), + priv->regs + TSI721_DMAC_DSBH(chnum)); iowrite32(((u64)sts_phys & TSI721_DMAC_DSBL_MASK), - regs + TSI721_DMAC_DSBL); + priv->regs + TSI721_DMAC_DSBL(chnum)); iowrite32(TSI721_DMAC_DSSZ_SIZE(sts_size), - regs + TSI721_DMAC_DSSZ); + priv->regs + TSI721_DMAC_DSSZ(chnum)); /* Clear interrupt bits */ - iowrite32(TSI721_DMAC_INT_ALL, regs + TSI721_DMAC_INT); + iowrite32(TSI721_DMAC_INT_ALL, + priv->regs + TSI721_DMAC_INT(chnum)); - ioread32(regs + TSI721_DMAC_INT); + ioread32(priv->regs + TSI721_DMAC_INT(chnum)); /* Toggle DMA channel initialization */ - iowrite32(TSI721_DMAC_CTL_INIT, regs + TSI721_DMAC_CTL); - ioread32(regs + TSI721_DMAC_CTL); + iowrite32(TSI721_DMAC_CTL_INIT, priv->regs + TSI721_DMAC_CTL(chnum)); + ioread32(priv->regs + TSI721_DMAC_CTL(chnum)); udelay(10); return 0; } -static int tsi721_bdma_maint_free(struct tsi721_device *priv) +static int tsi721_bdma_ch_free(struct tsi721_device *priv, int chnum) { u32 ch_stat; - struct tsi721_bdma_maint *mdma = &priv->mdma; - void __iomem *regs = priv->regs + TSI721_DMAC_BASE(mdma->ch_id); - if (mdma->bd_base == NULL) + if (priv->bdma[chnum].bd_base == NULL) return 0; /* Check if DMA channel still running */ - ch_stat = ioread32(regs + TSI721_DMAC_STS); + ch_stat = ioread32(priv->regs + TSI721_DMAC_STS(chnum)); if (ch_stat & TSI721_DMAC_STS_RUN) return -EFAULT; /* Put DMA channel into init state */ - iowrite32(TSI721_DMAC_CTL_INIT, regs + TSI721_DMAC_CTL); + iowrite32(TSI721_DMAC_CTL_INIT, + priv->regs + TSI721_DMAC_CTL(chnum)); /* Free space allocated for DMA descriptors */ dma_free_coherent(&priv->pdev->dev, - mdma->bd_num * sizeof(struct tsi721_dma_desc), - mdma->bd_base, mdma->bd_phys); - mdma->bd_base = NULL; + priv->bdma[chnum].bd_num * sizeof(struct tsi721_dma_desc), + priv->bdma[chnum].bd_base, priv->bdma[chnum].bd_phys); + priv->bdma[chnum].bd_base = NULL; /* Free space allocated for status FIFO */ dma_free_coherent(&priv->pdev->dev, - mdma->sts_size * sizeof(struct tsi721_dma_sts), - mdma->sts_base, mdma->sts_phys); - mdma->sts_base = NULL; + priv->bdma[chnum].sts_size * sizeof(struct tsi721_dma_sts), + priv->bdma[chnum].sts_base, priv->bdma[chnum].sts_phys); + priv->bdma[chnum].sts_base = NULL; + return 0; +} + +static int tsi721_bdma_init(struct tsi721_device *priv) +{ + /* Initialize BDMA channel allocated for RapidIO maintenance read/write + * request generation + */ + priv->bdma[TSI721_DMACH_MAINT].bd_num = 2; + if (tsi721_bdma_ch_init(priv, TSI721_DMACH_MAINT)) { + dev_err(&priv->pdev->dev, "Unable to initialize maintenance DMA" + " channel %d, aborting\n", TSI721_DMACH_MAINT); + return -ENOMEM; + } + return 0; } +static void tsi721_bdma_free(struct tsi721_device *priv) +{ + tsi721_bdma_ch_free(priv, TSI721_DMACH_MAINT); +} + /* Enable Inbound Messaging Interrupts */ static void tsi721_imsg_interrupt_enable(struct tsi721_device *priv, int ch, @@ -2081,8 +2035,7 @@ static void tsi721_disable_ints(struct tsi721_device *priv) /* Disable all BDMA Channel interrupts */ for (ch = 0; ch < TSI721_DMA_MAXCH; ch++) - iowrite32(0, - priv->regs + TSI721_DMAC_BASE(ch) + TSI721_DMAC_INTE); + iowrite32(0, priv->regs + TSI721_DMAC_INTE(ch)); /* Disable all general BDMA interrupts */ iowrite32(0, priv->regs + TSI721_BDMA_INTE); @@ -2151,7 +2104,6 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) mport->phy_type = RIO_PHY_SERIAL; mport->priv = (void *)priv; mport->phys_efptr = 0x100; - priv->mport = mport; INIT_LIST_HEAD(&mport->dbells); @@ -2177,21 +2129,17 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) if (!err) { tsi721_interrupts_init(priv); ops->pwenable = tsi721_pw_enable; - } else { + } else dev_err(&pdev->dev, "Unable to get assigned PCI IRQ " "vector %02X err=0x%x\n", pdev->irq, err); - goto err_exit; - } -#ifdef CONFIG_RAPIDIO_DMA_ENGINE - tsi721_register_dma(priv); -#endif /* Enable SRIO link */ iowrite32(ioread32(priv->regs + TSI721_DEVCTL) | TSI721_DEVCTL_SRBOOT_CMPL, priv->regs + TSI721_DEVCTL); rio_register_mport(mport); + priv->mport = mport; if (mport->host_deviceid >= 0) iowrite32(RIO_PORT_GEN_HOST | RIO_PORT_GEN_MASTER | @@ -2201,11 +2149,6 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) iowrite32(0, priv->regs + (0x100 + RIO_PORT_GEN_CTL_CSR)); return 0; - -err_exit: - kfree(mport); - kfree(ops); - return err; } static int __devinit tsi721_probe(struct pci_dev *pdev, @@ -2351,7 +2294,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, tsi721_init_pc2sr_mapping(priv); tsi721_init_sr2pc_mapping(priv); - if (tsi721_bdma_maint_init(priv)) { + if (tsi721_bdma_init(priv)) { dev_err(&pdev->dev, "BDMA initialization failed, aborting\n"); err = -ENOMEM; goto err_unmap_bars; @@ -2376,7 +2319,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, err_free_consistent: tsi721_doorbell_free(priv); err_free_bdma: - tsi721_bdma_maint_free(priv); + tsi721_bdma_free(priv); err_unmap_bars: if (priv->regs) iounmap(priv->regs); diff --git a/trunk/drivers/rapidio/devices/tsi721.h b/trunk/drivers/rapidio/devices/tsi721.h index 59de9d7be346..1c226b31af13 100644 --- a/trunk/drivers/rapidio/devices/tsi721.h +++ b/trunk/drivers/rapidio/devices/tsi721.h @@ -167,8 +167,6 @@ #define TSI721_DEV_INTE 0x29840 #define TSI721_DEV_INT 0x29844 #define TSI721_DEV_INTSET 0x29848 -#define TSI721_DEV_INT_BDMA_CH 0x00002000 -#define TSI721_DEV_INT_BDMA_NCH 0x00001000 #define TSI721_DEV_INT_SMSG_CH 0x00000800 #define TSI721_DEV_INT_SMSG_NCH 0x00000400 #define TSI721_DEV_INT_SR2PC_CH 0x00000200 @@ -183,8 +181,6 @@ #define TSI721_INT_IMSG_CHAN(x) (1 << (16 + (x))) #define TSI721_INT_OMSG_CHAN_M 0x0000ff00 #define TSI721_INT_OMSG_CHAN(x) (1 << (8 + (x))) -#define TSI721_INT_BDMA_CHAN_M 0x000000ff -#define TSI721_INT_BDMA_CHAN(x) (1 << (x)) /* * PC2SR block registers @@ -239,16 +235,14 @@ * x = 0..7 */ -#define TSI721_DMAC_BASE(x) (0x51000 + (x) * 0x1000) +#define TSI721_DMAC_DWRCNT(x) (0x51000 + (x) * 0x1000) +#define TSI721_DMAC_DRDCNT(x) (0x51004 + (x) * 0x1000) -#define TSI721_DMAC_DWRCNT 0x000 -#define TSI721_DMAC_DRDCNT 0x004 - -#define TSI721_DMAC_CTL 0x008 +#define TSI721_DMAC_CTL(x) (0x51008 + (x) * 0x1000) #define TSI721_DMAC_CTL_SUSP 0x00000002 #define TSI721_DMAC_CTL_INIT 0x00000001 -#define TSI721_DMAC_INT 0x00c +#define TSI721_DMAC_INT(x) (0x5100c + (x) * 0x1000) #define TSI721_DMAC_INT_STFULL 0x00000010 #define TSI721_DMAC_INT_DONE 0x00000008 #define TSI721_DMAC_INT_SUSP 0x00000004 @@ -256,33 +250,34 @@ #define TSI721_DMAC_INT_IOFDONE 0x00000001 #define TSI721_DMAC_INT_ALL 0x0000001f -#define TSI721_DMAC_INTSET 0x010 +#define TSI721_DMAC_INTSET(x) (0x51010 + (x) * 0x1000) -#define TSI721_DMAC_STS 0x014 +#define TSI721_DMAC_STS(x) (0x51014 + (x) * 0x1000) #define TSI721_DMAC_STS_ABORT 0x00400000 #define TSI721_DMAC_STS_RUN 0x00200000 #define TSI721_DMAC_STS_CS 0x001f0000 -#define TSI721_DMAC_INTE 0x018 +#define TSI721_DMAC_INTE(x) (0x51018 + (x) * 0x1000) -#define TSI721_DMAC_DPTRL 0x024 +#define TSI721_DMAC_DPTRL(x) (0x51024 + (x) * 0x1000) #define TSI721_DMAC_DPTRL_MASK 0xffffffe0 -#define TSI721_DMAC_DPTRH 0x028 +#define TSI721_DMAC_DPTRH(x) (0x51028 + (x) * 0x1000) -#define TSI721_DMAC_DSBL 0x02c +#define TSI721_DMAC_DSBL(x) (0x5102c + (x) * 0x1000) #define TSI721_DMAC_DSBL_MASK 0xffffffc0 -#define TSI721_DMAC_DSBH 0x030 +#define TSI721_DMAC_DSBH(x) (0x51030 + (x) * 0x1000) -#define TSI721_DMAC_DSSZ 0x034 +#define TSI721_DMAC_DSSZ(x) (0x51034 + (x) * 0x1000) #define TSI721_DMAC_DSSZ_SIZE_M 0x0000000f #define TSI721_DMAC_DSSZ_SIZE(size) (__fls(size) - 4) -#define TSI721_DMAC_DSRP 0x038 + +#define TSI721_DMAC_DSRP(x) (0x51038 + (x) * 0x1000) #define TSI721_DMAC_DSRP_MASK 0x0007ffff -#define TSI721_DMAC_DSWP 0x03c +#define TSI721_DMAC_DSWP(x) (0x5103c + (x) * 0x1000) #define TSI721_DMAC_DSWP_MASK 0x0007ffff #define TSI721_BDMA_INTE 0x5f000 @@ -617,8 +612,6 @@ enum dma_rtype { #define TSI721_DMACH_MAINT 0 /* DMA channel for maint requests */ #define TSI721_DMACH_MAINT_NBD 32 /* Number of BDs for maint requests */ -#define TSI721_DMACH_DMA 1 /* DMA channel for data transfers */ - #define MSG_DMA_ENTRY_INX_TO_SIZE(x) ((0x10 << (x)) & 0xFFFF0) enum tsi721_smsg_int_flag { @@ -633,48 +626,7 @@ enum tsi721_smsg_int_flag { /* Structures */ -#ifdef CONFIG_RAPIDIO_DMA_ENGINE - -struct tsi721_tx_desc { - struct dma_async_tx_descriptor txd; - struct tsi721_dma_desc *hw_desc; - u16 destid; - /* low 64-bits of 66-bit RIO address */ - u64 rio_addr; - /* upper 2-bits of 66-bit RIO address */ - u8 rio_addr_u; - bool interrupt; - struct list_head desc_node; - struct list_head tx_list; -}; - struct tsi721_bdma_chan { - int id; - void __iomem *regs; - int bd_num; /* number of buffer descriptors */ - void *bd_base; /* start of DMA descriptors */ - dma_addr_t bd_phys; - void *sts_base; /* start of DMA BD status FIFO */ - dma_addr_t sts_phys; - int sts_size; - u32 sts_rdptr; - u32 wr_count; - u32 wr_count_next; - - struct dma_chan dchan; - struct tsi721_tx_desc *tx_desc; - spinlock_t lock; - struct list_head active_list; - struct list_head queue; - struct list_head free_list; - dma_cookie_t completed_cookie; - struct tasklet_struct tasklet; -}; - -#endif /* CONFIG_RAPIDIO_DMA_ENGINE */ - -struct tsi721_bdma_maint { - int ch_id; /* BDMA channel number */ int bd_num; /* number of buffer descriptors */ void *bd_base; /* start of DMA descriptors */ dma_addr_t bd_phys; @@ -769,24 +721,6 @@ enum tsi721_msix_vect { TSI721_VECT_IMB1_INT, TSI721_VECT_IMB2_INT, TSI721_VECT_IMB3_INT, -#ifdef CONFIG_RAPIDIO_DMA_ENGINE - TSI721_VECT_DMA0_DONE, - TSI721_VECT_DMA1_DONE, - TSI721_VECT_DMA2_DONE, - TSI721_VECT_DMA3_DONE, - TSI721_VECT_DMA4_DONE, - TSI721_VECT_DMA5_DONE, - TSI721_VECT_DMA6_DONE, - TSI721_VECT_DMA7_DONE, - TSI721_VECT_DMA0_INT, - TSI721_VECT_DMA1_INT, - TSI721_VECT_DMA2_INT, - TSI721_VECT_DMA3_INT, - TSI721_VECT_DMA4_INT, - TSI721_VECT_DMA5_INT, - TSI721_VECT_DMA6_INT, - TSI721_VECT_DMA7_INT, -#endif /* CONFIG_RAPIDIO_DMA_ENGINE */ TSI721_VECT_MAX }; @@ -820,11 +754,7 @@ struct tsi721_device { u32 pw_discard_count; /* BDMA Engine */ - struct tsi721_bdma_maint mdma; /* Maintenance rd/wr request channel */ - -#ifdef CONFIG_RAPIDIO_DMA_ENGINE struct tsi721_bdma_chan bdma[TSI721_DMA_CHNUM]; -#endif /* Inbound Messaging */ int imsg_init[TSI721_IMSG_CHNUM]; @@ -835,9 +765,4 @@ struct tsi721_device { struct tsi721_omsg_ring omsg_ring[TSI721_OMSG_CHNUM]; }; -#ifdef CONFIG_RAPIDIO_DMA_ENGINE -extern void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan); -extern int __devinit tsi721_register_dma(struct tsi721_device *priv); -#endif - #endif diff --git a/trunk/drivers/rapidio/devices/tsi721_dma.c b/trunk/drivers/rapidio/devices/tsi721_dma.c deleted file mode 100644 index 92e06a5c62ec..000000000000 --- a/trunk/drivers/rapidio/devices/tsi721_dma.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - * DMA Engine support for Tsi721 PCIExpress-to-SRIO bridge - * - * Copyright 2011 Integrated Device Technology, Inc. - * Alexandre Bounine - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tsi721.h" - -static inline struct tsi721_bdma_chan *to_tsi721_chan(struct dma_chan *chan) -{ - return container_of(chan, struct tsi721_bdma_chan, dchan); -} - -static inline struct tsi721_device *to_tsi721(struct dma_device *ddev) -{ - return container_of(ddev, struct rio_mport, dma)->priv; -} - -static inline -struct tsi721_tx_desc *to_tsi721_desc(struct dma_async_tx_descriptor *txd) -{ - return container_of(txd, struct tsi721_tx_desc, txd); -} - -static inline -struct tsi721_tx_desc *tsi721_dma_first_active( - struct tsi721_bdma_chan *bdma_chan) -{ - return list_first_entry(&bdma_chan->active_list, - struct tsi721_tx_desc, desc_node); -} - -static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan) -{ - struct tsi721_dma_desc *bd_ptr; - struct device *dev = bdma_chan->dchan.device->dev; - u64 *sts_ptr; - dma_addr_t bd_phys; - dma_addr_t sts_phys; - int sts_size; - int bd_num = bdma_chan->bd_num; - - dev_dbg(dev, "Init Block DMA Engine, CH%d\n", bdma_chan->id); - - /* Allocate space for DMA descriptors */ - bd_ptr = dma_zalloc_coherent(dev, - bd_num * sizeof(struct tsi721_dma_desc), - &bd_phys, GFP_KERNEL); - if (!bd_ptr) - return -ENOMEM; - - bdma_chan->bd_phys = bd_phys; - bdma_chan->bd_base = bd_ptr; - - dev_dbg(dev, "DMA descriptors @ %p (phys = %llx)\n", - bd_ptr, (unsigned long long)bd_phys); - - /* Allocate space for descriptor status FIFO */ - sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ? - bd_num : TSI721_DMA_MINSTSSZ; - sts_size = roundup_pow_of_two(sts_size); - sts_ptr = dma_zalloc_coherent(dev, - sts_size * sizeof(struct tsi721_dma_sts), - &sts_phys, GFP_KERNEL); - if (!sts_ptr) { - /* Free space allocated for DMA descriptors */ - dma_free_coherent(dev, - bd_num * sizeof(struct tsi721_dma_desc), - bd_ptr, bd_phys); - bdma_chan->bd_base = NULL; - return -ENOMEM; - } - - bdma_chan->sts_phys = sts_phys; - bdma_chan->sts_base = sts_ptr; - bdma_chan->sts_size = sts_size; - - dev_dbg(dev, - "desc status FIFO @ %p (phys = %llx) size=0x%x\n", - sts_ptr, (unsigned long long)sts_phys, sts_size); - - /* Initialize DMA descriptors ring */ - bd_ptr[bd_num - 1].type_id = cpu_to_le32(DTYPE3 << 29); - bd_ptr[bd_num - 1].next_lo = cpu_to_le32((u64)bd_phys & - TSI721_DMAC_DPTRL_MASK); - bd_ptr[bd_num - 1].next_hi = cpu_to_le32((u64)bd_phys >> 32); - - /* Setup DMA descriptor pointers */ - iowrite32(((u64)bd_phys >> 32), - bdma_chan->regs + TSI721_DMAC_DPTRH); - iowrite32(((u64)bd_phys & TSI721_DMAC_DPTRL_MASK), - bdma_chan->regs + TSI721_DMAC_DPTRL); - - /* Setup descriptor status FIFO */ - iowrite32(((u64)sts_phys >> 32), - bdma_chan->regs + TSI721_DMAC_DSBH); - iowrite32(((u64)sts_phys & TSI721_DMAC_DSBL_MASK), - bdma_chan->regs + TSI721_DMAC_DSBL); - iowrite32(TSI721_DMAC_DSSZ_SIZE(sts_size), - bdma_chan->regs + TSI721_DMAC_DSSZ); - - /* Clear interrupt bits */ - iowrite32(TSI721_DMAC_INT_ALL, - bdma_chan->regs + TSI721_DMAC_INT); - - ioread32(bdma_chan->regs + TSI721_DMAC_INT); - - /* Toggle DMA channel initialization */ - iowrite32(TSI721_DMAC_CTL_INIT, bdma_chan->regs + TSI721_DMAC_CTL); - ioread32(bdma_chan->regs + TSI721_DMAC_CTL); - bdma_chan->wr_count = bdma_chan->wr_count_next = 0; - bdma_chan->sts_rdptr = 0; - udelay(10); - - return 0; -} - -static int tsi721_bdma_ch_free(struct tsi721_bdma_chan *bdma_chan) -{ - u32 ch_stat; - - if (bdma_chan->bd_base == NULL) - return 0; - - /* Check if DMA channel still running */ - ch_stat = ioread32(bdma_chan->regs + TSI721_DMAC_STS); - if (ch_stat & TSI721_DMAC_STS_RUN) - return -EFAULT; - - /* Put DMA channel into init state */ - iowrite32(TSI721_DMAC_CTL_INIT, bdma_chan->regs + TSI721_DMAC_CTL); - - /* Free space allocated for DMA descriptors */ - dma_free_coherent(bdma_chan->dchan.device->dev, - bdma_chan->bd_num * sizeof(struct tsi721_dma_desc), - bdma_chan->bd_base, bdma_chan->bd_phys); - bdma_chan->bd_base = NULL; - - /* Free space allocated for status FIFO */ - dma_free_coherent(bdma_chan->dchan.device->dev, - bdma_chan->sts_size * sizeof(struct tsi721_dma_sts), - bdma_chan->sts_base, bdma_chan->sts_phys); - bdma_chan->sts_base = NULL; - return 0; -} - -static void -tsi721_bdma_interrupt_enable(struct tsi721_bdma_chan *bdma_chan, int enable) -{ - if (enable) { - /* Clear pending BDMA channel interrupts */ - iowrite32(TSI721_DMAC_INT_ALL, - bdma_chan->regs + TSI721_DMAC_INT); - ioread32(bdma_chan->regs + TSI721_DMAC_INT); - /* Enable BDMA channel interrupts */ - iowrite32(TSI721_DMAC_INT_ALL, - bdma_chan->regs + TSI721_DMAC_INTE); - } else { - /* Disable BDMA channel interrupts */ - iowrite32(0, bdma_chan->regs + TSI721_DMAC_INTE); - /* Clear pending BDMA channel interrupts */ - iowrite32(TSI721_DMAC_INT_ALL, - bdma_chan->regs + TSI721_DMAC_INT); - } - -} - -static bool tsi721_dma_is_idle(struct tsi721_bdma_chan *bdma_chan) -{ - u32 sts; - - sts = ioread32(bdma_chan->regs + TSI721_DMAC_STS); - return ((sts & TSI721_DMAC_STS_RUN) == 0); -} - -void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan) -{ - /* Disable BDMA channel interrupts */ - iowrite32(0, bdma_chan->regs + TSI721_DMAC_INTE); - - tasklet_schedule(&bdma_chan->tasklet); -} - -#ifdef CONFIG_PCI_MSI -/** - * tsi721_omsg_msix - MSI-X interrupt handler for BDMA channels - * @irq: Linux interrupt number - * @ptr: Pointer to interrupt-specific data (BDMA channel structure) - * - * Handles BDMA channel interrupts signaled using MSI-X. - */ -static irqreturn_t tsi721_bdma_msix(int irq, void *ptr) -{ - struct tsi721_bdma_chan *bdma_chan = ptr; - - tsi721_bdma_handler(bdma_chan); - return IRQ_HANDLED; -} -#endif /* CONFIG_PCI_MSI */ - -/* Must be called with the spinlock held */ -static void tsi721_start_dma(struct tsi721_bdma_chan *bdma_chan) -{ - if (!tsi721_dma_is_idle(bdma_chan)) { - dev_err(bdma_chan->dchan.device->dev, - "BUG: Attempt to start non-idle channel\n"); - return; - } - - if (bdma_chan->wr_count == bdma_chan->wr_count_next) { - dev_err(bdma_chan->dchan.device->dev, - "BUG: Attempt to start DMA with no BDs ready\n"); - return; - } - - dev_dbg(bdma_chan->dchan.device->dev, - "tx_chan: %p, chan: %d, regs: %p\n", - bdma_chan, bdma_chan->dchan.chan_id, bdma_chan->regs); - - iowrite32(bdma_chan->wr_count_next, - bdma_chan->regs + TSI721_DMAC_DWRCNT); - ioread32(bdma_chan->regs + TSI721_DMAC_DWRCNT); - - bdma_chan->wr_count = bdma_chan->wr_count_next; -} - -static void tsi721_desc_put(struct tsi721_bdma_chan *bdma_chan, - struct tsi721_tx_desc *desc) -{ - dev_dbg(bdma_chan->dchan.device->dev, - "Put desc: %p into free list\n", desc); - - if (desc) { - spin_lock_bh(&bdma_chan->lock); - list_splice_init(&desc->tx_list, &bdma_chan->free_list); - list_add(&desc->desc_node, &bdma_chan->free_list); - bdma_chan->wr_count_next = bdma_chan->wr_count; - spin_unlock_bh(&bdma_chan->lock); - } -} - -static -struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan) -{ - struct tsi721_tx_desc *tx_desc, *_tx_desc; - struct tsi721_tx_desc *ret = NULL; - int i; - - spin_lock_bh(&bdma_chan->lock); - list_for_each_entry_safe(tx_desc, _tx_desc, - &bdma_chan->free_list, desc_node) { - if (async_tx_test_ack(&tx_desc->txd)) { - list_del(&tx_desc->desc_node); - ret = tx_desc; - break; - } - dev_dbg(bdma_chan->dchan.device->dev, - "desc %p not ACKed\n", tx_desc); - } - - i = bdma_chan->wr_count_next % bdma_chan->bd_num; - if (i == bdma_chan->bd_num - 1) { - i = 0; - bdma_chan->wr_count_next++; /* skip link descriptor */ - } - - bdma_chan->wr_count_next++; - tx_desc->txd.phys = bdma_chan->bd_phys + - i * sizeof(struct tsi721_dma_desc); - tx_desc->hw_desc = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[i]; - - spin_unlock_bh(&bdma_chan->lock); - - return ret; -} - -static int -tsi721_fill_desc(struct tsi721_bdma_chan *bdma_chan, - struct tsi721_tx_desc *desc, struct scatterlist *sg, - enum dma_rtype rtype, u32 sys_size) -{ - struct tsi721_dma_desc *bd_ptr = desc->hw_desc; - u64 rio_addr; - - if (sg_dma_len(sg) > TSI721_DMAD_BCOUNT1 + 1) { - dev_err(bdma_chan->dchan.device->dev, - "SG element is too large\n"); - return -EINVAL; - } - - dev_dbg(bdma_chan->dchan.device->dev, - "desc: 0x%llx, addr: 0x%llx len: 0x%x\n", - (u64)desc->txd.phys, (unsigned long long)sg_dma_address(sg), - sg_dma_len(sg)); - - dev_dbg(bdma_chan->dchan.device->dev, - "bd_ptr = %p did=%d raddr=0x%llx\n", - bd_ptr, desc->destid, desc->rio_addr); - - /* Initialize DMA descriptor */ - bd_ptr->type_id = cpu_to_le32((DTYPE1 << 29) | - (rtype << 19) | desc->destid); - if (desc->interrupt) - bd_ptr->type_id |= cpu_to_le32(TSI721_DMAD_IOF); - bd_ptr->bcount = cpu_to_le32(((desc->rio_addr & 0x3) << 30) | - (sys_size << 26) | sg_dma_len(sg)); - rio_addr = (desc->rio_addr >> 2) | - ((u64)(desc->rio_addr_u & 0x3) << 62); - bd_ptr->raddr_lo = cpu_to_le32(rio_addr & 0xffffffff); - bd_ptr->raddr_hi = cpu_to_le32(rio_addr >> 32); - bd_ptr->t1.bufptr_lo = cpu_to_le32( - (u64)sg_dma_address(sg) & 0xffffffff); - bd_ptr->t1.bufptr_hi = cpu_to_le32((u64)sg_dma_address(sg) >> 32); - bd_ptr->t1.s_dist = 0; - bd_ptr->t1.s_size = 0; - - return 0; -} - -static void tsi721_dma_chain_complete(struct tsi721_bdma_chan *bdma_chan, - struct tsi721_tx_desc *desc) -{ - struct dma_async_tx_descriptor *txd = &desc->txd; - dma_async_tx_callback callback = txd->callback; - void *param = txd->callback_param; - - list_splice_init(&desc->tx_list, &bdma_chan->free_list); - list_move(&desc->desc_node, &bdma_chan->free_list); - bdma_chan->completed_cookie = txd->cookie; - - if (callback) - callback(param); -} - -static void tsi721_dma_complete_all(struct tsi721_bdma_chan *bdma_chan) -{ - struct tsi721_tx_desc *desc, *_d; - LIST_HEAD(list); - - BUG_ON(!tsi721_dma_is_idle(bdma_chan)); - - if (!list_empty(&bdma_chan->queue)) - tsi721_start_dma(bdma_chan); - - list_splice_init(&bdma_chan->active_list, &list); - list_splice_init(&bdma_chan->queue, &bdma_chan->active_list); - - list_for_each_entry_safe(desc, _d, &list, desc_node) - tsi721_dma_chain_complete(bdma_chan, desc); -} - -static void tsi721_clr_stat(struct tsi721_bdma_chan *bdma_chan) -{ - u32 srd_ptr; - u64 *sts_ptr; - int i, j; - - /* Check and clear descriptor status FIFO entries */ - srd_ptr = bdma_chan->sts_rdptr; - sts_ptr = bdma_chan->sts_base; - j = srd_ptr * 8; - while (sts_ptr[j]) { - for (i = 0; i < 8 && sts_ptr[j]; i++, j++) - sts_ptr[j] = 0; - - ++srd_ptr; - srd_ptr %= bdma_chan->sts_size; - j = srd_ptr * 8; - } - - iowrite32(srd_ptr, bdma_chan->regs + TSI721_DMAC_DSRP); - bdma_chan->sts_rdptr = srd_ptr; -} - -static void tsi721_advance_work(struct tsi721_bdma_chan *bdma_chan) -{ - if (list_empty(&bdma_chan->active_list) || - list_is_singular(&bdma_chan->active_list)) { - dev_dbg(bdma_chan->dchan.device->dev, - "%s: Active_list empty\n", __func__); - tsi721_dma_complete_all(bdma_chan); - } else { - dev_dbg(bdma_chan->dchan.device->dev, - "%s: Active_list NOT empty\n", __func__); - tsi721_dma_chain_complete(bdma_chan, - tsi721_dma_first_active(bdma_chan)); - tsi721_start_dma(bdma_chan); - } -} - -static void tsi721_dma_tasklet(unsigned long data) -{ - struct tsi721_bdma_chan *bdma_chan = (struct tsi721_bdma_chan *)data; - u32 dmac_int, dmac_sts; - - dmac_int = ioread32(bdma_chan->regs + TSI721_DMAC_INT); - dev_dbg(bdma_chan->dchan.device->dev, "%s: DMAC%d_INT = 0x%x\n", - __func__, bdma_chan->id, dmac_int); - /* Clear channel interrupts */ - iowrite32(dmac_int, bdma_chan->regs + TSI721_DMAC_INT); - - if (dmac_int & TSI721_DMAC_INT_ERR) { - dmac_sts = ioread32(bdma_chan->regs + TSI721_DMAC_STS); - dev_err(bdma_chan->dchan.device->dev, - "%s: DMA ERROR - DMAC%d_STS = 0x%x\n", - __func__, bdma_chan->id, dmac_sts); - } - - if (dmac_int & TSI721_DMAC_INT_STFULL) { - dev_err(bdma_chan->dchan.device->dev, - "%s: DMAC%d descriptor status FIFO is full\n", - __func__, bdma_chan->id); - } - - if (dmac_int & (TSI721_DMAC_INT_DONE | TSI721_DMAC_INT_IOFDONE)) { - tsi721_clr_stat(bdma_chan); - spin_lock(&bdma_chan->lock); - tsi721_advance_work(bdma_chan); - spin_unlock(&bdma_chan->lock); - } - - /* Re-Enable BDMA channel interrupts */ - iowrite32(TSI721_DMAC_INT_ALL, bdma_chan->regs + TSI721_DMAC_INTE); -} - -static dma_cookie_t tsi721_tx_submit(struct dma_async_tx_descriptor *txd) -{ - struct tsi721_tx_desc *desc = to_tsi721_desc(txd); - struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(txd->chan); - dma_cookie_t cookie; - - spin_lock_bh(&bdma_chan->lock); - - cookie = txd->chan->cookie; - if (++cookie < 0) - cookie = 1; - txd->chan->cookie = cookie; - txd->cookie = cookie; - - if (list_empty(&bdma_chan->active_list)) { - list_add_tail(&desc->desc_node, &bdma_chan->active_list); - tsi721_start_dma(bdma_chan); - } else { - list_add_tail(&desc->desc_node, &bdma_chan->queue); - } - - spin_unlock_bh(&bdma_chan->lock); - return cookie; -} - -static int tsi721_alloc_chan_resources(struct dma_chan *dchan) -{ - struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); -#ifdef CONFIG_PCI_MSI - struct tsi721_device *priv = to_tsi721(dchan->device); -#endif - struct tsi721_tx_desc *desc = NULL; - LIST_HEAD(tmp_list); - int i; - int rc; - - if (bdma_chan->bd_base) - return bdma_chan->bd_num - 1; - - /* Initialize BDMA channel */ - if (tsi721_bdma_ch_init(bdma_chan)) { - dev_err(dchan->device->dev, "Unable to initialize data DMA" - " channel %d, aborting\n", bdma_chan->id); - return -ENOMEM; - } - - /* Alocate matching number of logical descriptors */ - desc = kcalloc((bdma_chan->bd_num - 1), sizeof(struct tsi721_tx_desc), - GFP_KERNEL); - if (!desc) { - dev_err(dchan->device->dev, - "Failed to allocate logical descriptors\n"); - rc = -ENOMEM; - goto err_out; - } - - bdma_chan->tx_desc = desc; - - for (i = 0; i < bdma_chan->bd_num - 1; i++) { - dma_async_tx_descriptor_init(&desc[i].txd, dchan); - desc[i].txd.tx_submit = tsi721_tx_submit; - desc[i].txd.flags = DMA_CTRL_ACK; - INIT_LIST_HEAD(&desc[i].tx_list); - list_add_tail(&desc[i].desc_node, &tmp_list); - } - - spin_lock_bh(&bdma_chan->lock); - list_splice(&tmp_list, &bdma_chan->free_list); - bdma_chan->completed_cookie = dchan->cookie = 1; - spin_unlock_bh(&bdma_chan->lock); - -#ifdef CONFIG_PCI_MSI - if (priv->flags & TSI721_USING_MSIX) { - /* Request interrupt service if we are in MSI-X mode */ - rc = request_irq( - priv->msix[TSI721_VECT_DMA0_DONE + - bdma_chan->id].vector, - tsi721_bdma_msix, 0, - priv->msix[TSI721_VECT_DMA0_DONE + - bdma_chan->id].irq_name, - (void *)bdma_chan); - - if (rc) { - dev_dbg(dchan->device->dev, - "Unable to allocate MSI-X interrupt for " - "BDMA%d-DONE\n", bdma_chan->id); - goto err_out; - } - - rc = request_irq(priv->msix[TSI721_VECT_DMA0_INT + - bdma_chan->id].vector, - tsi721_bdma_msix, 0, - priv->msix[TSI721_VECT_DMA0_INT + - bdma_chan->id].irq_name, - (void *)bdma_chan); - - if (rc) { - dev_dbg(dchan->device->dev, - "Unable to allocate MSI-X interrupt for " - "BDMA%d-INT\n", bdma_chan->id); - free_irq( - priv->msix[TSI721_VECT_DMA0_DONE + - bdma_chan->id].vector, - (void *)bdma_chan); - rc = -EIO; - goto err_out; - } - } -#endif /* CONFIG_PCI_MSI */ - - tasklet_enable(&bdma_chan->tasklet); - tsi721_bdma_interrupt_enable(bdma_chan, 1); - - return bdma_chan->bd_num - 1; - -err_out: - kfree(desc); - tsi721_bdma_ch_free(bdma_chan); - return rc; -} - -static void tsi721_free_chan_resources(struct dma_chan *dchan) -{ - struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); -#ifdef CONFIG_PCI_MSI - struct tsi721_device *priv = to_tsi721(dchan->device); -#endif - LIST_HEAD(list); - - dev_dbg(dchan->device->dev, "%s: Entry\n", __func__); - - if (bdma_chan->bd_base == NULL) - return; - - BUG_ON(!list_empty(&bdma_chan->active_list)); - BUG_ON(!list_empty(&bdma_chan->queue)); - - tasklet_disable(&bdma_chan->tasklet); - - spin_lock_bh(&bdma_chan->lock); - list_splice_init(&bdma_chan->free_list, &list); - spin_unlock_bh(&bdma_chan->lock); - - tsi721_bdma_interrupt_enable(bdma_chan, 0); - -#ifdef CONFIG_PCI_MSI - if (priv->flags & TSI721_USING_MSIX) { - free_irq(priv->msix[TSI721_VECT_DMA0_DONE + - bdma_chan->id].vector, (void *)bdma_chan); - free_irq(priv->msix[TSI721_VECT_DMA0_INT + - bdma_chan->id].vector, (void *)bdma_chan); - } -#endif /* CONFIG_PCI_MSI */ - - tsi721_bdma_ch_free(bdma_chan); - kfree(bdma_chan->tx_desc); -} - -static -enum dma_status tsi721_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, - struct dma_tx_state *txstate) -{ - struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); - dma_cookie_t last_used; - dma_cookie_t last_completed; - int ret; - - spin_lock_bh(&bdma_chan->lock); - last_completed = bdma_chan->completed_cookie; - last_used = dchan->cookie; - spin_unlock_bh(&bdma_chan->lock); - - ret = dma_async_is_complete(cookie, last_completed, last_used); - - dma_set_tx_state(txstate, last_completed, last_used, 0); - - dev_dbg(dchan->device->dev, - "%s: exit, ret: %d, last_completed: %d, last_used: %d\n", - __func__, ret, last_completed, last_used); - - return ret; -} - -static void tsi721_issue_pending(struct dma_chan *dchan) -{ - struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); - - dev_dbg(dchan->device->dev, "%s: Entry\n", __func__); - - if (tsi721_dma_is_idle(bdma_chan)) { - spin_lock_bh(&bdma_chan->lock); - tsi721_advance_work(bdma_chan); - spin_unlock_bh(&bdma_chan->lock); - } else - dev_dbg(dchan->device->dev, - "%s: DMA channel still busy\n", __func__); -} - -static -struct dma_async_tx_descriptor *tsi721_prep_rio_sg(struct dma_chan *dchan, - struct scatterlist *sgl, unsigned int sg_len, - enum dma_transfer_direction dir, unsigned long flags, - void *tinfo) -{ - struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); - struct tsi721_tx_desc *desc = NULL; - struct tsi721_tx_desc *first = NULL; - struct scatterlist *sg; - struct rio_dma_ext *rext = tinfo; - u64 rio_addr = rext->rio_addr; /* limited to 64-bit rio_addr for now */ - unsigned int i; - u32 sys_size = dma_to_mport(dchan->device)->sys_size; - enum dma_rtype rtype; - - if (!sgl || !sg_len) { - dev_err(dchan->device->dev, "%s: No SG list\n", __func__); - return NULL; - } - - if (dir == DMA_DEV_TO_MEM) - rtype = NREAD; - else if (dir == DMA_MEM_TO_DEV) { - switch (rext->wr_type) { - case RDW_ALL_NWRITE: - rtype = ALL_NWRITE; - break; - case RDW_ALL_NWRITE_R: - rtype = ALL_NWRITE_R; - break; - case RDW_LAST_NWRITE_R: - default: - rtype = LAST_NWRITE_R; - break; - } - } else { - dev_err(dchan->device->dev, - "%s: Unsupported DMA direction option\n", __func__); - return NULL; - } - - for_each_sg(sgl, sg, sg_len, i) { - int err; - - dev_dbg(dchan->device->dev, "%s: sg #%d\n", __func__, i); - desc = tsi721_desc_get(bdma_chan); - if (!desc) { - dev_err(dchan->device->dev, - "Not enough descriptors available\n"); - goto err_desc_get; - } - - if (sg_is_last(sg)) - desc->interrupt = (flags & DMA_PREP_INTERRUPT) != 0; - else - desc->interrupt = false; - - desc->destid = rext->destid; - desc->rio_addr = rio_addr; - desc->rio_addr_u = 0; - - err = tsi721_fill_desc(bdma_chan, desc, sg, rtype, sys_size); - if (err) { - dev_err(dchan->device->dev, - "Failed to build desc: %d\n", err); - goto err_desc_get; - } - - rio_addr += sg_dma_len(sg); - - if (!first) - first = desc; - else - list_add_tail(&desc->desc_node, &first->tx_list); - } - - first->txd.cookie = -EBUSY; - desc->txd.flags = flags; - - return &first->txd; - -err_desc_get: - tsi721_desc_put(bdma_chan, first); - return NULL; -} - -static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd, - unsigned long arg) -{ - struct tsi721_bdma_chan *bdma_chan = to_tsi721_chan(dchan); - struct tsi721_tx_desc *desc, *_d; - LIST_HEAD(list); - - dev_dbg(dchan->device->dev, "%s: Entry\n", __func__); - - if (cmd != DMA_TERMINATE_ALL) - return -ENXIO; - - spin_lock_bh(&bdma_chan->lock); - - /* make sure to stop the transfer */ - iowrite32(TSI721_DMAC_CTL_SUSP, bdma_chan->regs + TSI721_DMAC_CTL); - - list_splice_init(&bdma_chan->active_list, &list); - list_splice_init(&bdma_chan->queue, &list); - - list_for_each_entry_safe(desc, _d, &list, desc_node) - tsi721_dma_chain_complete(bdma_chan, desc); - - spin_unlock_bh(&bdma_chan->lock); - - return 0; -} - -int __devinit tsi721_register_dma(struct tsi721_device *priv) -{ - int i; - int nr_channels = TSI721_DMA_MAXCH; - int err; - struct rio_mport *mport = priv->mport; - - mport->dma.dev = &priv->pdev->dev; - mport->dma.chancnt = nr_channels; - - INIT_LIST_HEAD(&mport->dma.channels); - - for (i = 0; i < nr_channels; i++) { - struct tsi721_bdma_chan *bdma_chan = &priv->bdma[i]; - - if (i == TSI721_DMACH_MAINT) - continue; - - bdma_chan->bd_num = 64; - bdma_chan->regs = priv->regs + TSI721_DMAC_BASE(i); - - bdma_chan->dchan.device = &mport->dma; - bdma_chan->dchan.cookie = 1; - bdma_chan->dchan.chan_id = i; - bdma_chan->id = i; - - spin_lock_init(&bdma_chan->lock); - - INIT_LIST_HEAD(&bdma_chan->active_list); - INIT_LIST_HEAD(&bdma_chan->queue); - INIT_LIST_HEAD(&bdma_chan->free_list); - - tasklet_init(&bdma_chan->tasklet, tsi721_dma_tasklet, - (unsigned long)bdma_chan); - tasklet_disable(&bdma_chan->tasklet); - list_add_tail(&bdma_chan->dchan.device_node, - &mport->dma.channels); - } - - dma_cap_zero(mport->dma.cap_mask); - dma_cap_set(DMA_PRIVATE, mport->dma.cap_mask); - dma_cap_set(DMA_SLAVE, mport->dma.cap_mask); - - mport->dma.device_alloc_chan_resources = tsi721_alloc_chan_resources; - mport->dma.device_free_chan_resources = tsi721_free_chan_resources; - mport->dma.device_tx_status = tsi721_tx_status; - mport->dma.device_issue_pending = tsi721_issue_pending; - mport->dma.device_prep_slave_sg = tsi721_prep_rio_sg; - mport->dma.device_control = tsi721_device_control; - - err = dma_async_device_register(&mport->dma); - if (err) - dev_err(&priv->pdev->dev, "Failed to register DMA device\n"); - - return err; -} diff --git a/trunk/drivers/rapidio/rio.c b/trunk/drivers/rapidio/rio.c index c40665a4fa33..86c9a091a2ff 100644 --- a/trunk/drivers/rapidio/rio.c +++ b/trunk/drivers/rapidio/rio.c @@ -1121,87 +1121,6 @@ int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, return 0; } -#ifdef CONFIG_RAPIDIO_DMA_ENGINE - -static bool rio_chan_filter(struct dma_chan *chan, void *arg) -{ - struct rio_dev *rdev = arg; - - /* Check that DMA device belongs to the right MPORT */ - return (rdev->net->hport == - container_of(chan->device, struct rio_mport, dma)); -} - -/** - * rio_request_dma - request RapidIO capable DMA channel that supports - * specified target RapidIO device. - * @rdev: RIO device control structure - * - * Returns pointer to allocated DMA channel or NULL if failed. - */ -struct dma_chan *rio_request_dma(struct rio_dev *rdev) -{ - dma_cap_mask_t mask; - struct dma_chan *dchan; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dchan = dma_request_channel(mask, rio_chan_filter, rdev); - - return dchan; -} -EXPORT_SYMBOL_GPL(rio_request_dma); - -/** - * rio_release_dma - release specified DMA channel - * @dchan: DMA channel to release - */ -void rio_release_dma(struct dma_chan *dchan) -{ - dma_release_channel(dchan); -} -EXPORT_SYMBOL_GPL(rio_release_dma); - -/** - * rio_dma_prep_slave_sg - RapidIO specific wrapper - * for device_prep_slave_sg callback defined by DMAENGINE. - * @rdev: RIO device control structure - * @dchan: DMA channel to configure - * @data: RIO specific data descriptor - * @direction: DMA data transfer direction (TO or FROM the device) - * @flags: dmaengine defined flags - * - * Initializes RapidIO capable DMA channel for the specified data transfer. - * Uses DMA channel private extension to pass information related to remote - * target RIO device. - * Returns pointer to DMA transaction descriptor or NULL if failed. - */ -struct dma_async_tx_descriptor *rio_dma_prep_slave_sg(struct rio_dev *rdev, - struct dma_chan *dchan, struct rio_dma_data *data, - enum dma_transfer_direction direction, unsigned long flags) -{ - struct dma_async_tx_descriptor *txd = NULL; - struct rio_dma_ext rio_ext; - - if (dchan->device->device_prep_slave_sg == NULL) { - pr_err("%s: prep_rio_sg == NULL\n", __func__); - return NULL; - } - - rio_ext.destid = rdev->destid; - rio_ext.rio_addr_u = data->rio_addr_u; - rio_ext.rio_addr = data->rio_addr; - rio_ext.wr_type = data->wr_type; - - txd = dmaengine_prep_rio_sg(dchan, data->sg, data->sg_len, - direction, flags, &rio_ext); - - return txd; -} -EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg); - -#endif /* CONFIG_RAPIDIO_DMA_ENGINE */ - static void rio_fixup_device(struct rio_dev *dev) { } diff --git a/trunk/drivers/regulator/anatop-regulator.c b/trunk/drivers/regulator/anatop-regulator.c index e82e7eaac0f1..3660bace123c 100644 --- a/trunk/drivers/regulator/anatop-regulator.c +++ b/trunk/drivers/regulator/anatop-regulator.c @@ -224,7 +224,7 @@ static struct platform_driver anatop_regulator_driver = { .of_match_table = of_anatop_regulator_match_tbl, }, .probe = anatop_regulator_probe, - .remove = __devexit_p(anatop_regulator_remove), + .remove = anatop_regulator_remove, }; static int __init anatop_regulator_init(void) diff --git a/trunk/drivers/regulator/core.c b/trunk/drivers/regulator/core.c index 09a737c868b5..7584a74eec8a 100644 --- a/trunk/drivers/regulator/core.c +++ b/trunk/drivers/regulator/core.c @@ -2050,9 +2050,6 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev, return -EINVAL; } - if (min_uV < rdev->desc->min_uV) - min_uV = rdev->desc->min_uV; - ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); if (ret < 0) return ret; diff --git a/trunk/drivers/regulator/gpio-regulator.c b/trunk/drivers/regulator/gpio-regulator.c index 242851a4c1a6..9997d7aaca84 100644 --- a/trunk/drivers/regulator/gpio-regulator.c +++ b/trunk/drivers/regulator/gpio-regulator.c @@ -101,20 +101,16 @@ static int gpio_regulator_get_value(struct regulator_dev *dev) } static int gpio_regulator_set_value(struct regulator_dev *dev, - int min, int max, unsigned *selector) + int min, int max) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); - int ptr, target = 0, state, best_val = INT_MAX; + int ptr, target, state, best_val = INT_MAX; for (ptr = 0; ptr < data->nr_states; ptr++) if (data->states[ptr].value < best_val && data->states[ptr].value >= min && - data->states[ptr].value <= max) { + data->states[ptr].value <= max) target = data->states[ptr].gpios; - best_val = data->states[ptr].value; - if (selector) - *selector = ptr; - } if (best_val == INT_MAX) return -EINVAL; @@ -132,7 +128,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev, int min_uV, int max_uV, unsigned *selector) { - return gpio_regulator_set_value(dev, min_uV, max_uV, selector); + return gpio_regulator_set_value(dev, min_uV, max_uV); } static int gpio_regulator_list_voltage(struct regulator_dev *dev, @@ -149,7 +145,7 @@ static int gpio_regulator_list_voltage(struct regulator_dev *dev, static int gpio_regulator_set_current_limit(struct regulator_dev *dev, int min_uA, int max_uA) { - return gpio_regulator_set_value(dev, min_uA, max_uA, NULL); + return gpio_regulator_set_value(dev, min_uA, max_uA); } static struct regulator_ops gpio_regulator_voltage_ops = { @@ -290,7 +286,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) cfg.dev = &pdev->dev; cfg.init_data = config->init_data; - cfg.driver_data = drvdata; + cfg.driver_data = &drvdata; drvdata->dev = regulator_register(&drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { diff --git a/trunk/drivers/regulator/max8649.c b/trunk/drivers/regulator/max8649.c index 9d540cd02dab..1f4bb80457b3 100644 --- a/trunk/drivers/regulator/max8649.c +++ b/trunk/drivers/regulator/max8649.c @@ -259,7 +259,6 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, config.dev = &client->dev; config.init_data = pdata->regulator; config.driver_data = info; - config.regmap = info->regmap; info->regulator = regulator_register(&dcdc_desc, &config); if (IS_ERR(info->regulator)) { diff --git a/trunk/drivers/regulator/palmas-regulator.c b/trunk/drivers/regulator/palmas-regulator.c index 9b7ca90057d5..c4435f608df7 100644 --- a/trunk/drivers/regulator/palmas-regulator.c +++ b/trunk/drivers/regulator/palmas-regulator.c @@ -775,6 +775,9 @@ static __devinit int palmas_probe(struct platform_device *pdev) err_unregister_regulator: while (--id >= 0) regulator_unregister(pmic->rdev[id]); + kfree(pmic->rdev); + kfree(pmic->desc); + kfree(pmic); return ret; } @@ -785,6 +788,10 @@ static int __devexit palmas_remove(struct platform_device *pdev) for (id = 0; id < PALMAS_NUM_REGS; id++) regulator_unregister(pmic->rdev[id]); + + kfree(pmic->rdev); + kfree(pmic->desc); + kfree(pmic); return 0; } diff --git a/trunk/drivers/rtc/rtc-cmos.c b/trunk/drivers/rtc/rtc-cmos.c index 4267789ca995..7d5f56edb8ef 100644 --- a/trunk/drivers/rtc/rtc-cmos.c +++ b/trunk/drivers/rtc/rtc-cmos.c @@ -910,17 +910,14 @@ static inline int cmos_poweroff(struct device *dev) static u32 rtc_handler(void *context) { - struct device *dev = context; - - pm_wakeup_event(dev, 0); acpi_clear_event(ACPI_EVENT_RTC); acpi_disable_event(ACPI_EVENT_RTC, 0); return ACPI_INTERRUPT_HANDLED; } -static inline void rtc_wake_setup(struct device *dev) +static inline void rtc_wake_setup(void) { - acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, dev); + acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); /* * After the RTC handler is installed, the Fixed_RTC event should * be disabled. Only when the RTC alarm is set will it be enabled. @@ -953,7 +950,7 @@ cmos_wake_setup(struct device *dev) if (acpi_disabled) return; - rtc_wake_setup(dev); + rtc_wake_setup(); acpi_rtc_info.wake_on = rtc_wake_on; acpi_rtc_info.wake_off = rtc_wake_off; diff --git a/trunk/drivers/scsi/be2iscsi/be_mgmt.c b/trunk/drivers/scsi/be2iscsi/be_mgmt.c index 2a096795b9aa..01bb04cd9e75 100644 --- a/trunk/drivers/scsi/be2iscsi/be_mgmt.c +++ b/trunk/drivers/scsi/be2iscsi/be_mgmt.c @@ -571,12 +571,13 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd, int iscsi_cmd, int size) { - cmd->va = pci_alloc_consistent(phba->ctrl.pdev, size, &cmd->dma); + cmd->va = pci_alloc_consistent(phba->ctrl.pdev, sizeof(size), + &cmd->dma); if (!cmd->va) { SE_DEBUG(DBG_LVL_1, "Failed to allocate memory for if info\n"); return -ENOMEM; } - memset(cmd->va, 0, size); + memset(cmd->va, 0, sizeof(size)); cmd->size = size; be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); return 0; diff --git a/trunk/drivers/scsi/bfa/bfad_attr.c b/trunk/drivers/scsi/bfa/bfad_attr.c index b83927440171..8b6c6bf7837e 100644 --- a/trunk/drivers/scsi/bfa/bfad_attr.c +++ b/trunk/drivers/scsi/bfa/bfad_attr.c @@ -426,23 +426,6 @@ bfad_im_vport_create(struct fc_vport *fc_vport, bool disable) vshost = vport->drv_port.im_port->shost; fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn); fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn); - fc_host_supported_classes(vshost) = FC_COS_CLASS3; - - memset(fc_host_supported_fc4s(vshost), 0, - sizeof(fc_host_supported_fc4s(vshost))); - - /* For FCP type 0x08 */ - if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM) - fc_host_supported_fc4s(vshost)[2] = 1; - - /* For fibre channel services type 0x20 */ - fc_host_supported_fc4s(vshost)[7] = 1; - - fc_host_supported_speeds(vshost) = - bfad_im_supported_speeds(&bfad->bfa); - fc_host_maxframe_size(vshost) = - bfa_fcport_get_maxfrsize(&bfad->bfa); - fc_vport->dd_data = vport; vport->drv_port.im_port->fc_vport = fc_vport; } else if (rc == BFA_STATUS_INVALID_WWN) diff --git a/trunk/drivers/scsi/bfa/bfad_im.c b/trunk/drivers/scsi/bfa/bfad_im.c index 1ac09afe35ee..3153923f5b60 100644 --- a/trunk/drivers/scsi/bfa/bfad_im.c +++ b/trunk/drivers/scsi/bfa/bfad_im.c @@ -987,7 +987,7 @@ bfad_im_slave_alloc(struct scsi_device *sdev) return 0; } -u32 +static u32 bfad_im_supported_speeds(struct bfa_s *bfa) { struct bfa_ioc_attr_s *ioc_attr; diff --git a/trunk/drivers/scsi/bfa/bfad_im.h b/trunk/drivers/scsi/bfa/bfad_im.h index f6c1023e502a..0814367ef101 100644 --- a/trunk/drivers/scsi/bfa/bfad_im.h +++ b/trunk/drivers/scsi/bfa/bfad_im.h @@ -37,7 +37,6 @@ int bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port, struct device *dev); void bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port); -u32 bfad_im_supported_speeds(struct bfa_s *bfa); #define MAX_FCP_TARGET 1024 #define MAX_FCP_LUN 16384 diff --git a/trunk/drivers/scsi/bnx2fc/bnx2fc.h b/trunk/drivers/scsi/bnx2fc/bnx2fc.h index 0578fa0dc14b..a4953ef9e53a 100644 --- a/trunk/drivers/scsi/bnx2fc/bnx2fc.h +++ b/trunk/drivers/scsi/bnx2fc/bnx2fc.h @@ -62,7 +62,7 @@ #include "bnx2fc_constants.h" #define BNX2FC_NAME "bnx2fc" -#define BNX2FC_VERSION "1.0.11" +#define BNX2FC_VERSION "1.0.10" #define PFX "bnx2fc: " @@ -228,16 +228,13 @@ struct bnx2fc_interface { struct packet_type fip_packet_type; struct workqueue_struct *timer_work_queue; struct kref kref; + struct fcoe_ctlr ctlr; u8 vlan_enabled; int vlan_id; bool enabled; }; -#define bnx2fc_from_ctlr(x) \ - ((struct bnx2fc_interface *)((x) + 1)) - -#define bnx2fc_to_ctlr(x) \ - ((struct fcoe_ctlr *)(((struct fcoe_ctlr *)(x)) - 1)) +#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_interface, ctlr) struct bnx2fc_lport { struct list_head list; diff --git a/trunk/drivers/scsi/bnx2fc/bnx2fc_els.c b/trunk/drivers/scsi/bnx2fc/bnx2fc_els.c index bdbbb13b8534..ce0ce3e32f33 100644 --- a/trunk/drivers/scsi/bnx2fc/bnx2fc_els.c +++ b/trunk/drivers/scsi/bnx2fc/bnx2fc_els.c @@ -854,6 +854,7 @@ static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, struct fc_exch *exch = fc_seq_exch(seq); struct fc_lport *lport = exch->lp; u8 *mac; + struct fc_frame_header *fh; u8 op; if (IS_ERR(fp)) @@ -861,6 +862,13 @@ static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, mac = fr_cb(fp)->granted_mac; if (is_zero_ether_addr(mac)) { + fh = fc_frame_header_get(fp); + if (fh->fh_type != FC_TYPE_ELS) { + printk(KERN_ERR PFX "bnx2fc_flogi_resp:" + "fh_type != FC_TYPE_ELS\n"); + fc_frame_free(fp); + return; + } op = fc_frame_payload_op(fp); if (lport->vport) { if (op == ELS_LS_RJT) { @@ -870,10 +878,12 @@ static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, return; } } - fcoe_ctlr_recv_flogi(fip, lport, fp); + if (fcoe_ctlr_recv_flogi(fip, lport, fp)) { + fc_frame_free(fp); + return; + } } - if (!is_zero_ether_addr(mac)) - fip->update_mac(lport, mac); + fip->update_mac(lport, mac); done: fc_lport_flogi_resp(seq, fp, lport); } @@ -900,7 +910,7 @@ struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did, { struct fcoe_port *port = lport_priv(lport); struct bnx2fc_interface *interface = port->priv; - struct fcoe_ctlr *fip = bnx2fc_to_ctlr(interface); + struct fcoe_ctlr *fip = &interface->ctlr; struct fc_frame_header *fh = fc_frame_header_get(fp); switch (op) { diff --git a/trunk/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/trunk/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index f52f668fd247..c1c6a92a0b98 100644 --- a/trunk/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/trunk/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); #define DRV_MODULE_NAME "bnx2fc" #define DRV_MODULE_VERSION BNX2FC_VERSION -#define DRV_MODULE_RELDATE "Apr 24, 2012" +#define DRV_MODULE_RELDATE "Jan 22, 2011" static char version[] __devinitdata = @@ -54,7 +54,6 @@ static struct cnic_ulp_ops bnx2fc_cnic_cb; static struct libfc_function_template bnx2fc_libfc_fcn_templ; static struct scsi_host_template bnx2fc_shost_template; static struct fc_function_template bnx2fc_transport_function; -static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ; static struct fc_function_template bnx2fc_vport_xport_function; static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode); static void __bnx2fc_destroy(struct bnx2fc_interface *interface); @@ -89,7 +88,6 @@ static void bnx2fc_port_shutdown(struct fc_lport *lport); static void bnx2fc_stop(struct bnx2fc_interface *interface); static int __init bnx2fc_mod_init(void); static void __exit bnx2fc_mod_exit(void); -static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev); unsigned int bnx2fc_debug_level; module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR); @@ -120,41 +118,6 @@ static void bnx2fc_get_lesb(struct fc_lport *lport, __fcoe_get_lesb(lport, fc_lesb, netdev); } -static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev) -{ - struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); - struct net_device *netdev = bnx2fc_netdev(fip->lp); - struct fcoe_fc_els_lesb *fcoe_lesb; - struct fc_els_lesb fc_lesb; - - __fcoe_get_lesb(fip->lp, &fc_lesb, netdev); - fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb); - - ctlr_dev->lesb.lesb_link_fail = - ntohl(fcoe_lesb->lesb_link_fail); - ctlr_dev->lesb.lesb_vlink_fail = - ntohl(fcoe_lesb->lesb_vlink_fail); - ctlr_dev->lesb.lesb_miss_fka = - ntohl(fcoe_lesb->lesb_miss_fka); - ctlr_dev->lesb.lesb_symb_err = - ntohl(fcoe_lesb->lesb_symb_err); - ctlr_dev->lesb.lesb_err_block = - ntohl(fcoe_lesb->lesb_err_block); - ctlr_dev->lesb.lesb_fcs_error = - ntohl(fcoe_lesb->lesb_fcs_error); -} -EXPORT_SYMBOL(bnx2fc_ctlr_get_lesb); - -static void bnx2fc_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) -{ - struct fcoe_ctlr_device *ctlr_dev = - fcoe_fcf_dev_to_ctlr_dev(fcf_dev); - struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); - struct bnx2fc_interface *fcoe = fcoe_ctlr_priv(ctlr); - - fcf_dev->vlan_id = fcoe->vlan_id; -} - static void bnx2fc_clean_rx_queue(struct fc_lport *lp) { struct fcoe_percpu_s *bg; @@ -281,7 +244,6 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) struct sk_buff *skb; struct fc_frame_header *fh; struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; struct bnx2fc_hba *hba; struct fcoe_port *port; struct fcoe_hdr *hp; @@ -294,7 +256,6 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) port = (struct fcoe_port *)lport_priv(lport); interface = port->priv; - ctlr = bnx2fc_to_ctlr(interface); hba = interface->hba; fh = fc_frame_header_get(fp); @@ -307,12 +268,12 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) } if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) { - if (!ctlr->sel_fcf) { + if (!interface->ctlr.sel_fcf) { BNX2FC_HBA_DBG(lport, "FCF not selected yet!\n"); kfree_skb(skb); return -EINVAL; } - if (fcoe_ctlr_els_send(ctlr, lport, skb)) + if (fcoe_ctlr_els_send(&interface->ctlr, lport, skb)) return 0; } @@ -385,14 +346,14 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp) /* fill up mac and fcoe headers */ eh = eth_hdr(skb); eh->h_proto = htons(ETH_P_FCOE); - if (ctlr->map_dest) + if (interface->ctlr.map_dest) fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id); else /* insert GW address */ - memcpy(eh->h_dest, ctlr->dest_addr, ETH_ALEN); + memcpy(eh->h_dest, interface->ctlr.dest_addr, ETH_ALEN); - if (unlikely(ctlr->flogi_oxid != FC_XID_UNKNOWN)) - memcpy(eh->h_source, ctlr->ctl_src_addr, ETH_ALEN); + if (unlikely(interface->ctlr.flogi_oxid != FC_XID_UNKNOWN)) + memcpy(eh->h_source, interface->ctlr.ctl_src_addr, ETH_ALEN); else memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); @@ -442,7 +403,6 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, { struct fc_lport *lport; struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; struct fc_frame_header *fh; struct fcoe_rcv_info *fr; struct fcoe_percpu_s *bg; @@ -450,8 +410,7 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, interface = container_of(ptype, struct bnx2fc_interface, fcoe_packet_type); - ctlr = bnx2fc_to_ctlr(interface); - lport = ctlr->lp; + lport = interface->ctlr.lp; if (unlikely(lport == NULL)) { printk(KERN_ERR PFX "bnx2fc_rcv: lport is NULL\n"); @@ -799,13 +758,11 @@ static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev) { struct bnx2fc_hba *hba; struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; struct fcoe_port *port; u64 wwnn, wwpn; port = lport_priv(lport); interface = port->priv; - ctlr = bnx2fc_to_ctlr(interface); hba = interface->hba; /* require support for get_pauseparam ethtool op. */ @@ -824,13 +781,13 @@ static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev) if (!lport->vport) { if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) - wwnn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, + wwnn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, 1, 0); BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn); fc_set_wwnn(lport, wwnn); if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) - wwpn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, + wwpn = fcoe_wwn_from_mac(interface->ctlr.ctl_src_addr, 2, 0); BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn); @@ -867,7 +824,6 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, struct fc_lport *lport; struct fc_lport *vport; struct bnx2fc_interface *interface, *tmp; - struct fcoe_ctlr *ctlr; int wait_for_upload = 0; u32 link_possible = 1; @@ -918,8 +874,7 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, if (interface->hba != hba) continue; - ctlr = bnx2fc_to_ctlr(interface); - lport = ctlr->lp; + lport = interface->ctlr.lp; BNX2FC_HBA_DBG(lport, "netevent handler - event=%s %ld\n", interface->netdev->name, event); @@ -934,8 +889,8 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event, * on a stale vlan */ if (interface->enabled) - fcoe_ctlr_link_up(ctlr); - } else if (fcoe_ctlr_link_down(ctlr)) { + fcoe_ctlr_link_up(&interface->ctlr); + } else if (fcoe_ctlr_link_down(&interface->ctlr)) { mutex_lock(&lport->lp_mutex); list_for_each_entry(vport, &lport->vports, list) fc_host_port_type(vport->host) = @@ -1040,11 +995,9 @@ static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev, struct net_device *orig_dev) { struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; interface = container_of(ptype, struct bnx2fc_interface, fip_packet_type); - ctlr = bnx2fc_to_ctlr(interface); - fcoe_ctlr_recv(ctlr, skb); + fcoe_ctlr_recv(&interface->ctlr, skb); return 0; } @@ -1202,7 +1155,6 @@ static int bnx2fc_interface_setup(struct bnx2fc_interface *interface) { struct net_device *netdev = interface->netdev; struct net_device *physdev = interface->hba->phys_dev; - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); struct netdev_hw_addr *ha; int sel_san_mac = 0; @@ -1217,7 +1169,7 @@ static int bnx2fc_interface_setup(struct bnx2fc_interface *interface) if ((ha->type == NETDEV_HW_ADDR_T_SAN) && (is_valid_ether_addr(ha->addr))) { - memcpy(ctlr->ctl_src_addr, ha->addr, + memcpy(interface->ctlr.ctl_src_addr, ha->addr, ETH_ALEN); sel_san_mac = 1; BNX2FC_MISC_DBG("Found SAN MAC\n"); @@ -1272,23 +1224,19 @@ static void bnx2fc_release_transport(void) static void bnx2fc_interface_release(struct kref *kref) { - struct fcoe_ctlr_device *ctlr_dev; struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; struct net_device *netdev; interface = container_of(kref, struct bnx2fc_interface, kref); BNX2FC_MISC_DBG("Interface is being released\n"); - ctlr = bnx2fc_to_ctlr(interface); - ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr); netdev = interface->netdev; /* tear-down FIP controller */ if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags)) - fcoe_ctlr_destroy(ctlr); + fcoe_ctlr_destroy(&interface->ctlr); - fcoe_ctlr_device_delete(ctlr_dev); + kfree(interface); dev_put(netdev); module_put(THIS_MODULE); @@ -1381,40 +1329,33 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, struct net_device *netdev, enum fip_state fip_mode) { - struct fcoe_ctlr_device *ctlr_dev; struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; - int size; int rc = 0; - size = (sizeof(*interface) + sizeof(struct fcoe_ctlr)); - ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &bnx2fc_fcoe_sysfs_templ, - size); - if (!ctlr_dev) { + interface = kzalloc(sizeof(*interface), GFP_KERNEL); + if (!interface) { printk(KERN_ERR PFX "Unable to allocate interface structure\n"); return NULL; } - ctlr = fcoe_ctlr_device_priv(ctlr_dev); - interface = fcoe_ctlr_priv(ctlr); dev_hold(netdev); kref_init(&interface->kref); interface->hba = hba; interface->netdev = netdev; /* Initialize FIP */ - fcoe_ctlr_init(ctlr, fip_mode); - ctlr->send = bnx2fc_fip_send; - ctlr->update_mac = bnx2fc_update_src_mac; - ctlr->get_src_addr = bnx2fc_get_src_mac; + fcoe_ctlr_init(&interface->ctlr, fip_mode); + interface->ctlr.send = bnx2fc_fip_send; + interface->ctlr.update_mac = bnx2fc_update_src_mac; + interface->ctlr.get_src_addr = bnx2fc_get_src_mac; set_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags); rc = bnx2fc_interface_setup(interface); if (!rc) return interface; - fcoe_ctlr_destroy(ctlr); + fcoe_ctlr_destroy(&interface->ctlr); dev_put(netdev); - fcoe_ctlr_device_delete(ctlr_dev); + kfree(interface); return NULL; } @@ -1432,7 +1373,6 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, struct device *parent, int npiv) { - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); struct fc_lport *lport, *n_port; struct fcoe_port *port; struct Scsi_Host *shost; @@ -1443,7 +1383,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface, blport = kzalloc(sizeof(struct bnx2fc_lport), GFP_KERNEL); if (!blport) { - BNX2FC_HBA_DBG(ctlr->lp, "Unable to alloc blport\n"); + BNX2FC_HBA_DBG(interface->ctlr.lp, "Unable to alloc blport\n"); return NULL; } @@ -1539,8 +1479,7 @@ static void bnx2fc_net_cleanup(struct bnx2fc_interface *interface) static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface) { - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); - struct fc_lport *lport = ctlr->lp; + struct fc_lport *lport = interface->ctlr.lp; struct fcoe_port *port = lport_priv(lport); struct bnx2fc_hba *hba = interface->hba; @@ -1580,8 +1519,7 @@ static void bnx2fc_if_destroy(struct fc_lport *lport) static void __bnx2fc_destroy(struct bnx2fc_interface *interface) { - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); - struct fc_lport *lport = ctlr->lp; + struct fc_lport *lport = interface->ctlr.lp; struct fcoe_port *port = lport_priv(lport); bnx2fc_interface_cleanup(interface); @@ -1605,15 +1543,13 @@ static int bnx2fc_destroy(struct net_device *netdev) { struct bnx2fc_interface *interface = NULL; struct workqueue_struct *timer_work_queue; - struct fcoe_ctlr *ctlr; int rc = 0; rtnl_lock(); mutex_lock(&bnx2fc_dev_lock); interface = bnx2fc_interface_lookup(netdev); - ctlr = bnx2fc_to_ctlr(interface); - if (!interface || !ctlr->lp) { + if (!interface || !interface->ctlr.lp) { rc = -ENODEV; printk(KERN_ERR PFX "bnx2fc_destroy: interface or lport not found\n"); goto netdev_err; @@ -1710,7 +1646,6 @@ static void bnx2fc_ulp_start(void *handle) { struct bnx2fc_hba *hba = handle; struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; struct fc_lport *lport; mutex_lock(&bnx2fc_dev_lock); @@ -1722,8 +1657,7 @@ static void bnx2fc_ulp_start(void *handle) list_for_each_entry(interface, &if_list, list) { if (interface->hba == hba) { - ctlr = bnx2fc_to_ctlr(interface); - lport = ctlr->lp; + lport = interface->ctlr.lp; /* Kick off Fabric discovery*/ printk(KERN_ERR PFX "ulp_init: start discovery\n"); lport->tt.frame_send = bnx2fc_xmit; @@ -1743,14 +1677,13 @@ static void bnx2fc_port_shutdown(struct fc_lport *lport) static void bnx2fc_stop(struct bnx2fc_interface *interface) { - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); struct fc_lport *lport; struct fc_lport *vport; if (!test_bit(BNX2FC_FLAG_FW_INIT_DONE, &interface->hba->flags)) return; - lport = ctlr->lp; + lport = interface->ctlr.lp; bnx2fc_port_shutdown(lport); mutex_lock(&lport->lp_mutex); @@ -1759,7 +1692,7 @@ static void bnx2fc_stop(struct bnx2fc_interface *interface) FC_PORTTYPE_UNKNOWN; mutex_unlock(&lport->lp_mutex); fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN; - fcoe_ctlr_link_down(ctlr); + fcoe_ctlr_link_down(&interface->ctlr); fcoe_clean_pending_queue(lport); } @@ -1871,7 +1804,6 @@ static void bnx2fc_ulp_stop(void *handle) static void bnx2fc_start_disc(struct bnx2fc_interface *interface) { - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); struct fc_lport *lport; int wait_cnt = 0; @@ -1882,18 +1814,18 @@ static void bnx2fc_start_disc(struct bnx2fc_interface *interface) return; } - lport = ctlr->lp; + lport = interface->ctlr.lp; BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n"); if (!bnx2fc_link_ok(lport) && interface->enabled) { BNX2FC_HBA_DBG(lport, "ctlr_link_up\n"); - fcoe_ctlr_link_up(ctlr); + fcoe_ctlr_link_up(&interface->ctlr); fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state); } /* wait for the FCF to be selected before issuing FLOGI */ - while (!ctlr->sel_fcf) { + while (!interface->ctlr.sel_fcf) { msleep(250); /* give up after 3 secs */ if (++wait_cnt > 12) @@ -1957,21 +1889,19 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev) static int bnx2fc_disable(struct net_device *netdev) { struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; int rc = 0; rtnl_lock(); mutex_lock(&bnx2fc_dev_lock); interface = bnx2fc_interface_lookup(netdev); - ctlr = bnx2fc_to_ctlr(interface); - if (!interface || !ctlr->lp) { + if (!interface || !interface->ctlr.lp) { rc = -ENODEV; printk(KERN_ERR PFX "bnx2fc_disable: interface or lport not found\n"); } else { interface->enabled = false; - fcoe_ctlr_link_down(ctlr); - fcoe_clean_pending_queue(ctlr->lp); + fcoe_ctlr_link_down(&interface->ctlr); + fcoe_clean_pending_queue(interface->ctlr.lp); } mutex_unlock(&bnx2fc_dev_lock); @@ -1983,19 +1913,17 @@ static int bnx2fc_disable(struct net_device *netdev) static int bnx2fc_enable(struct net_device *netdev) { struct bnx2fc_interface *interface; - struct fcoe_ctlr *ctlr; int rc = 0; rtnl_lock(); mutex_lock(&bnx2fc_dev_lock); interface = bnx2fc_interface_lookup(netdev); - ctlr = bnx2fc_to_ctlr(interface); - if (!interface || !ctlr->lp) { + if (!interface || !interface->ctlr.lp) { rc = -ENODEV; printk(KERN_ERR PFX "bnx2fc_enable: interface or lport not found\n"); - } else if (!bnx2fc_link_ok(ctlr->lp)) { - fcoe_ctlr_link_up(ctlr); + } else if (!bnx2fc_link_ok(interface->ctlr.lp)) { + fcoe_ctlr_link_up(&interface->ctlr); interface->enabled = true; } @@ -2016,7 +1944,6 @@ static int bnx2fc_enable(struct net_device *netdev) */ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) { - struct fcoe_ctlr *ctlr; struct bnx2fc_interface *interface; struct bnx2fc_hba *hba; struct net_device *phys_dev; @@ -2083,7 +2010,6 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) goto ifput_err; } - ctlr = bnx2fc_to_ctlr(interface); interface->vlan_id = vlan_id; interface->vlan_enabled = 1; @@ -2109,10 +2035,10 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode) lport->boot_time = jiffies; /* Make this master N_port */ - ctlr->lp = lport; + interface->ctlr.lp = lport; if (!bnx2fc_link_ok(lport)) { - fcoe_ctlr_link_up(ctlr); + fcoe_ctlr_link_up(&interface->ctlr); fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state); } @@ -2513,19 +2439,6 @@ static void __exit bnx2fc_mod_exit(void) module_init(bnx2fc_mod_init); module_exit(bnx2fc_mod_exit); -static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ = { - .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode, - .get_fcoe_ctlr_link_fail = bnx2fc_ctlr_get_lesb, - .get_fcoe_ctlr_vlink_fail = bnx2fc_ctlr_get_lesb, - .get_fcoe_ctlr_miss_fka = bnx2fc_ctlr_get_lesb, - .get_fcoe_ctlr_symb_err = bnx2fc_ctlr_get_lesb, - .get_fcoe_ctlr_err_block = bnx2fc_ctlr_get_lesb, - .get_fcoe_ctlr_fcs_error = bnx2fc_ctlr_get_lesb, - - .get_fcoe_fcf_selected = fcoe_fcf_get_selected, - .get_fcoe_fcf_vlan_id = bnx2fc_fcf_get_vlan_id, -}; - static struct fc_function_template bnx2fc_transport_function = { .show_host_node_name = 1, .show_host_port_name = 1, diff --git a/trunk/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/trunk/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 2ca6bfe4ce5e..afd570962b8c 100644 --- a/trunk/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/trunk/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -167,7 +167,6 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port, { struct fc_lport *lport = port->lport; struct bnx2fc_interface *interface = port->priv; - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); struct bnx2fc_hba *hba = interface->hba; struct kwqe *kwqe_arr[4]; struct fcoe_kwqe_conn_offload1 ofld_req1; @@ -315,13 +314,13 @@ int bnx2fc_send_session_ofld_req(struct fcoe_port *port, ofld_req4.src_mac_addr_mid[1] = port->data_src_addr[2]; ofld_req4.src_mac_addr_hi[0] = port->data_src_addr[1]; ofld_req4.src_mac_addr_hi[1] = port->data_src_addr[0]; - ofld_req4.dst_mac_addr_lo[0] = ctlr->dest_addr[5]; + ofld_req4.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5]; /* fcf mac */ - ofld_req4.dst_mac_addr_lo[1] = ctlr->dest_addr[4]; - ofld_req4.dst_mac_addr_mid[0] = ctlr->dest_addr[3]; - ofld_req4.dst_mac_addr_mid[1] = ctlr->dest_addr[2]; - ofld_req4.dst_mac_addr_hi[0] = ctlr->dest_addr[1]; - ofld_req4.dst_mac_addr_hi[1] = ctlr->dest_addr[0]; + ofld_req4.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4]; + ofld_req4.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3]; + ofld_req4.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2]; + ofld_req4.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1]; + ofld_req4.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0]; ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma; ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32); @@ -352,7 +351,6 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port, { struct kwqe *kwqe_arr[2]; struct bnx2fc_interface *interface = port->priv; - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); struct bnx2fc_hba *hba = interface->hba; struct fcoe_kwqe_conn_enable_disable enbl_req; struct fc_lport *lport = port->lport; @@ -376,12 +374,12 @@ static int bnx2fc_send_session_enable_req(struct fcoe_port *port, enbl_req.src_mac_addr_hi[1] = port->data_src_addr[0]; memcpy(tgt->src_addr, port->data_src_addr, ETH_ALEN); - enbl_req.dst_mac_addr_lo[0] = ctlr->dest_addr[5]; - enbl_req.dst_mac_addr_lo[1] = ctlr->dest_addr[4]; - enbl_req.dst_mac_addr_mid[0] = ctlr->dest_addr[3]; - enbl_req.dst_mac_addr_mid[1] = ctlr->dest_addr[2]; - enbl_req.dst_mac_addr_hi[0] = ctlr->dest_addr[1]; - enbl_req.dst_mac_addr_hi[1] = ctlr->dest_addr[0]; + enbl_req.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5]; + enbl_req.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4]; + enbl_req.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3]; + enbl_req.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2]; + enbl_req.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1]; + enbl_req.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0]; port_id = fc_host_port_id(lport->host); if (port_id != tgt->sid) { @@ -421,7 +419,6 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port, struct bnx2fc_rport *tgt) { struct bnx2fc_interface *interface = port->priv; - struct fcoe_ctlr *ctlr = bnx2fc_to_ctlr(interface); struct bnx2fc_hba *hba = interface->hba; struct fcoe_kwqe_conn_enable_disable disable_req; struct kwqe *kwqe_arr[2]; @@ -443,12 +440,12 @@ int bnx2fc_send_session_disable_req(struct fcoe_port *port, disable_req.src_mac_addr_hi[0] = tgt->src_addr[1]; disable_req.src_mac_addr_hi[1] = tgt->src_addr[0]; - disable_req.dst_mac_addr_lo[0] = ctlr->dest_addr[5]; - disable_req.dst_mac_addr_lo[1] = ctlr->dest_addr[4]; - disable_req.dst_mac_addr_mid[0] = ctlr->dest_addr[3]; - disable_req.dst_mac_addr_mid[1] = ctlr->dest_addr[2]; - disable_req.dst_mac_addr_hi[0] = ctlr->dest_addr[1]; - disable_req.dst_mac_addr_hi[1] = ctlr->dest_addr[0]; + disable_req.dst_mac_addr_lo[0] = interface->ctlr.dest_addr[5]; + disable_req.dst_mac_addr_lo[1] = interface->ctlr.dest_addr[4]; + disable_req.dst_mac_addr_mid[0] = interface->ctlr.dest_addr[3]; + disable_req.dst_mac_addr_mid[1] = interface->ctlr.dest_addr[2]; + disable_req.dst_mac_addr_hi[0] = interface->ctlr.dest_addr[1]; + disable_req.dst_mac_addr_hi[1] = interface->ctlr.dest_addr[0]; port_id = tgt->sid; disable_req.s_id[0] = (port_id & 0x000000FF); diff --git a/trunk/drivers/scsi/bnx2fc/bnx2fc_io.c b/trunk/drivers/scsi/bnx2fc/bnx2fc_io.c index 4f7453b9e41e..e897ce975bb8 100644 --- a/trunk/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/trunk/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -810,22 +810,8 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags) spin_lock_bh(&tgt->tgt_lock); io_req->wait_for_comp = 0; - if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags))) { + if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags))) set_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags); - if (io_req->on_tmf_queue) { - list_del_init(&io_req->link); - io_req->on_tmf_queue = 0; - } - io_req->wait_for_comp = 1; - bnx2fc_initiate_cleanup(io_req); - spin_unlock_bh(&tgt->tgt_lock); - rc = wait_for_completion_timeout(&io_req->tm_done, - BNX2FC_FW_TIMEOUT); - spin_lock_bh(&tgt->tgt_lock); - io_req->wait_for_comp = 0; - if (!rc) - kref_put(&io_req->refcount, bnx2fc_cmd_release); - } spin_unlock_bh(&tgt->tgt_lock); @@ -1103,48 +1089,6 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd) return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); } -int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req) -{ - struct bnx2fc_rport *tgt = io_req->tgt; - struct fc_rport_priv *rdata = tgt->rdata; - int logo_issued; - int rc = SUCCESS; - int wait_cnt = 0; - - BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n", - tgt->flags); - logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO, - &tgt->flags); - io_req->wait_for_comp = 1; - bnx2fc_initiate_cleanup(io_req); - - spin_unlock_bh(&tgt->tgt_lock); - - wait_for_completion(&io_req->tm_done); - - io_req->wait_for_comp = 0; - /* - * release the reference taken in eh_abort to allow the - * target to re-login after flushing IOs - */ - kref_put(&io_req->refcount, bnx2fc_cmd_release); - - if (!logo_issued) { - clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags); - mutex_lock(&lport->disc.disc_mutex); - lport->tt.rport_logoff(rdata); - mutex_unlock(&lport->disc.disc_mutex); - do { - msleep(BNX2FC_RELOGIN_WAIT_TIME); - if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) { - rc = FAILED; - break; - } - } while (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)); - } - spin_lock_bh(&tgt->tgt_lock); - return rc; -} /** * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding * SCSI command @@ -1159,7 +1103,10 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) struct fc_rport_libfc_priv *rp = rport->dd_data; struct bnx2fc_cmd *io_req; struct fc_lport *lport; + struct fc_rport_priv *rdata; struct bnx2fc_rport *tgt; + int logo_issued; + int wait_cnt = 0; int rc = FAILED; @@ -1236,31 +1183,58 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) list_add_tail(&io_req->link, &tgt->io_retire_queue); init_completion(&io_req->tm_done); + io_req->wait_for_comp = 1; - if (test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) { + if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) { + /* Cancel the current timer running on this io_req */ + if (cancel_delayed_work(&io_req->timeout_work)) + kref_put(&io_req->refcount, + bnx2fc_cmd_release); /* drop timer hold */ + set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags); + rc = bnx2fc_initiate_abts(io_req); + } else { printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) " "already in abts processing\n", io_req->xid); if (cancel_delayed_work(&io_req->timeout_work)) kref_put(&io_req->refcount, bnx2fc_cmd_release); /* drop timer hold */ - rc = bnx2fc_expl_logo(lport, io_req); - goto out; - } - - /* Cancel the current timer running on this io_req */ - if (cancel_delayed_work(&io_req->timeout_work)) - kref_put(&io_req->refcount, - bnx2fc_cmd_release); /* drop timer hold */ - set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags); - io_req->wait_for_comp = 1; - rc = bnx2fc_initiate_abts(io_req); - if (rc == FAILED) { bnx2fc_initiate_cleanup(io_req); + spin_unlock_bh(&tgt->tgt_lock); + wait_for_completion(&io_req->tm_done); + spin_lock_bh(&tgt->tgt_lock); io_req->wait_for_comp = 0; - goto done; + rdata = io_req->tgt->rdata; + logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO, + &tgt->flags); + kref_put(&io_req->refcount, bnx2fc_cmd_release); + spin_unlock_bh(&tgt->tgt_lock); + + if (!logo_issued) { + BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n", + tgt->flags); + mutex_lock(&lport->disc.disc_mutex); + lport->tt.rport_logoff(rdata); + mutex_unlock(&lport->disc.disc_mutex); + do { + msleep(BNX2FC_RELOGIN_WAIT_TIME); + /* + * If session not recovered, let SCSI-ml + * escalate error recovery. + */ + if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) + return FAILED; + } while (!test_bit(BNX2FC_FLAG_SESSION_READY, + &tgt->flags)); + } + return SUCCESS; + } + if (rc == FAILED) { + kref_put(&io_req->refcount, bnx2fc_cmd_release); + spin_unlock_bh(&tgt->tgt_lock); + return rc; } spin_unlock_bh(&tgt->tgt_lock); @@ -1273,8 +1247,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) /* Let the scsi-ml try to recover this command */ printk(KERN_ERR PFX "abort failed, xid = 0x%x\n", io_req->xid); - rc = bnx2fc_expl_logo(lport, io_req); - goto out; + rc = FAILED; } else { /* * We come here even when there was a race condition @@ -1286,10 +1259,9 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) bnx2fc_scsi_done(io_req, DID_ABORT); kref_put(&io_req->refcount, bnx2fc_cmd_release); } -done: + /* release the reference taken in eh_abort */ kref_put(&io_req->refcount, bnx2fc_cmd_release); -out: spin_unlock_bh(&tgt->tgt_lock); return rc; } diff --git a/trunk/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/trunk/drivers/scsi/bnx2fc/bnx2fc_tgt.c index 082a25c3117e..c1800b531270 100644 --- a/trunk/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/trunk/drivers/scsi/bnx2fc/bnx2fc_tgt.c @@ -185,16 +185,6 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt) BUG_ON(rc); } - list_for_each_safe(list, tmp, &tgt->active_tm_queue) { - i++; - io_req = (struct bnx2fc_cmd *)list; - list_del_init(&io_req->link); - io_req->on_tmf_queue = 0; - BNX2FC_IO_DBG(io_req, "tm_queue cleanup\n"); - if (io_req->wait_for_comp) - complete(&io_req->tm_done); - } - list_for_each_safe(list, tmp, &tgt->els_queue) { i++; io_req = (struct bnx2fc_cmd *)list; @@ -223,17 +213,8 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt) BNX2FC_IO_DBG(io_req, "retire_queue flush\n"); - if (cancel_delayed_work(&io_req->timeout_work)) { - if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT, - &io_req->req_flags)) { - /* Handle eh_abort timeout */ - BNX2FC_IO_DBG(io_req, "eh_abort for IO " - "in retire_q\n"); - if (io_req->wait_for_comp) - complete(&io_req->tm_done); - } + if (cancel_delayed_work(&io_req->timeout_work)) kref_put(&io_req->refcount, bnx2fc_cmd_release); - } clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags); } diff --git a/trunk/drivers/scsi/fcoe/Makefile b/trunk/drivers/scsi/fcoe/Makefile index aed0f5db3668..f6d37d0271f7 100644 --- a/trunk/drivers/scsi/fcoe/Makefile +++ b/trunk/drivers/scsi/fcoe/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_FCOE) += fcoe.o obj-$(CONFIG_LIBFCOE) += libfcoe.o -libfcoe-objs := fcoe_ctlr.o fcoe_transport.o fcoe_sysfs.o +libfcoe-objs := fcoe_ctlr.o fcoe_transport.o diff --git a/trunk/drivers/scsi/fcoe/fcoe.c b/trunk/drivers/scsi/fcoe/fcoe.c index fe30b1b65e1d..76e3d0b5bfa6 100644 --- a/trunk/drivers/scsi/fcoe/fcoe.c +++ b/trunk/drivers/scsi/fcoe/fcoe.c @@ -41,7 +41,6 @@ #include #include -#include #include #include @@ -151,21 +150,6 @@ static int fcoe_vport_create(struct fc_vport *, bool disabled); static int fcoe_vport_disable(struct fc_vport *, bool disable); static void fcoe_set_vport_symbolic_name(struct fc_vport *); static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); -static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *); -static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *); - -static struct fcoe_sysfs_function_template fcoe_sysfs_templ = { - .get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode, - .get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb, - .get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb, - .get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb, - .get_fcoe_ctlr_symb_err = fcoe_ctlr_get_lesb, - .get_fcoe_ctlr_err_block = fcoe_ctlr_get_lesb, - .get_fcoe_ctlr_fcs_error = fcoe_ctlr_get_lesb, - - .get_fcoe_fcf_selected = fcoe_fcf_get_selected, - .get_fcoe_fcf_vlan_id = fcoe_fcf_get_vlan_id, -}; static struct libfc_function_template fcoe_libfc_fcn_templ = { .frame_send = fcoe_xmit, @@ -298,7 +282,7 @@ static struct scsi_host_template fcoe_shost_template = { static int fcoe_interface_setup(struct fcoe_interface *fcoe, struct net_device *netdev) { - struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); + struct fcoe_ctlr *fip = &fcoe->ctlr; struct netdev_hw_addr *ha; struct net_device *real_dev; u8 flogi_maddr[ETH_ALEN]; @@ -382,10 +366,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, enum fip_state fip_mode) { - struct fcoe_ctlr_device *ctlr_dev; - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; - int size; int err; if (!try_module_get(THIS_MODULE)) { @@ -395,32 +376,27 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, goto out; } - size = sizeof(struct fcoe_ctlr) + sizeof(struct fcoe_interface); - ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &fcoe_sysfs_templ, - size); - if (!ctlr_dev) { - FCOE_DBG("Failed to add fcoe_ctlr_device\n"); + fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL); + if (!fcoe) { + FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n"); fcoe = ERR_PTR(-ENOMEM); goto out_putmod; } - ctlr = fcoe_ctlr_device_priv(ctlr_dev); - fcoe = fcoe_ctlr_priv(ctlr); - dev_hold(netdev); /* * Initialize FIP. */ - fcoe_ctlr_init(ctlr, fip_mode); - ctlr->send = fcoe_fip_send; - ctlr->update_mac = fcoe_update_src_mac; - ctlr->get_src_addr = fcoe_get_src_mac; + fcoe_ctlr_init(&fcoe->ctlr, fip_mode); + fcoe->ctlr.send = fcoe_fip_send; + fcoe->ctlr.update_mac = fcoe_update_src_mac; + fcoe->ctlr.get_src_addr = fcoe_get_src_mac; err = fcoe_interface_setup(fcoe, netdev); if (err) { - fcoe_ctlr_destroy(ctlr); - fcoe_ctlr_device_delete(ctlr_dev); + fcoe_ctlr_destroy(&fcoe->ctlr); + kfree(fcoe); dev_put(netdev); fcoe = ERR_PTR(err); goto out_putmod; @@ -443,7 +419,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, static void fcoe_interface_remove(struct fcoe_interface *fcoe) { struct net_device *netdev = fcoe->netdev; - struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); + struct fcoe_ctlr *fip = &fcoe->ctlr; u8 flogi_maddr[ETH_ALEN]; const struct net_device_ops *ops; @@ -486,8 +462,7 @@ static void fcoe_interface_remove(struct fcoe_interface *fcoe) static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) { struct net_device *netdev = fcoe->netdev; - struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); - struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); + struct fcoe_ctlr *fip = &fcoe->ctlr; rtnl_lock(); if (!fcoe->removed) @@ -497,8 +472,8 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) /* Release the self-reference taken during fcoe_interface_create() */ /* tear-down the FCoE controller */ fcoe_ctlr_destroy(fip); - scsi_host_put(fip->lp->host); - fcoe_ctlr_device_delete(ctlr_dev); + scsi_host_put(fcoe->ctlr.lp->host); + kfree(fcoe); dev_put(netdev); module_put(THIS_MODULE); } @@ -518,11 +493,9 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev, struct net_device *orig_dev) { struct fcoe_interface *fcoe; - struct fcoe_ctlr *ctlr; fcoe = container_of(ptype, struct fcoe_interface, fip_packet_type); - ctlr = fcoe_to_ctlr(fcoe); - fcoe_ctlr_recv(ctlr, skb); + fcoe_ctlr_recv(&fcoe->ctlr, skb); return 0; } @@ -672,13 +645,11 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) u32 mfs; u64 wwnn, wwpn; struct fcoe_interface *fcoe; - struct fcoe_ctlr *ctlr; struct fcoe_port *port; /* Setup lport private data to point to fcoe softc */ port = lport_priv(lport); fcoe = port->priv; - ctlr = fcoe_to_ctlr(fcoe); /* * Determine max frame size based on underlying device and optional @@ -705,10 +676,10 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) if (!lport->vport) { if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) - wwnn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, 1, 0); + wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0); fc_set_wwnn(lport, wwnn); if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN)) - wwpn = fcoe_wwn_from_mac(ctlr->ctl_src_addr, + wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 2, 0); fc_set_wwpn(lport, wwpn); } @@ -1085,7 +1056,6 @@ static int fcoe_ddp_done(struct fc_lport *lport, u16 xid) static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, struct device *parent, int npiv) { - struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); struct net_device *netdev = fcoe->netdev; struct fc_lport *lport, *n_port; struct fcoe_port *port; @@ -1149,7 +1119,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, } /* Initialize the library */ - rc = fcoe_libfc_config(lport, ctlr, &fcoe_libfc_fcn_templ, 1); + rc = fcoe_libfc_config(lport, &fcoe->ctlr, &fcoe_libfc_fcn_templ, 1); if (rc) { FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " "interface\n"); @@ -1416,7 +1386,6 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, { struct fc_lport *lport; struct fcoe_rcv_info *fr; - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; struct fc_frame_header *fh; struct fcoe_percpu_s *fps; @@ -1424,8 +1393,7 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, unsigned int cpu; fcoe = container_of(ptype, struct fcoe_interface, fcoe_packet_type); - ctlr = fcoe_to_ctlr(fcoe); - lport = ctlr->lp; + lport = fcoe->ctlr.lp; if (unlikely(!lport)) { FCOE_NETDEV_DBG(netdev, "Cannot find hba structure"); goto err2; @@ -1441,8 +1409,8 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, eh = eth_hdr(skb); - if (is_fip_mode(ctlr) && - compare_ether_addr(eh->h_source, ctlr->dest_addr)) { + if (is_fip_mode(&fcoe->ctlr) && + compare_ether_addr(eh->h_source, fcoe->ctlr.dest_addr)) { FCOE_NETDEV_DBG(netdev, "wrong source mac address:%pM\n", eh->h_source); goto err; @@ -1576,7 +1544,6 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) unsigned int elen; /* eth header, may include vlan */ struct fcoe_port *port = lport_priv(lport); struct fcoe_interface *fcoe = port->priv; - struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); u8 sof, eof; struct fcoe_hdr *hp; @@ -1592,7 +1559,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) } if (unlikely(fh->fh_type == FC_TYPE_ELS) && - fcoe_ctlr_els_send(ctlr, lport, skb)) + fcoe_ctlr_els_send(&fcoe->ctlr, lport, skb)) return 0; sof = fr_sof(fp); @@ -1656,12 +1623,12 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) /* fill up mac and fcoe headers */ eh = eth_hdr(skb); eh->h_proto = htons(ETH_P_FCOE); - memcpy(eh->h_dest, ctlr->dest_addr, ETH_ALEN); - if (ctlr->map_dest) + memcpy(eh->h_dest, fcoe->ctlr.dest_addr, ETH_ALEN); + if (fcoe->ctlr.map_dest) memcpy(eh->h_dest + 3, fh->fh_d_id, 3); - if (unlikely(ctlr->flogi_oxid != FC_XID_UNKNOWN)) - memcpy(eh->h_source, ctlr->ctl_src_addr, ETH_ALEN); + if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) + memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); else memcpy(eh->h_source, port->data_src_addr, ETH_ALEN); @@ -1710,7 +1677,6 @@ static void fcoe_percpu_flush_done(struct sk_buff *skb) static inline int fcoe_filter_frames(struct fc_lport *lport, struct fc_frame *fp) { - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; struct fc_frame_header *fh; struct sk_buff *skb = (struct sk_buff *)fp; @@ -1732,8 +1698,7 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, return 0; fcoe = ((struct fcoe_port *)lport_priv(lport))->priv; - ctlr = fcoe_to_ctlr(fcoe); - if (is_fip_mode(ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && + if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO && ntoh24(fh->fh_s_id) == FC_FID_FLOGI) { FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n"); return -EINVAL; @@ -1912,7 +1877,6 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, ulong event, void *ptr) { struct dcb_app_type *entry = ptr; - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; struct net_device *netdev; struct fcoe_port *port; @@ -1930,8 +1894,6 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, if (!fcoe) return NOTIFY_OK; - ctlr = fcoe_to_ctlr(fcoe); - if (entry->dcbx & DCB_CAP_DCBX_VER_CEE) prio = ffs(entry->app.priority) - 1; else @@ -1942,10 +1904,10 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier, if (entry->app.protocol == ETH_P_FIP || entry->app.protocol == ETH_P_FCOE) - ctlr->priority = prio; + fcoe->ctlr.priority = prio; if (entry->app.protocol == ETH_P_FCOE) { - port = lport_priv(ctlr->lp); + port = lport_priv(fcoe->ctlr.lp); port->priority = prio; } @@ -1967,7 +1929,6 @@ static int fcoe_device_notification(struct notifier_block *notifier, { struct fc_lport *lport = NULL; struct net_device *netdev = ptr; - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; struct fcoe_port *port; struct fcoe_dev_stats *stats; @@ -1977,8 +1938,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, list_for_each_entry(fcoe, &fcoe_hostlist, list) { if (fcoe->netdev == netdev) { - ctlr = fcoe_to_ctlr(fcoe); - lport = ctlr->lp; + lport = fcoe->ctlr.lp; break; } } @@ -2007,7 +1967,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, break; case NETDEV_UNREGISTER: list_del(&fcoe->list); - port = lport_priv(ctlr->lp); + port = lport_priv(fcoe->ctlr.lp); queue_work(fcoe_wq, &port->destroy_work); goto out; break; @@ -2022,8 +1982,8 @@ static int fcoe_device_notification(struct notifier_block *notifier, fcoe_link_speed_update(lport); if (link_possible && !fcoe_link_ok(lport)) - fcoe_ctlr_link_up(ctlr); - else if (fcoe_ctlr_link_down(ctlr)) { + fcoe_ctlr_link_up(&fcoe->ctlr); + else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { stats = per_cpu_ptr(lport->dev_stats, get_cpu()); stats->LinkFailureCount++; put_cpu(); @@ -2043,7 +2003,6 @@ static int fcoe_device_notification(struct notifier_block *notifier, */ static int fcoe_disable(struct net_device *netdev) { - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; int rc = 0; @@ -2054,9 +2013,8 @@ static int fcoe_disable(struct net_device *netdev) rtnl_unlock(); if (fcoe) { - ctlr = fcoe_to_ctlr(fcoe); - fcoe_ctlr_link_down(ctlr); - fcoe_clean_pending_queue(ctlr->lp); + fcoe_ctlr_link_down(&fcoe->ctlr); + fcoe_clean_pending_queue(fcoe->ctlr.lp); } else rc = -ENODEV; @@ -2074,7 +2032,6 @@ static int fcoe_disable(struct net_device *netdev) */ static int fcoe_enable(struct net_device *netdev) { - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; int rc = 0; @@ -2083,17 +2040,11 @@ static int fcoe_enable(struct net_device *netdev) fcoe = fcoe_hostlist_lookup_port(netdev); rtnl_unlock(); - if (!fcoe) { + if (!fcoe) rc = -ENODEV; - goto out; - } - - ctlr = fcoe_to_ctlr(fcoe); - - if (!fcoe_link_ok(ctlr->lp)) - fcoe_ctlr_link_up(ctlr); + else if (!fcoe_link_ok(fcoe->ctlr.lp)) + fcoe_ctlr_link_up(&fcoe->ctlr); -out: mutex_unlock(&fcoe_config_mutex); return rc; } @@ -2108,7 +2059,6 @@ static int fcoe_enable(struct net_device *netdev) */ static int fcoe_destroy(struct net_device *netdev) { - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; struct fc_lport *lport; struct fcoe_port *port; @@ -2121,8 +2071,7 @@ static int fcoe_destroy(struct net_device *netdev) rc = -ENODEV; goto out_nodev; } - ctlr = fcoe_to_ctlr(fcoe); - lport = ctlr->lp; + lport = fcoe->ctlr.lp; port = lport_priv(lport); list_del(&fcoe->list); queue_work(fcoe_wq, &port->destroy_work); @@ -2177,8 +2126,7 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) int dcbx; u8 fup, up; struct net_device *netdev = fcoe->realdev; - struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); - struct fcoe_port *port = lport_priv(ctlr->lp); + struct fcoe_port *port = lport_priv(fcoe->ctlr.lp); struct dcb_app app = { .priority = 0, .protocol = ETH_P_FCOE @@ -2201,7 +2149,7 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) } port->priority = ffs(up) ? ffs(up) - 1 : 0; - ctlr->priority = ffs(fup) ? ffs(fup) - 1 : port->priority; + fcoe->ctlr.priority = ffs(fup) ? ffs(fup) - 1 : port->priority; } #endif } @@ -2218,8 +2166,6 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) { int rc = 0; - struct fcoe_ctlr_device *ctlr_dev; - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; struct fc_lport *lport; @@ -2238,9 +2184,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) goto out_nodev; } - ctlr = fcoe_to_ctlr(fcoe); - ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr); - lport = fcoe_if_create(fcoe, &ctlr_dev->dev, 0); + lport = fcoe_if_create(fcoe, &netdev->dev, 0); if (IS_ERR(lport)) { printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", netdev->name); @@ -2251,7 +2195,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) } /* Make this the "master" N_Port */ - ctlr->lp = lport; + fcoe->ctlr.lp = lport; /* setup DCB priority attributes. */ fcoe_dcb_create(fcoe); @@ -2264,7 +2208,7 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) fc_fabric_login(lport); if (!fcoe_link_ok(lport)) { rtnl_unlock(); - fcoe_ctlr_link_up(ctlr); + fcoe_ctlr_link_up(&fcoe->ctlr); mutex_unlock(&fcoe_config_mutex); return rc; } @@ -2376,12 +2320,11 @@ static int fcoe_reset(struct Scsi_Host *shost) struct fc_lport *lport = shost_priv(shost); struct fcoe_port *port = lport_priv(lport); struct fcoe_interface *fcoe = port->priv; - struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); - fcoe_ctlr_link_down(ctlr); - fcoe_clean_pending_queue(ctlr->lp); - if (!fcoe_link_ok(ctlr->lp)) - fcoe_ctlr_link_up(ctlr); + fcoe_ctlr_link_down(&fcoe->ctlr); + fcoe_clean_pending_queue(fcoe->ctlr.lp); + if (!fcoe_link_ok(fcoe->ctlr.lp)) + fcoe_ctlr_link_up(&fcoe->ctlr); return 0; } @@ -2416,12 +2359,10 @@ fcoe_hostlist_lookup_port(const struct net_device *netdev) */ static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) { - struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; fcoe = fcoe_hostlist_lookup_port(netdev); - ctlr = fcoe_to_ctlr(fcoe); - return (fcoe) ? ctlr->lp : NULL; + return (fcoe) ? fcoe->ctlr.lp : NULL; } /** @@ -2525,7 +2466,6 @@ module_init(fcoe_init); static void __exit fcoe_exit(void) { struct fcoe_interface *fcoe, *tmp; - struct fcoe_ctlr *ctlr; struct fcoe_port *port; unsigned int cpu; @@ -2537,8 +2477,7 @@ static void __exit fcoe_exit(void) rtnl_lock(); list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) { list_del(&fcoe->list); - ctlr = fcoe_to_ctlr(fcoe); - port = lport_priv(ctlr->lp); + port = lport_priv(fcoe->ctlr.lp); queue_work(fcoe_wq, &port->destroy_work); } rtnl_unlock(); @@ -2634,7 +2573,7 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did, { struct fcoe_port *port = lport_priv(lport); struct fcoe_interface *fcoe = port->priv; - struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe); + struct fcoe_ctlr *fip = &fcoe->ctlr; struct fc_frame_header *fh = fc_frame_header_get(fp); switch (op) { @@ -2791,40 +2730,6 @@ static void fcoe_get_lesb(struct fc_lport *lport, __fcoe_get_lesb(lport, fc_lesb, netdev); } -static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev) -{ - struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); - struct net_device *netdev = fcoe_netdev(fip->lp); - struct fcoe_fc_els_lesb *fcoe_lesb; - struct fc_els_lesb fc_lesb; - - __fcoe_get_lesb(fip->lp, &fc_lesb, netdev); - fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb); - - ctlr_dev->lesb.lesb_link_fail = - ntohl(fcoe_lesb->lesb_link_fail); - ctlr_dev->lesb.lesb_vlink_fail = - ntohl(fcoe_lesb->lesb_vlink_fail); - ctlr_dev->lesb.lesb_miss_fka = - ntohl(fcoe_lesb->lesb_miss_fka); - ctlr_dev->lesb.lesb_symb_err = - ntohl(fcoe_lesb->lesb_symb_err); - ctlr_dev->lesb.lesb_err_block = - ntohl(fcoe_lesb->lesb_err_block); - ctlr_dev->lesb.lesb_fcs_error = - ntohl(fcoe_lesb->lesb_fcs_error); -} - -static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) -{ - struct fcoe_ctlr_device *ctlr_dev = - fcoe_fcf_dev_to_ctlr_dev(fcf_dev); - struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); - struct fcoe_interface *fcoe = fcoe_ctlr_priv(ctlr); - - fcf_dev->vlan_id = vlan_dev_vlan_id(fcoe->netdev); -} - /** * fcoe_set_port_id() - Callback from libfc when Port_ID is set. * @lport: the local port @@ -2842,8 +2747,7 @@ static void fcoe_set_port_id(struct fc_lport *lport, { struct fcoe_port *port = lport_priv(lport); struct fcoe_interface *fcoe = port->priv; - struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); if (fp && fc_frame_payload_op(fp) == ELS_FLOGI) - fcoe_ctlr_recv_flogi(ctlr, lport, fp); + fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp); } diff --git a/trunk/drivers/scsi/fcoe/fcoe.h b/trunk/drivers/scsi/fcoe/fcoe.h index a624add4f8ec..96ac938d39cc 100644 --- a/trunk/drivers/scsi/fcoe/fcoe.h +++ b/trunk/drivers/scsi/fcoe/fcoe.h @@ -68,6 +68,7 @@ do { \ * @netdev: The associated net device * @fcoe_packet_type: FCoE packet type * @fip_packet_type: FIP packet type + * @ctlr: The FCoE controller (for FIP) * @oem: The offload exchange manager for all local port * instances associated with this port * @removed: Indicates fcoe interface removed from net device @@ -79,15 +80,12 @@ struct fcoe_interface { struct net_device *realdev; struct packet_type fcoe_packet_type; struct packet_type fip_packet_type; + struct fcoe_ctlr ctlr; struct fc_exch_mgr *oem; u8 removed; }; -#define fcoe_to_ctlr(x) \ - (struct fcoe_ctlr *)(((struct fcoe_ctlr *)(x)) - 1) - -#define fcoe_from_ctlr(x) \ - ((struct fcoe_interface *)((x) + 1)) +#define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr) /** * fcoe_netdev() - Return the net device associated with a local port diff --git a/trunk/drivers/scsi/fcoe/fcoe_ctlr.c b/trunk/drivers/scsi/fcoe/fcoe_ctlr.c index d68d57241ee6..5a4c7250aa77 100644 --- a/trunk/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/trunk/drivers/scsi/fcoe/fcoe_ctlr.c @@ -160,76 +160,6 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) } EXPORT_SYMBOL(fcoe_ctlr_init); -static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new) -{ - struct fcoe_ctlr *fip = new->fip; - struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); - struct fcoe_fcf_device temp, *fcf_dev; - int rc = 0; - - LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", - new->fabric_name, new->fcf_mac); - - mutex_lock(&ctlr_dev->lock); - - temp.fabric_name = new->fabric_name; - temp.switch_name = new->switch_name; - temp.fc_map = new->fc_map; - temp.vfid = new->vfid; - memcpy(temp.mac, new->fcf_mac, ETH_ALEN); - temp.priority = new->pri; - temp.fka_period = new->fka_period; - temp.selected = 0; /* default to unselected */ - - fcf_dev = fcoe_fcf_device_add(ctlr_dev, &temp); - if (unlikely(!fcf_dev)) { - rc = -ENOMEM; - goto out; - } - - /* - * The fcoe_sysfs layer can return a CONNECTED fcf that - * has a priv (fcf was never deleted) or a CONNECTED fcf - * that doesn't have a priv (fcf was deleted). However, - * libfcoe will always delete FCFs before trying to add - * them. This is ensured because both recv_adv and - * age_fcfs are protected by the the fcoe_ctlr's mutex. - * This means that we should never get a FCF with a - * non-NULL priv pointer. - */ - BUG_ON(fcf_dev->priv); - - fcf_dev->priv = new; - new->fcf_dev = fcf_dev; - - list_add(&new->list, &fip->fcfs); - fip->fcf_count++; - -out: - mutex_unlock(&ctlr_dev->lock); - return rc; -} - -static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new) -{ - struct fcoe_ctlr *fip = new->fip; - struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); - struct fcoe_fcf_device *fcf_dev; - - list_del(&new->list); - fip->fcf_count--; - - mutex_lock(&ctlr_dev->lock); - - fcf_dev = fcoe_fcf_to_fcf_dev(new); - WARN_ON(!fcf_dev); - new->fcf_dev = NULL; - fcoe_fcf_device_delete(fcf_dev); - kfree(new); - - mutex_unlock(&ctlr_dev->lock); -} - /** * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller * @fip: The FCoE controller whose FCFs are to be reset @@ -243,10 +173,10 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) fip->sel_fcf = NULL; list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { - fcoe_sysfs_fcf_del(fcf); + list_del(&fcf->list); + kfree(fcf); } - WARN_ON(fip->fcf_count); - + fip->fcf_count = 0; fip->sel_time = 0; } @@ -787,11 +717,8 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); unsigned long deadline; unsigned long sel_time = 0; - struct list_head del_list; struct fcoe_dev_stats *stats; - INIT_LIST_HEAD(&del_list); - stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu()); list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { @@ -812,13 +739,10 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) if (time_after_eq(jiffies, deadline)) { if (fip->sel_fcf == fcf) fip->sel_fcf = NULL; - /* - * Move to delete list so we can call - * fcoe_sysfs_fcf_del (which can sleep) - * after the put_cpu(). - */ list_del(&fcf->list); - list_add(&fcf->list, &del_list); + WARN_ON(!fip->fcf_count); + fip->fcf_count--; + kfree(fcf); stats->VLinkFailureCount++; } else { if (time_after(next_timer, deadline)) @@ -829,12 +753,6 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) } } put_cpu(); - - list_for_each_entry_safe(fcf, next, &del_list, list) { - /* Removes fcf from current list */ - fcoe_sysfs_fcf_del(fcf); - } - if (sel_time && !fip->sel_fcf && !fip->sel_time) { sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); fip->sel_time = sel_time; @@ -985,23 +903,23 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) { struct fcoe_fcf *fcf; struct fcoe_fcf new; + struct fcoe_fcf *found; unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV); int first = 0; int mtu_valid; - int found = 0; - int rc = 0; if (fcoe_ctlr_parse_adv(fip, skb, &new)) return; mutex_lock(&fip->ctlr_mutex); first = list_empty(&fip->fcfs); + found = NULL; list_for_each_entry(fcf, &fip->fcfs, list) { if (fcf->switch_name == new.switch_name && fcf->fabric_name == new.fabric_name && fcf->fc_map == new.fc_map && compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { - found = 1; + found = fcf; break; } } @@ -1013,16 +931,9 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) if (!fcf) goto out; + fip->fcf_count++; memcpy(fcf, &new, sizeof(new)); - fcf->fip = fip; - rc = fcoe_sysfs_fcf_add(fcf); - if (rc) { - printk(KERN_ERR "Failed to allocate sysfs instance " - "for FCF, fab %16.16llx mac %pM\n", - new.fabric_name, new.fcf_mac); - kfree(fcf); - goto out; - } + list_add(&fcf->list, &fip->fcfs); } else { /* * Update the FCF's keep-alive descriptor flags. @@ -1043,7 +954,6 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) fcf->fka_period = new.fka_period; memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN); } - mtu_valid = fcoe_ctlr_mtu_valid(fcf); fcf->time = jiffies; if (!found) @@ -1086,7 +996,6 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) time_before(fip->sel_time, fip->timer.expires)) mod_timer(&fip->timer, fip->sel_time); } - out: mutex_unlock(&fip->ctlr_mutex); } @@ -2809,9 +2718,9 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) /** * fcoe_libfc_config() - Sets up libfc related properties for local port - * @lport: The local port to configure libfc for - * @fip: The FCoE controller in use by the local port - * @tt: The libfc function template + * @lp: The local port to configure libfc for + * @fip: The FCoE controller in use by the local port + * @tt: The libfc function template * @init_fcp: If non-zero, the FCP portion of libfc should be initialized * * Returns : 0 for success @@ -2844,43 +2753,3 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip, return 0; } EXPORT_SYMBOL_GPL(fcoe_libfc_config); - -void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev) -{ - struct fcoe_ctlr_device *ctlr_dev = fcoe_fcf_dev_to_ctlr_dev(fcf_dev); - struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); - struct fcoe_fcf *fcf; - - mutex_lock(&fip->ctlr_mutex); - mutex_lock(&ctlr_dev->lock); - - fcf = fcoe_fcf_device_priv(fcf_dev); - if (fcf) - fcf_dev->selected = (fcf == fip->sel_fcf) ? 1 : 0; - else - fcf_dev->selected = 0; - - mutex_unlock(&ctlr_dev->lock); - mutex_unlock(&fip->ctlr_mutex); -} -EXPORT_SYMBOL(fcoe_fcf_get_selected); - -void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *ctlr_dev) -{ - struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); - - mutex_lock(&ctlr->ctlr_mutex); - switch (ctlr->mode) { - case FIP_MODE_FABRIC: - ctlr_dev->mode = FIP_CONN_TYPE_FABRIC; - break; - case FIP_MODE_VN2VN: - ctlr_dev->mode = FIP_CONN_TYPE_VN2VN; - break; - default: - ctlr_dev->mode = FIP_CONN_TYPE_UNKNOWN; - break; - } - mutex_unlock(&ctlr->ctlr_mutex); -} -EXPORT_SYMBOL(fcoe_ctlr_get_fip_mode); diff --git a/trunk/drivers/scsi/fcoe/fcoe_sysfs.c b/trunk/drivers/scsi/fcoe/fcoe_sysfs.c deleted file mode 100644 index 2bc163198d33..000000000000 --- a/trunk/drivers/scsi/fcoe/fcoe_sysfs.c +++ /dev/null @@ -1,832 +0,0 @@ -/* - * Copyright(c) 2011 - 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Maintained at www.Open-FCoE.org - */ - -#include -#include -#include -#include - -#include - -static atomic_t ctlr_num; -static atomic_t fcf_num; - -/* - * fcoe_fcf_dev_loss_tmo: the default number of seconds that fcoe sysfs - * should insulate the loss of a fcf. - */ -static unsigned int fcoe_fcf_dev_loss_tmo = 1800; /* seconds */ - -module_param_named(fcf_dev_loss_tmo, fcoe_fcf_dev_loss_tmo, - uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(fcf_dev_loss_tmo, - "Maximum number of seconds that libfcoe should" - " insulate the loss of a fcf. Once this value is" - " exceeded, the fcf is removed."); - -/* - * These are used by the fcoe_*_show_function routines, they - * are intentionally placed in the .c file as they're not intended - * for use throughout the code. - */ -#define fcoe_ctlr_id(x) \ - ((x)->id) -#define fcoe_ctlr_work_q_name(x) \ - ((x)->work_q_name) -#define fcoe_ctlr_work_q(x) \ - ((x)->work_q) -#define fcoe_ctlr_devloss_work_q_name(x) \ - ((x)->devloss_work_q_name) -#define fcoe_ctlr_devloss_work_q(x) \ - ((x)->devloss_work_q) -#define fcoe_ctlr_mode(x) \ - ((x)->mode) -#define fcoe_ctlr_fcf_dev_loss_tmo(x) \ - ((x)->fcf_dev_loss_tmo) -#define fcoe_ctlr_link_fail(x) \ - ((x)->lesb.lesb_link_fail) -#define fcoe_ctlr_vlink_fail(x) \ - ((x)->lesb.lesb_vlink_fail) -#define fcoe_ctlr_miss_fka(x) \ - ((x)->lesb.lesb_miss_fka) -#define fcoe_ctlr_symb_err(x) \ - ((x)->lesb.lesb_symb_err) -#define fcoe_ctlr_err_block(x) \ - ((x)->lesb.lesb_err_block) -#define fcoe_ctlr_fcs_error(x) \ - ((x)->lesb.lesb_fcs_error) -#define fcoe_fcf_state(x) \ - ((x)->state) -#define fcoe_fcf_fabric_name(x) \ - ((x)->fabric_name) -#define fcoe_fcf_switch_name(x) \ - ((x)->switch_name) -#define fcoe_fcf_fc_map(x) \ - ((x)->fc_map) -#define fcoe_fcf_vfid(x) \ - ((x)->vfid) -#define fcoe_fcf_mac(x) \ - ((x)->mac) -#define fcoe_fcf_priority(x) \ - ((x)->priority) -#define fcoe_fcf_fka_period(x) \ - ((x)->fka_period) -#define fcoe_fcf_dev_loss_tmo(x) \ - ((x)->dev_loss_tmo) -#define fcoe_fcf_selected(x) \ - ((x)->selected) -#define fcoe_fcf_vlan_id(x) \ - ((x)->vlan_id) - -/* - * dev_loss_tmo attribute - */ -static int fcoe_str_to_dev_loss(const char *buf, unsigned long *val) -{ - int ret; - - ret = kstrtoul(buf, 0, val); - if (ret || *val < 0) - return -EINVAL; - /* - * Check for overflow; dev_loss_tmo is u32 - */ - if (*val > UINT_MAX) - return -EINVAL; - - return 0; -} - -static int fcoe_fcf_set_dev_loss_tmo(struct fcoe_fcf_device *fcf, - unsigned long val) -{ - if ((fcf->state == FCOE_FCF_STATE_UNKNOWN) || - (fcf->state == FCOE_FCF_STATE_DISCONNECTED) || - (fcf->state == FCOE_FCF_STATE_DELETED)) - return -EBUSY; - /* - * Check for overflow; dev_loss_tmo is u32 - */ - if (val > UINT_MAX) - return -EINVAL; - - fcoe_fcf_dev_loss_tmo(fcf) = val; - return 0; -} - -#define FCOE_DEVICE_ATTR(_prefix, _name, _mode, _show, _store) \ -struct device_attribute device_attr_fcoe_##_prefix##_##_name = \ - __ATTR(_name, _mode, _show, _store) - -#define fcoe_ctlr_show_function(field, format_string, sz, cast) \ -static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); \ - if (ctlr->f->get_fcoe_ctlr_##field) \ - ctlr->f->get_fcoe_ctlr_##field(ctlr); \ - return snprintf(buf, sz, format_string, \ - cast fcoe_ctlr_##field(ctlr)); \ -} - -#define fcoe_fcf_show_function(field, format_string, sz, cast) \ -static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct fcoe_fcf_device *fcf = dev_to_fcf(dev); \ - struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); \ - if (ctlr->f->get_fcoe_fcf_##field) \ - ctlr->f->get_fcoe_fcf_##field(fcf); \ - return snprintf(buf, sz, format_string, \ - cast fcoe_fcf_##field(fcf)); \ -} - -#define fcoe_ctlr_private_show_function(field, format_string, sz, cast) \ -static ssize_t show_fcoe_ctlr_device_##field(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); \ - return snprintf(buf, sz, format_string, cast fcoe_ctlr_##field(ctlr)); \ -} - -#define fcoe_fcf_private_show_function(field, format_string, sz, cast) \ -static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct fcoe_fcf_device *fcf = dev_to_fcf(dev); \ - return snprintf(buf, sz, format_string, cast fcoe_fcf_##field(fcf)); \ -} - -#define fcoe_ctlr_private_rd_attr(field, format_string, sz) \ - fcoe_ctlr_private_show_function(field, format_string, sz, ) \ - static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ - show_fcoe_ctlr_device_##field, NULL) - -#define fcoe_ctlr_rd_attr(field, format_string, sz) \ - fcoe_ctlr_show_function(field, format_string, sz, ) \ - static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ - show_fcoe_ctlr_device_##field, NULL) - -#define fcoe_fcf_rd_attr(field, format_string, sz) \ - fcoe_fcf_show_function(field, format_string, sz, ) \ - static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ - show_fcoe_fcf_device_##field, NULL) - -#define fcoe_fcf_private_rd_attr(field, format_string, sz) \ - fcoe_fcf_private_show_function(field, format_string, sz, ) \ - static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ - show_fcoe_fcf_device_##field, NULL) - -#define fcoe_ctlr_private_rd_attr_cast(field, format_string, sz, cast) \ - fcoe_ctlr_private_show_function(field, format_string, sz, (cast)) \ - static FCOE_DEVICE_ATTR(ctlr, field, S_IRUGO, \ - show_fcoe_ctlr_device_##field, NULL) - -#define fcoe_fcf_private_rd_attr_cast(field, format_string, sz, cast) \ - fcoe_fcf_private_show_function(field, format_string, sz, (cast)) \ - static FCOE_DEVICE_ATTR(fcf, field, S_IRUGO, \ - show_fcoe_fcf_device_##field, NULL) - -#define fcoe_enum_name_search(title, table_type, table) \ -static const char *get_fcoe_##title##_name(enum table_type table_key) \ -{ \ - int i; \ - char *name = NULL; \ - \ - for (i = 0; i < ARRAY_SIZE(table); i++) { \ - if (table[i].value == table_key) { \ - name = table[i].name; \ - break; \ - } \ - } \ - return name; \ -} - -static struct { - enum fcf_state value; - char *name; -} fcf_state_names[] = { - { FCOE_FCF_STATE_UNKNOWN, "Unknown" }, - { FCOE_FCF_STATE_DISCONNECTED, "Disconnected" }, - { FCOE_FCF_STATE_CONNECTED, "Connected" }, -}; -fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names) -#define FCOE_FCF_STATE_MAX_NAMELEN 50 - -static ssize_t show_fcf_state(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct fcoe_fcf_device *fcf = dev_to_fcf(dev); - const char *name; - name = get_fcoe_fcf_state_name(fcf->state); - if (!name) - return -EINVAL; - return snprintf(buf, FCOE_FCF_STATE_MAX_NAMELEN, "%s\n", name); -} -static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL); - -static struct { - enum fip_conn_type value; - char *name; -} fip_conn_type_names[] = { - { FIP_CONN_TYPE_UNKNOWN, "Unknown" }, - { FIP_CONN_TYPE_FABRIC, "Fabric" }, - { FIP_CONN_TYPE_VN2VN, "VN2VN" }, -}; -fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names) -#define FCOE_CTLR_MODE_MAX_NAMELEN 50 - -static ssize_t show_ctlr_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); - const char *name; - - if (ctlr->f->get_fcoe_ctlr_mode) - ctlr->f->get_fcoe_ctlr_mode(ctlr); - - name = get_fcoe_ctlr_mode_name(ctlr->mode); - if (!name) - return -EINVAL; - return snprintf(buf, FCOE_CTLR_MODE_MAX_NAMELEN, - "%s\n", name); -} -static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO, - show_ctlr_mode, NULL); - -static ssize_t -store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); - struct fcoe_fcf_device *fcf; - unsigned long val; - int rc; - - rc = fcoe_str_to_dev_loss(buf, &val); - if (rc) - return rc; - - fcoe_ctlr_fcf_dev_loss_tmo(ctlr) = val; - mutex_lock(&ctlr->lock); - list_for_each_entry(fcf, &ctlr->fcfs, peers) - fcoe_fcf_set_dev_loss_tmo(fcf, val); - mutex_unlock(&ctlr->lock); - return count; -} -fcoe_ctlr_private_show_function(fcf_dev_loss_tmo, "%d\n", 20, ); -static FCOE_DEVICE_ATTR(ctlr, fcf_dev_loss_tmo, S_IRUGO | S_IWUSR, - show_fcoe_ctlr_device_fcf_dev_loss_tmo, - store_private_fcoe_ctlr_fcf_dev_loss_tmo); - -/* Link Error Status Block (LESB) */ -fcoe_ctlr_rd_attr(link_fail, "%u\n", 20); -fcoe_ctlr_rd_attr(vlink_fail, "%u\n", 20); -fcoe_ctlr_rd_attr(miss_fka, "%u\n", 20); -fcoe_ctlr_rd_attr(symb_err, "%u\n", 20); -fcoe_ctlr_rd_attr(err_block, "%u\n", 20); -fcoe_ctlr_rd_attr(fcs_error, "%u\n", 20); - -fcoe_fcf_private_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long); -fcoe_fcf_private_rd_attr_cast(switch_name, "0x%llx\n", 20, unsigned long long); -fcoe_fcf_private_rd_attr(priority, "%u\n", 20); -fcoe_fcf_private_rd_attr(fc_map, "0x%x\n", 20); -fcoe_fcf_private_rd_attr(vfid, "%u\n", 20); -fcoe_fcf_private_rd_attr(mac, "%pM\n", 20); -fcoe_fcf_private_rd_attr(fka_period, "%u\n", 20); -fcoe_fcf_rd_attr(selected, "%u\n", 20); -fcoe_fcf_rd_attr(vlan_id, "%u\n", 20); - -fcoe_fcf_private_show_function(dev_loss_tmo, "%d\n", 20, ) -static ssize_t -store_fcoe_fcf_dev_loss_tmo(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fcoe_fcf_device *fcf = dev_to_fcf(dev); - unsigned long val; - int rc; - - rc = fcoe_str_to_dev_loss(buf, &val); - if (rc) - return rc; - - rc = fcoe_fcf_set_dev_loss_tmo(fcf, val); - if (rc) - return rc; - return count; -} -static FCOE_DEVICE_ATTR(fcf, dev_loss_tmo, S_IRUGO | S_IWUSR, - show_fcoe_fcf_device_dev_loss_tmo, - store_fcoe_fcf_dev_loss_tmo); - -static struct attribute *fcoe_ctlr_lesb_attrs[] = { - &device_attr_fcoe_ctlr_link_fail.attr, - &device_attr_fcoe_ctlr_vlink_fail.attr, - &device_attr_fcoe_ctlr_miss_fka.attr, - &device_attr_fcoe_ctlr_symb_err.attr, - &device_attr_fcoe_ctlr_err_block.attr, - &device_attr_fcoe_ctlr_fcs_error.attr, - NULL, -}; - -static struct attribute_group fcoe_ctlr_lesb_attr_group = { - .name = "lesb", - .attrs = fcoe_ctlr_lesb_attrs, -}; - -static struct attribute *fcoe_ctlr_attrs[] = { - &device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr, - &device_attr_fcoe_ctlr_mode.attr, - NULL, -}; - -static struct attribute_group fcoe_ctlr_attr_group = { - .attrs = fcoe_ctlr_attrs, -}; - -static const struct attribute_group *fcoe_ctlr_attr_groups[] = { - &fcoe_ctlr_attr_group, - &fcoe_ctlr_lesb_attr_group, - NULL, -}; - -static struct attribute *fcoe_fcf_attrs[] = { - &device_attr_fcoe_fcf_fabric_name.attr, - &device_attr_fcoe_fcf_switch_name.attr, - &device_attr_fcoe_fcf_dev_loss_tmo.attr, - &device_attr_fcoe_fcf_fc_map.attr, - &device_attr_fcoe_fcf_vfid.attr, - &device_attr_fcoe_fcf_mac.attr, - &device_attr_fcoe_fcf_priority.attr, - &device_attr_fcoe_fcf_fka_period.attr, - &device_attr_fcoe_fcf_state.attr, - &device_attr_fcoe_fcf_selected.attr, - &device_attr_fcoe_fcf_vlan_id.attr, - NULL -}; - -static struct attribute_group fcoe_fcf_attr_group = { - .attrs = fcoe_fcf_attrs, -}; - -static const struct attribute_group *fcoe_fcf_attr_groups[] = { - &fcoe_fcf_attr_group, - NULL, -}; - -struct bus_type fcoe_bus_type; - -static int fcoe_bus_match(struct device *dev, - struct device_driver *drv) -{ - if (dev->bus == &fcoe_bus_type) - return 1; - return 0; -} - -/** - * fcoe_ctlr_device_release() - Release the FIP ctlr memory - * @dev: Pointer to the FIP ctlr's embedded device - * - * Called when the last FIP ctlr reference is released. - */ -static void fcoe_ctlr_device_release(struct device *dev) -{ - struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); - kfree(ctlr); -} - -/** - * fcoe_fcf_device_release() - Release the FIP fcf memory - * @dev: Pointer to the fcf's embedded device - * - * Called when the last FIP fcf reference is released. - */ -static void fcoe_fcf_device_release(struct device *dev) -{ - struct fcoe_fcf_device *fcf = dev_to_fcf(dev); - kfree(fcf); -} - -struct device_type fcoe_ctlr_device_type = { - .name = "fcoe_ctlr", - .groups = fcoe_ctlr_attr_groups, - .release = fcoe_ctlr_device_release, -}; - -struct device_type fcoe_fcf_device_type = { - .name = "fcoe_fcf", - .groups = fcoe_fcf_attr_groups, - .release = fcoe_fcf_device_release, -}; - -struct bus_type fcoe_bus_type = { - .name = "fcoe", - .match = &fcoe_bus_match, -}; - -/** - * fcoe_ctlr_device_flush_work() - Flush a FIP ctlr's workqueue - * @ctlr: Pointer to the FIP ctlr whose workqueue is to be flushed - */ -void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr) -{ - if (!fcoe_ctlr_work_q(ctlr)) { - printk(KERN_ERR - "ERROR: FIP Ctlr '%d' attempted to flush work, " - "when no workqueue created.\n", ctlr->id); - dump_stack(); - return; - } - - flush_workqueue(fcoe_ctlr_work_q(ctlr)); -} - -/** - * fcoe_ctlr_device_queue_work() - Schedule work for a FIP ctlr's workqueue - * @ctlr: Pointer to the FIP ctlr who owns the devloss workqueue - * @work: Work to queue for execution - * - * Return value: - * 1 on success / 0 already queued / < 0 for error - */ -int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr, - struct work_struct *work) -{ - if (unlikely(!fcoe_ctlr_work_q(ctlr))) { - printk(KERN_ERR - "ERROR: FIP Ctlr '%d' attempted to queue work, " - "when no workqueue created.\n", ctlr->id); - dump_stack(); - - return -EINVAL; - } - - return queue_work(fcoe_ctlr_work_q(ctlr), work); -} - -/** - * fcoe_ctlr_device_flush_devloss() - Flush a FIP ctlr's devloss workqueue - * @ctlr: Pointer to FIP ctlr whose workqueue is to be flushed - */ -void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr) -{ - if (!fcoe_ctlr_devloss_work_q(ctlr)) { - printk(KERN_ERR - "ERROR: FIP Ctlr '%d' attempted to flush work, " - "when no workqueue created.\n", ctlr->id); - dump_stack(); - return; - } - - flush_workqueue(fcoe_ctlr_devloss_work_q(ctlr)); -} - -/** - * fcoe_ctlr_device_queue_devloss_work() - Schedule work for a FIP ctlr's devloss workqueue - * @ctlr: Pointer to the FIP ctlr who owns the devloss workqueue - * @work: Work to queue for execution - * @delay: jiffies to delay the work queuing - * - * Return value: - * 1 on success / 0 already queued / < 0 for error - */ -int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr, - struct delayed_work *work, - unsigned long delay) -{ - if (unlikely(!fcoe_ctlr_devloss_work_q(ctlr))) { - printk(KERN_ERR - "ERROR: FIP Ctlr '%d' attempted to queue work, " - "when no workqueue created.\n", ctlr->id); - dump_stack(); - - return -EINVAL; - } - - return queue_delayed_work(fcoe_ctlr_devloss_work_q(ctlr), work, delay); -} - -static int fcoe_fcf_device_match(struct fcoe_fcf_device *new, - struct fcoe_fcf_device *old) -{ - if (new->switch_name == old->switch_name && - new->fabric_name == old->fabric_name && - new->fc_map == old->fc_map && - compare_ether_addr(new->mac, old->mac) == 0) - return 1; - return 0; -} - -/** - * fcoe_ctlr_device_add() - Add a FIP ctlr to sysfs - * @parent: The parent device to which the fcoe_ctlr instance - * should be attached - * @f: The LLD's FCoE sysfs function template pointer - * @priv_size: Size to be allocated with the fcoe_ctlr_device for the LLD - * - * This routine allocates a FIP ctlr object with some additional memory - * for the LLD. The FIP ctlr is initialized, added to sysfs and then - * attributes are added to it. - */ -struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent, - struct fcoe_sysfs_function_template *f, - int priv_size) -{ - struct fcoe_ctlr_device *ctlr; - int error = 0; - - ctlr = kzalloc(sizeof(struct fcoe_ctlr_device) + priv_size, - GFP_KERNEL); - if (!ctlr) - goto out; - - ctlr->id = atomic_inc_return(&ctlr_num) - 1; - ctlr->f = f; - INIT_LIST_HEAD(&ctlr->fcfs); - mutex_init(&ctlr->lock); - ctlr->dev.parent = parent; - ctlr->dev.bus = &fcoe_bus_type; - ctlr->dev.type = &fcoe_ctlr_device_type; - - ctlr->fcf_dev_loss_tmo = fcoe_fcf_dev_loss_tmo; - - snprintf(ctlr->work_q_name, sizeof(ctlr->work_q_name), - "ctlr_wq_%d", ctlr->id); - ctlr->work_q = create_singlethread_workqueue( - ctlr->work_q_name); - if (!ctlr->work_q) - goto out_del; - - snprintf(ctlr->devloss_work_q_name, - sizeof(ctlr->devloss_work_q_name), - "ctlr_dl_wq_%d", ctlr->id); - ctlr->devloss_work_q = create_singlethread_workqueue( - ctlr->devloss_work_q_name); - if (!ctlr->devloss_work_q) - goto out_del_q; - - dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id); - error = device_register(&ctlr->dev); - if (error) - goto out_del_q2; - - return ctlr; - -out_del_q2: - destroy_workqueue(ctlr->devloss_work_q); - ctlr->devloss_work_q = NULL; -out_del_q: - destroy_workqueue(ctlr->work_q); - ctlr->work_q = NULL; -out_del: - kfree(ctlr); -out: - return NULL; -} -EXPORT_SYMBOL_GPL(fcoe_ctlr_device_add); - -/** - * fcoe_ctlr_device_delete() - Delete a FIP ctlr and its subtree from sysfs - * @ctlr: A pointer to the ctlr to be deleted - * - * Deletes a FIP ctlr and any fcfs attached - * to it. Deleting fcfs will cause their childen - * to be deleted as well. - * - * The ctlr is detached from sysfs and it's resources - * are freed (work q), but the memory is not freed - * until its last reference is released. - * - * This routine expects no locks to be held before - * calling. - * - * TODO: Currently there are no callbacks to clean up LLD data - * for a fcoe_fcf_device. LLDs must keep this in mind as they need - * to clean up each of their LLD data for all fcoe_fcf_device before - * calling fcoe_ctlr_device_delete. - */ -void fcoe_ctlr_device_delete(struct fcoe_ctlr_device *ctlr) -{ - struct fcoe_fcf_device *fcf, *next; - /* Remove any attached fcfs */ - mutex_lock(&ctlr->lock); - list_for_each_entry_safe(fcf, next, - &ctlr->fcfs, peers) { - list_del(&fcf->peers); - fcf->state = FCOE_FCF_STATE_DELETED; - fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work); - } - mutex_unlock(&ctlr->lock); - - fcoe_ctlr_device_flush_work(ctlr); - - destroy_workqueue(ctlr->devloss_work_q); - ctlr->devloss_work_q = NULL; - destroy_workqueue(ctlr->work_q); - ctlr->work_q = NULL; - - device_unregister(&ctlr->dev); -} -EXPORT_SYMBOL_GPL(fcoe_ctlr_device_delete); - -/** - * fcoe_fcf_device_final_delete() - Final delete routine - * @work: The FIP fcf's embedded work struct - * - * It is expected that the fcf has been removed from - * the FIP ctlr's list before calling this routine. - */ -static void fcoe_fcf_device_final_delete(struct work_struct *work) -{ - struct fcoe_fcf_device *fcf = - container_of(work, struct fcoe_fcf_device, delete_work); - struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); - - /* - * Cancel any outstanding timers. These should really exist - * only when rmmod'ing the LLDD and we're asking for - * immediate termination of the rports - */ - if (!cancel_delayed_work(&fcf->dev_loss_work)) - fcoe_ctlr_device_flush_devloss(ctlr); - - device_unregister(&fcf->dev); -} - -/** - * fip_timeout_deleted_fcf() - Delete a fcf when the devloss timer fires - * @work: The FIP fcf's embedded work struct - * - * Removes the fcf from the FIP ctlr's list of fcfs and - * queues the final deletion. - */ -static void fip_timeout_deleted_fcf(struct work_struct *work) -{ - struct fcoe_fcf_device *fcf = - container_of(work, struct fcoe_fcf_device, dev_loss_work.work); - struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); - - mutex_lock(&ctlr->lock); - - /* - * If the fcf is deleted or reconnected before the timer - * fires the devloss queue will be flushed, but the state will - * either be CONNECTED or DELETED. If that is the case we - * cancel deleting the fcf. - */ - if (fcf->state != FCOE_FCF_STATE_DISCONNECTED) - goto out; - - dev_printk(KERN_ERR, &fcf->dev, - "FIP fcf connection time out: removing fcf\n"); - - list_del(&fcf->peers); - fcf->state = FCOE_FCF_STATE_DELETED; - fcoe_ctlr_device_queue_work(ctlr, &fcf->delete_work); - -out: - mutex_unlock(&ctlr->lock); -} - -/** - * fcoe_fcf_device_delete() - Delete a FIP fcf - * @fcf: Pointer to the fcf which is to be deleted - * - * Queues the FIP fcf on the devloss workqueue - * - * Expects the ctlr_attrs mutex to be held for fcf - * state change. - */ -void fcoe_fcf_device_delete(struct fcoe_fcf_device *fcf) -{ - struct fcoe_ctlr_device *ctlr = fcoe_fcf_dev_to_ctlr_dev(fcf); - int timeout = fcf->dev_loss_tmo; - - if (fcf->state != FCOE_FCF_STATE_CONNECTED) - return; - - fcf->state = FCOE_FCF_STATE_DISCONNECTED; - - /* - * FCF will only be re-connected by the LLD calling - * fcoe_fcf_device_add, and it should be setting up - * priv then. - */ - fcf->priv = NULL; - - fcoe_ctlr_device_queue_devloss_work(ctlr, &fcf->dev_loss_work, - timeout * HZ); -} -EXPORT_SYMBOL_GPL(fcoe_fcf_device_delete); - -/** - * fcoe_fcf_device_add() - Add a FCoE sysfs fcoe_fcf_device to the system - * @ctlr: The fcoe_ctlr_device that will be the fcoe_fcf_device parent - * @new_fcf: A temporary FCF used for lookups on the current list of fcfs - * - * Expects to be called with the ctlr->lock held - */ -struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr, - struct fcoe_fcf_device *new_fcf) -{ - struct fcoe_fcf_device *fcf; - int error = 0; - - list_for_each_entry(fcf, &ctlr->fcfs, peers) { - if (fcoe_fcf_device_match(new_fcf, fcf)) { - if (fcf->state == FCOE_FCF_STATE_CONNECTED) - return fcf; - - fcf->state = FCOE_FCF_STATE_CONNECTED; - - if (!cancel_delayed_work(&fcf->dev_loss_work)) - fcoe_ctlr_device_flush_devloss(ctlr); - - return fcf; - } - } - - fcf = kzalloc(sizeof(struct fcoe_fcf_device), GFP_ATOMIC); - if (unlikely(!fcf)) - goto out; - - INIT_WORK(&fcf->delete_work, fcoe_fcf_device_final_delete); - INIT_DELAYED_WORK(&fcf->dev_loss_work, fip_timeout_deleted_fcf); - - fcf->dev.parent = &ctlr->dev; - fcf->dev.bus = &fcoe_bus_type; - fcf->dev.type = &fcoe_fcf_device_type; - fcf->id = atomic_inc_return(&fcf_num) - 1; - fcf->state = FCOE_FCF_STATE_UNKNOWN; - - fcf->dev_loss_tmo = ctlr->fcf_dev_loss_tmo; - - dev_set_name(&fcf->dev, "fcf_%d", fcf->id); - - fcf->fabric_name = new_fcf->fabric_name; - fcf->switch_name = new_fcf->switch_name; - fcf->fc_map = new_fcf->fc_map; - fcf->vfid = new_fcf->vfid; - memcpy(fcf->mac, new_fcf->mac, ETH_ALEN); - fcf->priority = new_fcf->priority; - fcf->fka_period = new_fcf->fka_period; - fcf->selected = new_fcf->selected; - - error = device_register(&fcf->dev); - if (error) - goto out_del; - - fcf->state = FCOE_FCF_STATE_CONNECTED; - list_add_tail(&fcf->peers, &ctlr->fcfs); - - return fcf; - -out_del: - kfree(fcf); -out: - return NULL; -} -EXPORT_SYMBOL_GPL(fcoe_fcf_device_add); - -int __init fcoe_sysfs_setup(void) -{ - int error; - - atomic_set(&ctlr_num, 0); - atomic_set(&fcf_num, 0); - - error = bus_register(&fcoe_bus_type); - if (error) - return error; - - return 0; -} - -void __exit fcoe_sysfs_teardown(void) -{ - bus_unregister(&fcoe_bus_type); -} diff --git a/trunk/drivers/scsi/fcoe/fcoe_transport.c b/trunk/drivers/scsi/fcoe/fcoe_transport.c index b46f43dced78..710e149d41b6 100644 --- a/trunk/drivers/scsi/fcoe/fcoe_transport.c +++ b/trunk/drivers/scsi/fcoe/fcoe_transport.c @@ -815,17 +815,9 @@ static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) */ static int __init libfcoe_init(void) { - int rc = 0; - - rc = fcoe_transport_init(); - if (rc) - return rc; + fcoe_transport_init(); - rc = fcoe_sysfs_setup(); - if (rc) - fcoe_transport_exit(); - - return rc; + return 0; } module_init(libfcoe_init); @@ -834,7 +826,6 @@ module_init(libfcoe_init); */ static void __exit libfcoe_exit(void) { - fcoe_sysfs_teardown(); fcoe_transport_exit(); } module_exit(libfcoe_exit); diff --git a/trunk/drivers/scsi/qla2xxx/Kconfig b/trunk/drivers/scsi/qla2xxx/Kconfig index 317a7fdc3b82..6208d562890d 100644 --- a/trunk/drivers/scsi/qla2xxx/Kconfig +++ b/trunk/drivers/scsi/qla2xxx/Kconfig @@ -25,12 +25,3 @@ config SCSI_QLA_FC Firmware images can be retrieved from: ftp://ftp.qlogic.com/outgoing/linux/firmware/ - -config TCM_QLA2XXX - tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs" - depends on SCSI_QLA_FC && TARGET_CORE - select LIBFC - select BTREE - default n - ---help--- - Say Y here to enable the TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs diff --git a/trunk/drivers/scsi/qla2xxx/Makefile b/trunk/drivers/scsi/qla2xxx/Makefile index dce7d788cdc9..5df782f4a097 100644 --- a/trunk/drivers/scsi/qla2xxx/Makefile +++ b/trunk/drivers/scsi/qla2xxx/Makefile @@ -1,6 +1,5 @@ qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \ - qla_nx.o qla_target.o + qla_nx.o obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o -obj-$(CONFIG_TCM_QLA2XXX) += tcm_qla2xxx.o diff --git a/trunk/drivers/scsi/qla2xxx/qla_attr.c b/trunk/drivers/scsi/qla2xxx/qla_attr.c index 5ab953029f8d..5926f5a87ea8 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_attr.c +++ b/trunk/drivers/scsi/qla2xxx/qla_attr.c @@ -5,7 +5,6 @@ * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" -#include "qla_target.h" #include #include @@ -577,7 +576,6 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, scsi_block_requests(vha->host); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); if (IS_QLA82XX(ha)) { - ha->flags.isp82xx_no_md_cap = 1; qla82xx_idc_lock(ha); qla82xx_set_reset_owner(vha); qla82xx_idc_unlock(ha); @@ -587,7 +585,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, scsi_unblock_requests(vha->host); break; case 0x2025d: - if (!IS_QLA81XX(ha) || !IS_QLA8031(ha)) + if (!IS_QLA81XX(ha)) return -EPERM; ql_log(ql_log_info, vha, 0x706f, @@ -1107,8 +1105,9 @@ qla2x00_total_isp_aborts_show(struct device *dev, struct device_attribute *attr, char *buf) { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); + struct qla_hw_data *ha = vha->hw; return snprintf(buf, PAGE_SIZE, "%d\n", - vha->qla_stats.total_isp_aborts); + ha->qla_stats.total_isp_aborts); } static ssize_t @@ -1155,7 +1154,7 @@ qla2x00_phy_version_show(struct device *dev, struct device_attribute *attr, scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); struct qla_hw_data *ha = vha->hw; - if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) return snprintf(buf, PAGE_SIZE, "\n"); return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n", @@ -1538,7 +1537,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) dma_addr_t stats_dma; struct fc_host_statistics *pfc_host_stat; - pfc_host_stat = &vha->fc_host_stat; + pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); if (test_bit(UNLOADING, &vha->dpc_flags)) @@ -1581,8 +1580,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat->dumped_frames = stats->dumped_frames; pfc_host_stat->nos_count = stats->nos_rcvd; } - pfc_host_stat->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20; - pfc_host_stat->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20; + pfc_host_stat->fcp_input_megabytes = ha->qla_stats.input_bytes >> 20; + pfc_host_stat->fcp_output_megabytes = ha->qla_stats.output_bytes >> 20; done_free: dma_pool_free(ha->s_dma_pool, stats, stats_dma); @@ -1738,7 +1737,6 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) fc_host_supported_speeds(vha->host) = fc_host_supported_speeds(base_vha->host); - qlt_vport_create(vha, ha); qla24xx_vport_disable(fc_vport, disable); if (ha->flags.cpu_affinity_enabled) { @@ -1953,16 +1951,12 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha) fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count; fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name); fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); - fc_host_supported_classes(vha->host) = ha->tgt.enable_class_2 ? - (FC_COS_CLASS2|FC_COS_CLASS3) : FC_COS_CLASS3; + fc_host_supported_classes(vha->host) = FC_COS_CLASS3; fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports; fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count; if (IS_CNA_CAPABLE(ha)) speed = FC_PORTSPEED_10GBIT; - else if (IS_QLA2031(ha)) - speed = FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT | - FC_PORTSPEED_4GBIT; else if (IS_QLA25XX(ha)) speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT; diff --git a/trunk/drivers/scsi/qla2xxx/qla_bsg.c b/trunk/drivers/scsi/qla2xxx/qla_bsg.c index c68883806c54..bc3cc6d91117 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_bsg.c +++ b/trunk/drivers/scsi/qla2xxx/qla_bsg.c @@ -297,6 +297,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) /* Initialize all required fields of fcport */ fcport->vha = vha; + fcport->vp_idx = vha->vp_idx; fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_els.port_id[0]; fcport->d_id.b.area = @@ -482,6 +483,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) /* Initialize all required fields of fcport */ fcport->vha = vha; + fcport->vp_idx = vha->vp_idx; fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0]; fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1]; fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2]; @@ -542,7 +544,7 @@ qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config, int rval = 0; struct qla_hw_data *ha = vha->hw; - if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) goto done_set_internal; new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1); @@ -584,7 +586,7 @@ qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config, uint16_t new_config[4]; struct qla_hw_data *ha = vha->hw; - if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) + if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) goto done_reset_internal; memset(new_config, 0 , sizeof(new_config)); @@ -708,7 +710,8 @@ qla2x00_process_loopback(struct fc_bsg_job *bsg_job) elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1]; if ((ha->current_topology == ISP_CFG_F || - ((IS_QLA81XX(ha) || IS_QLA8031(ha)) && + (atomic_read(&vha->loop_state) == LOOP_DOWN) || + ((IS_QLA81XX(ha) || IS_QLA83XX(ha)) && le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE && req_data_len == MAX_ELS_FRAME_PAYLOAD)) && elreq.options == EXTERNAL_LOOPBACK) { @@ -1399,9 +1402,6 @@ qla2x00_update_optrom(struct fc_bsg_job *bsg_job) if (rval) return rval; - /* Set the isp82xx_no_md_cap not to capture minidump */ - ha->flags.isp82xx_no_md_cap = 1; - sg_copy_to_buffer(bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, ha->optrom_buffer, ha->optrom_region_size); diff --git a/trunk/drivers/scsi/qla2xxx/qla_dbg.c b/trunk/drivers/scsi/qla2xxx/qla_dbg.c index fdee5611f3e2..62324a1d5573 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_dbg.c +++ b/trunk/drivers/scsi/qla2xxx/qla_dbg.c @@ -11,31 +11,27 @@ * ---------------------------------------------------------------------- * | Level | Last Value Used | Holes | * ---------------------------------------------------------------------- - * | Module Init and Probe | 0x0122 | 0x4b,0xba,0xfa | - * | Mailbox commands | 0x1140 | 0x111a-0x111b | - * | | | 0x112c-0x112e | + * | Module Init and Probe | 0x0120 | 0x4b,0xba,0xfa | + * | Mailbox commands | 0x113e | 0x112c-0x112e | * | | | 0x113a | * | Device Discovery | 0x2086 | 0x2020-0x2022 | * | Queue Command and IO tracing | 0x3030 | 0x3006,0x3008 | * | | | 0x302d-0x302e | - * | DPC Thread | 0x401c | 0x4002,0x4013 | - * | Async Events | 0x505f | 0x502b-0x502f | + * | DPC Thread | 0x401c | | + * | Async Events | 0x505d | 0x502b-0x502f | * | | | 0x5047,0x5052 | - * | Timer Routines | 0x6011 | | + * | Timer Routines | 0x6011 | 0x600e-0x600f | * | User Space Interactions | 0x709f | 0x7018,0x702e, | * | | | 0x7039,0x7045, | * | | | 0x7073-0x7075, | * | | | 0x708c | * | Task Management | 0x803c | 0x8025-0x8026 | * | | | 0x800b,0x8039 | - * | AER/EEH | 0x9011 | | + * | AER/EEH | 0x900f | | * | Virtual Port | 0xa007 | | - * | ISP82XX Specific | 0xb054 | 0xb024 | + * | ISP82XX Specific | 0xb054 | 0xb053 | * | MultiQ | 0xc00c | | * | Misc | 0xd010 | | - * | Target Mode | 0xe06f | | - * | Target Mode Management | 0xf071 | | - * | Target Mode Task Management | 0x1000b | | * ---------------------------------------------------------------------- */ @@ -382,54 +378,6 @@ qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) return (char *)iter_reg + ntohl(fcec->size); } -static inline void * -qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr, - uint32_t **last_chain) -{ - struct qla2xxx_mqueue_chain *q; - struct qla2xxx_mqueue_header *qh; - uint32_t num_queues; - int que; - struct { - int length; - void *ring; - } aq, *aqp; - - if (!ha->tgt.atio_q_length) - return ptr; - - num_queues = 1; - aqp = &aq; - aqp->length = ha->tgt.atio_q_length; - aqp->ring = ha->tgt.atio_ring; - - for (que = 0; que < num_queues; que++) { - /* aqp = ha->atio_q_map[que]; */ - q = ptr; - *last_chain = &q->type; - q->type = __constant_htonl(DUMP_CHAIN_QUEUE); - q->chain_size = htonl( - sizeof(struct qla2xxx_mqueue_chain) + - sizeof(struct qla2xxx_mqueue_header) + - (aqp->length * sizeof(request_t))); - ptr += sizeof(struct qla2xxx_mqueue_chain); - - /* Add header. */ - qh = ptr; - qh->queue = __constant_htonl(TYPE_ATIO_QUEUE); - qh->number = htonl(que); - qh->size = htonl(aqp->length * sizeof(request_t)); - ptr += sizeof(struct qla2xxx_mqueue_header); - - /* Add data. */ - memcpy(ptr, aqp->ring, aqp->length * sizeof(request_t)); - - ptr += aqp->length * sizeof(request_t); - } - - return ptr; -} - static inline void * qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain) { @@ -925,8 +873,6 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) struct qla24xx_fw_dump *fw; uint32_t ext_mem_cnt; void *nxt; - void *nxt_chain; - uint32_t *last_chain = NULL; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); if (IS_QLA82XX(ha)) @@ -1145,16 +1091,6 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) qla24xx_copy_eft(ha, nxt); - nxt_chain = (void *)ha->fw_dump + ha->chain_offset; - nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); - if (last_chain) { - ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); - *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); - } - - /* Adjust valid length. */ - ha->fw_dump_len = (nxt_chain - (void *)ha->fw_dump); - qla24xx_fw_dump_failed_0: qla2xxx_dump_post_process(base_vha, rval); @@ -1463,7 +1399,6 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Chain entries -- started with MQ. */ nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); - nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); if (last_chain) { ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); @@ -1782,7 +1717,6 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Chain entries -- started with MQ. */ nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); - nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); if (last_chain) { ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); @@ -2284,7 +2218,6 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) /* Chain entries -- started with MQ. */ nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); nxt_chain = qla25xx_copy_mqueues(ha, nxt_chain, &last_chain); - nxt_chain = qla2xxx_copy_atioqueues(ha, nxt_chain, &last_chain); if (last_chain) { ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT); *last_chain |= __constant_htonl(DUMP_CHAIN_LAST); diff --git a/trunk/drivers/scsi/qla2xxx/qla_dbg.h b/trunk/drivers/scsi/qla2xxx/qla_dbg.h index f278df8cce0f..2157bdf1569a 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_dbg.h +++ b/trunk/drivers/scsi/qla2xxx/qla_dbg.h @@ -244,7 +244,6 @@ struct qla2xxx_mqueue_header { uint32_t queue; #define TYPE_REQUEST_QUEUE 0x1 #define TYPE_RESPONSE_QUEUE 0x2 -#define TYPE_ATIO_QUEUE 0x3 uint32_t number; uint32_t size; }; @@ -340,11 +339,3 @@ ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...); #define ql_dbg_misc 0x00010000 /* For dumping everything that is not * not covered by upper categories */ -#define ql_dbg_verbose 0x00008000 /* More verbosity for each level - * This is to be used with other levels where - * more verbosity is required. It might not - * be applicable to all the levels. - */ -#define ql_dbg_tgt 0x00004000 /* Target mode */ -#define ql_dbg_tgt_mgt 0x00002000 /* Target mode management */ -#define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */ diff --git a/trunk/drivers/scsi/qla2xxx/qla_def.h b/trunk/drivers/scsi/qla2xxx/qla_def.h index 39007f53aec0..a2443031dbe7 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_def.h +++ b/trunk/drivers/scsi/qla2xxx/qla_def.h @@ -186,7 +186,6 @@ #define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/ #define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/ #define RESPONSE_ENTRY_CNT_MQ 128 /* Number of response entries.*/ -#define ATIO_ENTRY_CNT_24XX 4096 /* Number of ATIO entries. */ struct req_que; @@ -1235,27 +1234,11 @@ typedef struct { * ISP queue - response queue entry definition. */ typedef struct { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System defined handle */ - uint8_t data[52]; + uint8_t data[60]; uint32_t signature; #define RESPONSE_PROCESSED 0xDEADDEAD /* Signature */ } response_t; -/* - * ISP queue - ATIO queue entry definition. - */ -struct atio { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t data[58]; - uint32_t signature; -#define ATIO_PROCESSED 0xDEADDEAD /* Signature */ -}; - typedef union { uint16_t extended; struct { @@ -1736,13 +1719,11 @@ typedef struct fc_port { struct fc_rport *rport, *drport; u32 supported_classes; + uint16_t vp_idx; uint8_t fc4_type; uint8_t scan_state; } fc_port_t; -#define QLA_FCPORT_SCAN_NONE 0 -#define QLA_FCPORT_SCAN_FOUND 1 - /* * Fibre channel port/lun states. */ @@ -1766,7 +1747,6 @@ static const char * const port_state_str[] = { #define FCF_LOGIN_NEEDED BIT_1 #define FCF_FCP2_DEVICE BIT_2 #define FCF_ASYNC_SENT BIT_3 -#define FCF_CONF_COMP_SUPPORTED BIT_4 /* No loop ID flag. */ #define FC_NO_LOOP_ID 0x1000 @@ -2439,40 +2419,6 @@ struct qlfc_fw { uint32_t len; }; -struct qlt_hw_data { - /* Protected by hw lock */ - uint32_t enable_class_2:1; - uint32_t enable_explicit_conf:1; - uint32_t ini_mode_force_reverse:1; - uint32_t node_name_set:1; - - dma_addr_t atio_dma; /* Physical address. */ - struct atio *atio_ring; /* Base virtual address */ - struct atio *atio_ring_ptr; /* Current address. */ - uint16_t atio_ring_index; /* Current index. */ - uint16_t atio_q_length; - - void *target_lport_ptr; - struct qla_tgt_func_tmpl *tgt_ops; - struct qla_tgt *qla_tgt; - struct qla_tgt_cmd *cmds[MAX_OUTSTANDING_COMMANDS]; - uint16_t current_handle; - - struct qla_tgt_vp_map *tgt_vp_map; - struct mutex tgt_mutex; - struct mutex tgt_host_action_mutex; - - int saved_set; - uint16_t saved_exchange_count; - uint32_t saved_firmware_options_1; - uint32_t saved_firmware_options_2; - uint32_t saved_firmware_options_3; - uint8_t saved_firmware_options[2]; - uint8_t saved_add_firmware_options[2]; - - uint8_t tgt_node_name[WWN_SIZE]; -}; - /* * Qlogic host adapter specific data structure. */ @@ -2514,9 +2460,7 @@ struct qla_hw_data { uint32_t thermal_supported:1; uint32_t isp82xx_reset_hdlr_active:1; uint32_t isp82xx_reset_owner:1; - uint32_t isp82xx_no_md_cap:1; - uint32_t host_shutting_down:1; - /* 30 bits */ + /* 28 bits */ } flags; /* This spinlock is used to protect "io transactions", you must @@ -2860,6 +2804,7 @@ struct qla_hw_data { /* ISP2322: red, green, amber. */ uint16_t zio_mode; uint16_t zio_timer; + struct fc_host_statistics fc_host_stat; struct qla_msix_entry *msix_entries; @@ -2872,6 +2817,7 @@ struct qla_hw_data { int cur_vport_count; struct qla_chip_state_84xx *cs84xx; + struct qla_statistics qla_stats; struct isp_operations *isp_ops; struct workqueue_struct *wq; struct qlfc_fw fw_buf; @@ -2917,8 +2863,6 @@ struct qla_hw_data { dma_addr_t md_tmplt_hdr_dma; void *md_dump; uint32_t md_dump_size; - - struct qlt_hw_data tgt; }; /* @@ -2976,7 +2920,6 @@ typedef struct scsi_qla_host { #define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ #define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */ -#define SCR_PENDING 21 /* SCR in target mode */ uint32_t device_flags; #define SWITCH_FOUND BIT_0 @@ -3036,21 +2979,10 @@ typedef struct scsi_qla_host { struct req_que *req; int fw_heartbeat_counter; int seconds_since_last_heartbeat; - struct fc_host_statistics fc_host_stat; - struct qla_statistics qla_stats; atomic_t vref_count; } scsi_qla_host_t; -#define SET_VP_IDX 1 -#define SET_AL_PA 2 -#define RESET_VP_IDX 3 -#define RESET_AL_PA 4 -struct qla_tgt_vp_map { - uint8_t idx; - scsi_qla_host_t *vha; -}; - /* * Macros to help code, maintain, etc. */ diff --git a/trunk/drivers/scsi/qla2xxx/qla_gbl.h b/trunk/drivers/scsi/qla2xxx/qla_gbl.h index 9eacd2df111b..9f065804bd12 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_gbl.h +++ b/trunk/drivers/scsi/qla2xxx/qla_gbl.h @@ -175,7 +175,6 @@ extern int qla2x00_vp_abort_isp(scsi_qla_host_t *); /* * Global Function Prototypes in qla_iocb.c source file. */ - extern uint16_t qla2x00_calc_iocbs_32(uint16_t); extern uint16_t qla2x00_calc_iocbs_64(uint16_t); extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t); @@ -189,8 +188,6 @@ extern uint16_t qla24xx_calc_iocbs(scsi_qla_host_t *, uint16_t); extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t); extern int qla24xx_dif_start_scsi(srb_t *); -extern void *qla2x00_alloc_iocbs(scsi_qla_host_t *, srb_t *); -extern int qla2x00_issue_marker(scsi_qla_host_t *, int); /* * Global Function Prototypes in qla_mbx.c source file. @@ -241,9 +238,6 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *, uint8_t *, uint8_t *, uint16_t *); extern int qla2x00_init_firmware(scsi_qla_host_t *, uint16_t); -extern int -qla2x00_get_node_name_list(scsi_qla_host_t *, void **, int *); - extern int qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t); @@ -389,8 +383,6 @@ extern int qla2x00_request_irqs(struct qla_hw_data *, struct rsp_que *); extern void qla2x00_free_irqs(scsi_qla_host_t *); extern int qla2x00_get_data_rate(scsi_qla_host_t *); -extern char *qla2x00_get_link_speed_str(struct qla_hw_data *); - /* * Global Function Prototypes in qla_sup.c source file. */ @@ -554,7 +546,6 @@ extern void qla2x00_sp_free(void *, void *); extern void qla2x00_sp_timeout(unsigned long); extern void qla2x00_bsg_job_done(void *, void *, int); extern void qla2x00_bsg_sp_free(void *, void *); -extern void qla2x00_start_iocbs(struct scsi_qla_host *, struct req_que *); /* Interrupt related */ extern irqreturn_t qla82xx_intr_handler(int, void *); diff --git a/trunk/drivers/scsi/qla2xxx/qla_gs.c b/trunk/drivers/scsi/qla2xxx/qla_gs.c index 05260d25fe46..3128f80441f5 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_gs.c +++ b/trunk/drivers/scsi/qla2xxx/qla_gs.c @@ -5,7 +5,6 @@ * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" -#include "qla_target.h" static int qla2x00_sns_ga_nxt(scsi_qla_host_t *, fc_port_t *); static int qla2x00_sns_gid_pt(scsi_qla_host_t *, sw_info_t *); @@ -557,8 +556,7 @@ qla2x00_rff_id(scsi_qla_host_t *vha) ct_req->req.rff_id.port_id[1] = vha->d_id.b.area; ct_req->req.rff_id.port_id[2] = vha->d_id.b.al_pa; - qlt_rff_id(vha, ct_req); - + ct_req->req.rff_id.fc4_feature = BIT_1; ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */ /* Execute MS IOCB */ diff --git a/trunk/drivers/scsi/qla2xxx/qla_init.c b/trunk/drivers/scsi/qla2xxx/qla_init.c index ca5084743135..b9465643396b 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_init.c +++ b/trunk/drivers/scsi/qla2xxx/qla_init.c @@ -17,9 +17,6 @@ #include #endif -#include -#include "qla_target.h" - /* * QLogic ISP2x00 Hardware Support Function Prototypes. */ @@ -521,10 +518,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) return QLA_FUNCTION_FAILED; } } - - if (qla_ini_mode_enabled(vha)) - rval = qla2x00_init_rings(vha); - + rval = qla2x00_init_rings(vha); ha->flags.chip_reset_done = 1; if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) { @@ -1239,8 +1233,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) mq_size += ha->max_rsp_queues * (rsp->length * sizeof(response_t)); } - if (ha->tgt.atio_q_length) - mq_size += ha->tgt.atio_q_length * sizeof(request_t); /* Allocate memory for Fibre Channel Event Buffer. */ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha)) goto try_eft; @@ -1704,12 +1696,6 @@ qla24xx_config_rings(struct scsi_qla_host *vha) icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma)); icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma)); - /* Setup ATIO queue dma pointers for target mode */ - icb->atio_q_inpointer = __constant_cpu_to_le16(0); - icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length); - icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma)); - icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma)); - if (ha->mqenable || IS_QLA83XX(ha)) { icb->qos = __constant_cpu_to_le16(QLA_DEFAULT_QUE_QOS); icb->rid = __constant_cpu_to_le16(rid); @@ -1753,8 +1739,6 @@ qla24xx_config_rings(struct scsi_qla_host *vha) WRT_REG_DWORD(®->isp24.rsp_q_in, 0); WRT_REG_DWORD(®->isp24.rsp_q_out, 0); } - qlt_24xx_config_rings(vha, reg); - /* PCI posting */ RD_REG_DWORD(&ioreg->hccr); } @@ -1810,11 +1794,6 @@ qla2x00_init_rings(scsi_qla_host_t *vha) spin_unlock(&ha->vport_slock); - ha->tgt.atio_ring_ptr = ha->tgt.atio_ring; - ha->tgt.atio_ring_index = 0; - /* Initialize ATIO queue entries */ - qlt_init_atio_q_entries(vha); - ha->isp_ops->config_rings(vha); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -2072,10 +2051,6 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) vha->d_id.b.area = area; vha->d_id.b.al_pa = al_pa; - spin_lock(&ha->vport_slock); - qlt_update_vp_map(vha, SET_AL_PA); - spin_unlock(&ha->vport_slock); - if (!vha->flags.init_done) ql_log(ql_log_info, vha, 0x2010, "Topology - %s, Host Loop address 0x%x.\n", @@ -2210,7 +2185,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x0064, - "Inconsistent NVRAM " + "Inconisistent NVRAM " "detected: checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); ql_log(ql_log_warn, vha, 0x0065, @@ -2295,7 +2270,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) if (IS_QLA23XX(ha)) { nv->firmware_options[0] |= BIT_2; nv->firmware_options[0] &= ~BIT_3; - nv->special_options[0] &= ~BIT_6; + nv->firmware_options[0] &= ~BIT_6; nv->add_firmware_options[1] |= BIT_5 | BIT_4; if (IS_QLA2300(ha)) { @@ -2492,21 +2467,14 @@ qla2x00_rport_del(void *data) { fc_port_t *fcport = data; struct fc_rport *rport; - scsi_qla_host_t *vha = fcport->vha; unsigned long flags; spin_lock_irqsave(fcport->vha->host->host_lock, flags); rport = fcport->drport ? fcport->drport: fcport->rport; fcport->drport = NULL; spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); - if (rport) { + if (rport) fc_remote_port_delete(rport); - /* - * Release the target mode FC NEXUS in qla_target.c code - * if target mod is enabled. - */ - qlt_fc_port_deleted(vha, fcport); - } } /** @@ -2527,11 +2495,11 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) /* Setup fcport template structure. */ fcport->vha = vha; + fcport->vp_idx = vha->vp_idx; fcport->port_type = FCT_UNKNOWN; fcport->loop_id = FC_NO_LOOP_ID; qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED); fcport->supported_classes = FC_COS_UNSPECIFIED; - fcport->scan_state = QLA_FCPORT_SCAN_NONE; return fcport; } @@ -2758,6 +2726,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) new_fcport->d_id.b.area = area; new_fcport->d_id.b.al_pa = al_pa; new_fcport->loop_id = loop_id; + new_fcport->vp_idx = vha->vp_idx; rval2 = qla2x00_get_port_database(vha, new_fcport, 0); if (rval2 != QLA_SUCCESS) { ql_dbg(ql_dbg_disc, vha, 0x201a, @@ -2791,6 +2760,10 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) if (!found) { /* New device, add to fcports list. */ + if (vha->vp_idx) { + new_fcport->vha = vha; + new_fcport->vp_idx = vha->vp_idx; + } list_add_tail(&new_fcport->list, &vha->vp_fcports); /* Allocate a new replacement fcport. */ @@ -2827,6 +2800,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha) static void qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) { +#define LS_UNKNOWN 2 + static char *link_speeds[] = { "1", "2", "?", "4", "8", "10" }; char *link_speed; int rval; uint16_t mb[4]; @@ -2854,7 +2829,11 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) fcport->port_name[6], fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1]); } else { - link_speed = qla2x00_get_link_speed_str(ha); + link_speed = link_speeds[LS_UNKNOWN]; + if (fcport->fp_speed < 5) + link_speed = link_speeds[fcport->fp_speed]; + else if (fcport->fp_speed == 0x13) + link_speed = link_speeds[5]; ql_dbg(ql_dbg_disc, vha, 0x2005, "iIDMA adjusted to %s GB/s " "on %02x%02x%02x%02x%02x%02x%02x%02x.\n", link_speed, @@ -2885,12 +2864,6 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) "Unable to allocate fc remote port.\n"); return; } - /* - * Create target mode FC NEXUS in qla_target.c if target mode is - * enabled.. - */ - qlt_fc_port_added(vha, fcport); - spin_lock_irqsave(fcport->vha->host->host_lock, flags); *((fc_port_t **)rport->dd_data) = fcport; spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); @@ -2948,7 +2921,7 @@ static int qla2x00_configure_fabric(scsi_qla_host_t *vha) { int rval; - fc_port_t *fcport; + fc_port_t *fcport, *fcptemp; uint16_t next_loopid; uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t loop_id; @@ -2986,7 +2959,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) 0xfc, mb, BIT_1|BIT_0); if (rval != QLA_SUCCESS) { set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); - break; + return rval; } if (mb[0] != MBS_COMMAND_COMPLETE) { ql_dbg(ql_dbg_disc, vha, 0x2042, @@ -3018,16 +2991,21 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) } } +#define QLA_FCPORT_SCAN 1 +#define QLA_FCPORT_FOUND 2 + + list_for_each_entry(fcport, &vha->vp_fcports, list) { + fcport->scan_state = QLA_FCPORT_SCAN; + } + rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); if (rval != QLA_SUCCESS) break; - /* Add new ports to existing port list */ - list_splice_tail_init(&new_fcports, &vha->vp_fcports); - - /* Starting free loop ID. */ - next_loopid = ha->min_external_loopid; - + /* + * Logout all previous fabric devices marked lost, except + * FCP2 devices. + */ list_for_each_entry(fcport, &vha->vp_fcports, list) { if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) break; @@ -3035,8 +3013,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) continue; - /* Logout lost/gone fabric devices (non-FCP2) */ - if (fcport->scan_state != QLA_FCPORT_SCAN_FOUND && + if (fcport->scan_state == QLA_FCPORT_SCAN && atomic_read(&fcport->state) == FCS_ONLINE) { qla2x00_mark_device_lost(vha, fcport, ql2xplogiabsentdevice, 0); @@ -3049,30 +3026,78 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); + fcport->loop_id = FC_NO_LOOP_ID; } - continue; } - fcport->scan_state = QLA_FCPORT_SCAN_NONE; - - /* Login fabric devices that need a login */ - if ((fcport->flags & FCF_LOGIN_NEEDED) != 0 && - atomic_read(&vha->loop_down_timer) == 0) { - if (fcport->loop_id == FC_NO_LOOP_ID) { - fcport->loop_id = next_loopid; - rval = qla2x00_find_new_loop_id( - base_vha, fcport); - if (rval != QLA_SUCCESS) { - /* Ran out of IDs to use */ - continue; - } + } + + /* Starting free loop ID. */ + next_loopid = ha->min_external_loopid; + + /* + * Scan through our port list and login entries that need to be + * logged in. + */ + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (atomic_read(&vha->loop_down_timer) || + test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) + break; + + if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || + (fcport->flags & FCF_LOGIN_NEEDED) == 0) + continue; + + if (fcport->loop_id == FC_NO_LOOP_ID) { + fcport->loop_id = next_loopid; + rval = qla2x00_find_new_loop_id( + base_vha, fcport); + if (rval != QLA_SUCCESS) { + /* Ran out of IDs to use */ + break; } } + /* Login and update database */ + qla2x00_fabric_dev_login(vha, fcport, &next_loopid); + } + + /* Exit if out of loop IDs. */ + if (rval != QLA_SUCCESS) { + break; + } + + /* + * Login and add the new devices to our port list. + */ + list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { + if (atomic_read(&vha->loop_down_timer) || + test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) + break; + + /* Find a new loop ID to use. */ + fcport->loop_id = next_loopid; + rval = qla2x00_find_new_loop_id(base_vha, fcport); + if (rval != QLA_SUCCESS) { + /* Ran out of IDs to use */ + break; + } /* Login and update database */ qla2x00_fabric_dev_login(vha, fcport, &next_loopid); + + if (vha->vp_idx) { + fcport->vha = vha; + fcport->vp_idx = vha->vp_idx; + } + list_move_tail(&fcport->list, &vha->vp_fcports); } } while (0); + /* Free all new device structures not processed. */ + list_for_each_entry_safe(fcport, fcptemp, &new_fcports, list) { + list_del(&fcport->list); + kfree(fcport); + } + if (rval) { ql_dbg(ql_dbg_disc, vha, 0x2068, "Configure fabric error exit rval=%d.\n", rval); @@ -3262,7 +3287,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, WWN_SIZE)) continue; - fcport->scan_state = QLA_FCPORT_SCAN_FOUND; + fcport->scan_state = QLA_FCPORT_FOUND; found++; @@ -3570,12 +3595,6 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport, if (mb[10] & BIT_1) fcport->supported_classes |= FC_COS_CLASS3; - if (IS_FWI2_CAPABLE(ha)) { - if (mb[10] & BIT_7) - fcport->flags |= - FCF_CONF_COMP_SUPPORTED; - } - rval = QLA_SUCCESS; break; } else if (mb[0] == MBS_LOOP_ID_USED) { @@ -3822,7 +3841,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) vha->flags.online = 0; ha->flags.chip_reset_done = 0; clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); - vha->qla_stats.total_isp_aborts++; + ha->qla_stats.total_isp_aborts++; ql_log(ql_log_info, vha, 0x00af, "Performing ISP error recovery - ha=%p.\n", ha); @@ -4047,7 +4066,6 @@ qla2x00_restart_isp(scsi_qla_host_t *vha) struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; struct rsp_que *rsp = ha->rsp_q_map[0]; - unsigned long flags; /* If firmware needs to be loaded */ if (qla2x00_isp_firmware(vha)) { @@ -4072,16 +4090,6 @@ qla2x00_restart_isp(scsi_qla_host_t *vha) qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL); vha->flags.online = 1; - - /* - * Process any ATIO queue entries that came in - * while we weren't online. - */ - spin_lock_irqsave(&ha->hardware_lock, flags); - if (qla_tgt_mode_enabled(vha)) - qlt_24xx_process_atio_queue(vha); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - /* Wait at most MAX_TARGET RSCNs for a stable link. */ wait_time = 256; do { @@ -4271,7 +4279,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { /* Reset NVRAM data. */ ql_log(ql_log_warn, vha, 0x006b, - "Inconsistent NVRAM detected: checksum=0x%x id=%c " + "Inconisistent NVRAM detected: checksum=0x%x id=%c " "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); ql_log(ql_log_warn, vha, 0x006c, "Falling back to functioning (yet invalid -- WWPN) " @@ -4322,15 +4330,6 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) rval = 1; } - if (!qla_ini_mode_enabled(vha)) { - /* Don't enable full login after initial LIP */ - nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13); - /* Don't enable LIP full login for initiator */ - nv->host_p &= __constant_cpu_to_le32(~BIT_10); - } - - qlt_24xx_config_nvram_stage1(vha, nv); - /* Reset Initialization control block */ memset(icb, 0, ha->init_cb_size); @@ -4358,10 +4357,8 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name), "QLA2462"); - qlt_24xx_config_nvram_stage2(vha, icb); - + /* Use alternate WWN? */ if (nv->host_p & __constant_cpu_to_le32(BIT_15)) { - /* Use alternate WWN? */ memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE); memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE); } @@ -5032,7 +5029,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) { /* Reset NVRAM data. */ ql_log(ql_log_info, vha, 0x0073, - "Inconsistent NVRAM detected: checksum=0x%x id=%c " + "Inconisistent NVRAM detected: checksum=0x%x id=%c " "version=0x%x.\n", chksum, nv->id[0], le16_to_cpu(nv->nvram_version)); ql_log(ql_log_info, vha, 0x0074, diff --git a/trunk/drivers/scsi/qla2xxx/qla_iocb.c b/trunk/drivers/scsi/qla2xxx/qla_iocb.c index 70dbf53d9e0f..eac950924497 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_iocb.c +++ b/trunk/drivers/scsi/qla2xxx/qla_iocb.c @@ -5,7 +5,6 @@ * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" -#include "qla_target.h" #include #include @@ -24,17 +23,18 @@ qla2x00_get_cmd_direction(srb_t *sp) { uint16_t cflags; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - struct scsi_qla_host *vha = sp->fcport->vha; cflags = 0; /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { cflags = CF_WRITE; - vha->qla_stats.output_bytes += scsi_bufflen(cmd); + sp->fcport->vha->hw->qla_stats.output_bytes += + scsi_bufflen(cmd); } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { cflags = CF_READ; - vha->qla_stats.input_bytes += scsi_bufflen(cmd); + sp->fcport->vha->hw->qla_stats.input_bytes += + scsi_bufflen(cmd); } return (cflags); } @@ -385,10 +385,9 @@ qla2x00_start_scsi(srb_t *sp) else req->cnt = req->length - (req->ring_index - cnt); - /* If still no head room then bail out */ - if (req->cnt < (req_cnt + 2)) - goto queuing_error; } + if (req->cnt < (req_cnt + 2)) + goto queuing_error; /* Build command packet */ req->current_outstanding_cmd = handle; @@ -471,7 +470,7 @@ qla2x00_start_scsi(srb_t *sp) /** * qla2x00_start_iocbs() - Execute the IOCB command */ -void +static void qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) { struct qla_hw_data *ha = vha->hw; @@ -572,29 +571,6 @@ qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, return (ret); } -/* - * qla2x00_issue_marker - * - * Issue marker - * Caller CAN have hardware lock held as specified by ha_locked parameter. - * Might release it, then reaquire. - */ -int qla2x00_issue_marker(scsi_qla_host_t *vha, int ha_locked) -{ - if (ha_locked) { - if (__qla2x00_marker(vha, vha->req, vha->req->rsp, 0, 0, - MK_SYNC_ALL) != QLA_SUCCESS) - return QLA_FUNCTION_FAILED; - } else { - if (qla2x00_marker(vha, vha->req, vha->req->rsp, 0, 0, - MK_SYNC_ALL) != QLA_SUCCESS) - return QLA_FUNCTION_FAILED; - } - vha->marker_needed = 0; - - return QLA_SUCCESS; -} - /** * qla24xx_calc_iocbs() - Determine number of Command Type 3 and * Continuation Type 1 IOCBs to allocate. @@ -653,11 +629,11 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, if (cmd->sc_data_direction == DMA_TO_DEVICE) { cmd_pkt->control_flags = __constant_cpu_to_le16(CF_WRITE_DATA); - vha->qla_stats.output_bytes += scsi_bufflen(cmd); + ha->qla_stats.output_bytes += scsi_bufflen(cmd); } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { cmd_pkt->control_flags = __constant_cpu_to_le16(CF_READ_DATA); - vha->qla_stats.input_bytes += scsi_bufflen(cmd); + ha->qla_stats.input_bytes += scsi_bufflen(cmd); } cur_seg = scsi_sglist(cmd); @@ -769,11 +745,13 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, if (cmd->sc_data_direction == DMA_TO_DEVICE) { cmd_pkt->task_mgmt_flags = __constant_cpu_to_le16(TMF_WRITE_DATA); - vha->qla_stats.output_bytes += scsi_bufflen(cmd); + sp->fcport->vha->hw->qla_stats.output_bytes += + scsi_bufflen(cmd); } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { cmd_pkt->task_mgmt_flags = __constant_cpu_to_le16(TMF_READ_DATA); - vha->qla_stats.input_bytes += scsi_bufflen(cmd); + sp->fcport->vha->hw->qla_stats.input_bytes += + scsi_bufflen(cmd); } /* One DSD is available in the Command Type 3 IOCB */ @@ -1267,7 +1245,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, return QLA_SUCCESS; } - cmd_pkt->vp_index = sp->fcport->vha->vp_idx; + cmd_pkt->vp_index = sp->fcport->vp_idx; /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { @@ -1524,9 +1502,9 @@ qla24xx_start_scsi(srb_t *sp) else req->cnt = req->length - (req->ring_index - cnt); - if (req->cnt < (req_cnt + 2)) - goto queuing_error; } + if (req->cnt < (req_cnt + 2)) + goto queuing_error; /* Build command packet. */ req->current_outstanding_cmd = handle; @@ -1549,7 +1527,7 @@ qla24xx_start_scsi(srb_t *sp) cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; - cmd_pkt->vp_index = sp->fcport->vha->vp_idx; + cmd_pkt->vp_index = sp->fcport->vp_idx; int_to_scsilun(cmd->device->lun, &cmd_pkt->lun); host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); @@ -1739,10 +1717,11 @@ qla24xx_dif_start_scsi(srb_t *sp) else req->cnt = req->length - (req->ring_index - cnt); - if (req->cnt < (req_cnt + 2)) - goto queuing_error; } + if (req->cnt < (req_cnt + 2)) + goto queuing_error; + status |= QDSS_GOT_Q_SPACE; /* Build header part of command packet (excluding the OPCODE). */ @@ -1919,7 +1898,7 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) logio->port_id[0] = sp->fcport->d_id.b.al_pa; logio->port_id[1] = sp->fcport->d_id.b.area; logio->port_id[2] = sp->fcport->d_id.b.domain; - logio->vp_index = sp->fcport->vha->vp_idx; + logio->vp_index = sp->fcport->vp_idx; } static void @@ -1943,7 +1922,7 @@ qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | sp->fcport->d_id.b.al_pa); - mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx); + mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); } static void @@ -1956,7 +1935,7 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio) logio->port_id[0] = sp->fcport->d_id.b.al_pa; logio->port_id[1] = sp->fcport->d_id.b.area; logio->port_id[2] = sp->fcport->d_id.b.domain; - logio->vp_index = sp->fcport->vha->vp_idx; + logio->vp_index = sp->fcport->vp_idx; } static void @@ -1973,7 +1952,7 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | sp->fcport->d_id.b.al_pa); - mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx); + mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); /* Implicit: mbx->mbx10 = 0. */ } @@ -1983,7 +1962,7 @@ qla24xx_adisc_iocb(srb_t *sp, struct logio_entry_24xx *logio) logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC); logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); - logio->vp_index = sp->fcport->vha->vp_idx; + logio->vp_index = sp->fcport->vp_idx; } static void @@ -2004,7 +1983,7 @@ qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx) mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma)); mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma))); mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma))); - mbx->mb9 = cpu_to_le16(sp->fcport->vha->vp_idx); + mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); } static void @@ -2030,7 +2009,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) tsk->port_id[0] = fcport->d_id.b.al_pa; tsk->port_id[1] = fcport->d_id.b.area; tsk->port_id[2] = fcport->d_id.b.domain; - tsk->vp_index = fcport->vha->vp_idx; + tsk->vp_index = fcport->vp_idx; if (flags == TCF_LUN_RESET) { int_to_scsilun(lun, &tsk->lun); @@ -2051,7 +2030,7 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->handle = sp->handle; els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); els_iocb->tx_dsd_count = __constant_cpu_to_le16(bsg_job->request_payload.sg_cnt); - els_iocb->vp_index = sp->fcport->vha->vp_idx; + els_iocb->vp_index = sp->fcport->vp_idx; els_iocb->sof_type = EST_SOFI3; els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); @@ -2181,7 +2160,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) ct_iocb->handle = sp->handle; ct_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); - ct_iocb->vp_index = sp->fcport->vha->vp_idx; + ct_iocb->vp_index = sp->fcport->vp_idx; ct_iocb->comp_status = __constant_cpu_to_le16(0); ct_iocb->cmd_dsd_count = @@ -2364,10 +2343,11 @@ qla82xx_start_scsi(srb_t *sp) else req->cnt = req->length - (req->ring_index - cnt); - if (req->cnt < (req_cnt + 2)) - goto queuing_error; } + if (req->cnt < (req_cnt + 2)) + goto queuing_error; + ctx = sp->u.scmd.ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); if (!ctx) { @@ -2382,7 +2362,7 @@ qla82xx_start_scsi(srb_t *sp) if (!ctx->fcp_cmnd) { ql_log(ql_log_fatal, vha, 0x3011, "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd); - goto queuing_error; + goto queuing_error_fcp_cmnd; } /* Initialize the DSD list and dma handle */ @@ -2420,7 +2400,7 @@ qla82xx_start_scsi(srb_t *sp) cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; - cmd_pkt->vp_index = sp->fcport->vha->vp_idx; + cmd_pkt->vp_index = sp->fcport->vp_idx; /* Build IOCB segments */ if (qla24xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds)) @@ -2509,7 +2489,7 @@ qla82xx_start_scsi(srb_t *sp) cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; - cmd_pkt->vp_index = sp->fcport->vha->vp_idx; + cmd_pkt->vp_index = sp->fcport->vp_idx; int_to_scsilun(cmd->device->lun, &cmd_pkt->lun); host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, diff --git a/trunk/drivers/scsi/qla2xxx/qla_isr.c b/trunk/drivers/scsi/qla2xxx/qla_isr.c index 6f67a9d4998b..ce42288049b5 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_isr.c +++ b/trunk/drivers/scsi/qla2xxx/qla_isr.c @@ -5,7 +5,6 @@ * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" -#include "qla_target.h" #include #include @@ -310,28 +309,6 @@ qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr) "IDC failed to post ACK.\n"); } -#define LS_UNKNOWN 2 -char * -qla2x00_get_link_speed_str(struct qla_hw_data *ha) -{ - static char *link_speeds[] = {"1", "2", "?", "4", "8", "16", "10"}; - char *link_speed; - int fw_speed = ha->link_data_rate; - - if (IS_QLA2100(ha) || IS_QLA2200(ha)) - link_speed = link_speeds[0]; - else if (fw_speed == 0x13) - link_speed = link_speeds[6]; - else { - link_speed = link_speeds[LS_UNKNOWN]; - if (fw_speed < 6) - link_speed = - link_speeds[fw_speed]; - } - - return link_speed; -} - /** * qla2x00_async_event() - Process aynchronous events. * @ha: SCSI driver HA context @@ -340,6 +317,9 @@ qla2x00_get_link_speed_str(struct qla_hw_data *ha) void qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) { +#define LS_UNKNOWN 2 + static char *link_speeds[] = { "1", "2", "?", "4", "8", "16", "10" }; + char *link_speed; uint16_t handle_cnt; uint16_t cnt, mbx; uint32_t handles[5]; @@ -474,8 +454,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ ql_dbg(ql_dbg_async, vha, 0x5008, "Asynchronous WAKEUP_THRES.\n"); - break; + case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ ql_dbg(ql_dbg_async, vha, 0x5009, "LIP occurred (%x).\n", mb[1]); @@ -499,14 +479,20 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) break; case MBA_LOOP_UP: /* Loop Up Event */ - if (IS_QLA2100(ha) || IS_QLA2200(ha)) + if (IS_QLA2100(ha) || IS_QLA2200(ha)) { + link_speed = link_speeds[0]; ha->link_data_rate = PORT_SPEED_1GB; - else + } else { + link_speed = link_speeds[LS_UNKNOWN]; + if (mb[1] < 6) + link_speed = link_speeds[mb[1]]; + else if (mb[1] == 0x13) + link_speed = link_speeds[6]; ha->link_data_rate = mb[1]; + } ql_dbg(ql_dbg_async, vha, 0x500a, - "LOOP UP detected (%s Gbps).\n", - qla2x00_get_link_speed_str(ha)); + "LOOP UP detected (%s Gbps).\n", link_speed); vha->flags.management_server_logged_in = 0; qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate); @@ -652,8 +638,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) ql_dbg(ql_dbg_async, vha, 0x5010, "Port unavailable %04x %04x %04x.\n", mb[1], mb[2], mb[3]); - ql_log(ql_log_warn, vha, 0x505e, - "Link is offline.\n"); if (atomic_read(&vha->loop_state) != LOOP_DOWN) { atomic_set(&vha->loop_state, LOOP_DOWN); @@ -686,17 +670,12 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) ql_dbg(ql_dbg_async, vha, 0x5011, "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n", mb[1], mb[2], mb[3]); - - qlt_async_event(mb[0], vha, mb); break; } ql_dbg(ql_dbg_async, vha, 0x5012, "Port database changed %04x %04x %04x.\n", mb[1], mb[2], mb[3]); - ql_log(ql_log_warn, vha, 0x505f, - "Link is operational (%s Gbps).\n", - qla2x00_get_link_speed_str(ha)); /* * Mark all devices as missing so we will login again. @@ -705,13 +684,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) qla2x00_mark_all_devices_lost(vha, 1); - if (vha->vp_idx == 0 && !qla_ini_mode_enabled(vha)) - set_bit(SCR_PENDING, &vha->dpc_flags); - set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); - - qlt_async_event(mb[0], vha, mb); break; case MBA_RSCN_UPDATE: /* State Change Registration */ @@ -833,8 +807,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) mb[0], mb[1], mb[2], mb[3]); } - qlt_async_event(mb[0], vha, mb); - if (!vha->vp_idx && ha->num_vhosts) qla2x00_alert_all_vps(rsp, mb); } @@ -1200,9 +1172,6 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, } else if (iop[0] & BIT_5) fcport->port_type = FCT_INITIATOR; - if (iop[0] & BIT_7) - fcport->flags |= FCF_CONF_COMP_SUPPORTED; - if (logio->io_parameter[7] || logio->io_parameter[8]) fcport->supported_classes |= FC_COS_CLASS2; if (logio->io_parameter[9] || logio->io_parameter[10]) @@ -2017,9 +1986,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, if (pkt->entry_status != 0) { qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt); - - (void)qlt_24xx_process_response_error(vha, pkt); - ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); continue; @@ -2050,14 +2016,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, case ELS_IOCB_TYPE: qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); break; - case ABTS_RECV_24XX: - /* ensure that the ATIO queue is empty */ - qlt_24xx_process_atio_queue(vha); - case ABTS_RESP_24XX: - case CTIO_TYPE7: - case NOTIFY_ACK_TYPE: - qlt_response_pkt_all_vps(vha, (response_t *)pkt); - break; case MARKER_TYPE: /* Do nothing in this case, this check is to prevent it * from falling into default case @@ -2210,13 +2168,6 @@ qla24xx_intr_handler(int irq, void *dev_id) case 0x14: qla24xx_process_response_queue(vha, rsp); break; - case 0x1C: /* ATIO queue updated */ - qlt_24xx_process_atio_queue(vha); - break; - case 0x1D: /* ATIO and response queues updated */ - qlt_24xx_process_atio_queue(vha); - qla24xx_process_response_queue(vha, rsp); - break; default: ql_dbg(ql_dbg_async, vha, 0x504f, "Unrecognized interrupt type (%d).\n", stat * 0xff); @@ -2361,13 +2312,6 @@ qla24xx_msix_default(int irq, void *dev_id) case 0x14: qla24xx_process_response_queue(vha, rsp); break; - case 0x1C: /* ATIO queue updated */ - qlt_24xx_process_atio_queue(vha); - break; - case 0x1D: /* ATIO and response queues updated */ - qlt_24xx_process_atio_queue(vha); - qla24xx_process_response_queue(vha, rsp); - break; default: ql_dbg(ql_dbg_async, vha, 0x5051, "Unrecognized interrupt type (%d).\n", stat & 0xff); @@ -2620,15 +2564,7 @@ void qla2x00_free_irqs(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - struct rsp_que *rsp; - - /* - * We need to check that ha->rsp_q_map is valid in case we are called - * from a probe failure context. - */ - if (!ha->rsp_q_map || !ha->rsp_q_map[0]) - return; - rsp = ha->rsp_q_map[0]; + struct rsp_que *rsp = ha->rsp_q_map[0]; if (ha->flags.msix_enabled) qla24xx_disable_msix(ha); diff --git a/trunk/drivers/scsi/qla2xxx/qla_mbx.c b/trunk/drivers/scsi/qla2xxx/qla_mbx.c index d5ce92c0a8fc..b4a23394a7bd 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_mbx.c +++ b/trunk/drivers/scsi/qla2xxx/qla_mbx.c @@ -5,7 +5,6 @@ * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" -#include "qla_target.h" #include #include @@ -271,8 +270,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) ictrl = RD_REG_WORD(®->isp.ictrl); } ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119, - "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx " - "mb[0]=0x%x\n", command, ictrl, jiffies, mb0); + "MBX Command timeout for cmd %x.\n", command); + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111a, + "iocontrol=%x jiffies=%lx.\n", ictrl, jiffies); + ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111b, + "mb[0] = 0x%x.\n", mb0); ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019); /* @@ -318,7 +320,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) CRB_NIU_XG_PAUSE_CTL_P1); } ql_log(ql_log_info, base_vha, 0x101c, - "Mailbox cmd timeout occurred, cmd=0x%x, " + "Mailbox cmd timeout occured, cmd=0x%x, " "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP " "abort.\n", command, mcp->mb[0], ha->flags.eeh_busy); @@ -343,7 +345,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) CRB_NIU_XG_PAUSE_CTL_P1); } ql_log(ql_log_info, base_vha, 0x101e, - "Mailbox cmd timeout occurred, cmd=0x%x, " + "Mailbox cmd timeout occured, cmd=0x%x, " "mb[0]=0x%x. Scheduling ISP abort ", command, mcp->mb[0]); set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags); @@ -388,8 +390,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1022, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1022, "Entered %s.\n", __func__); if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) { mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; @@ -423,8 +424,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr, ql_dbg(ql_dbg_mbx, vha, 0x1023, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1024, "Done %s.\n", __func__); } return rval; @@ -454,8 +454,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1025, "Entered %s.\n", __func__); mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->out_mb = MBX_0; @@ -490,11 +489,10 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { if (IS_FWI2_CAPABLE(ha)) { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1027, + ql_dbg(ql_dbg_mbx, vha, 0x1027, "Done exchanges=%x.\n", mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1028, "Done %s.\n", __func__); } } @@ -525,8 +523,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1029, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1029, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_FIRMWARE_VERSION; mcp->out_mb = MBX_0; @@ -564,11 +561,11 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) ha->fw_attributes_h = mcp->mb[15]; ha->fw_attributes_ext[0] = mcp->mb[16]; ha->fw_attributes_ext[1] = mcp->mb[17]; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1139, + ql_dbg(ql_dbg_mbx, vha, 0x1139, "%s: FW_attributes Upper: 0x%x, Lower: 0x%x.\n", __func__, mcp->mb[15], mcp->mb[6]); } else - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x112f, + ql_dbg(ql_dbg_mbx, vha, 0x112f, "%s: FwAttributes [Upper] invalid, MB6:%04x\n", __func__, mcp->mb[6]); } @@ -579,8 +576,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x102a, "Failed=%x.\n", rval); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102b, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x102b, "Done %s.\n", __func__); } return rval; } @@ -606,8 +602,7 @@ qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102c, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x102c, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_FIRMWARE_OPTION; mcp->out_mb = MBX_0; @@ -625,8 +620,7 @@ qla2x00_get_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) fwopts[2] = mcp->mb[2]; fwopts[3] = mcp->mb[3]; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102e, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x102e, "Done %s.\n", __func__); } return rval; @@ -654,8 +648,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x102f, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x102f, "Entered %s.\n", __func__); mcp->mb[0] = MBC_SET_FIRMWARE_OPTION; mcp->mb[1] = fwopts[1]; @@ -683,8 +676,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *vha, uint16_t *fwopts) "Failed=%x (%x/%x).\n", rval, mcp->mb[0], mcp->mb[1]); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1031, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1031, "Done %s.\n", __func__); } return rval; @@ -712,8 +704,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1032, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1032, "Entered %s.\n", __func__); mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST; mcp->mb[1] = 0xAAAA; @@ -743,8 +734,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1034, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1034, "Done %s.\n", __func__); } return rval; @@ -772,8 +762,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1035, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1035, "Entered %s.\n", __func__); mcp->mb[0] = MBC_VERIFY_CHECKSUM; mcp->out_mb = MBX_0; @@ -798,8 +787,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *vha, uint32_t risc_addr) "Failed=%x chm sum=%x.\n", rval, IS_FWI2_CAPABLE(vha->hw) ? (mcp->mb[2] << 16) | mcp->mb[1] : mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1037, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1037, "Done %s.\n", __func__); } return rval; @@ -831,8 +819,7 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1038, "Entered %s.\n", __func__); mcp->mb[0] = MBC_IOCB_COMMAND_A64; mcp->mb[1] = 0; @@ -855,8 +842,7 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, /* Mask reserved bits. */ sts_entry->entry_status &= IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x103a, "Done %s.\n", __func__); } return rval; @@ -898,8 +884,7 @@ qla2x00_abort_command(srb_t *sp) struct req_que *req = vha->req; struct scsi_cmnd *cmd = GET_CMD_SP(sp); - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x103b, "Entered %s.\n", __func__); spin_lock_irqsave(&ha->hardware_lock, flags); for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { @@ -930,8 +915,7 @@ qla2x00_abort_command(srb_t *sp) if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x103c, "Failed=%x.\n", rval); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103d, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x103d, "Done %s.\n", __func__); } return rval; @@ -950,8 +934,7 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) l = l; vha = fcport->vha; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103e, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x103e, "Entered %s.\n", __func__); req = vha->hw->req_q_map[0]; rsp = req->rsp; @@ -972,8 +955,7 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); if (rval != QLA_SUCCESS) { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103f, - "Failed=%x.\n", rval); + ql_dbg(ql_dbg_mbx, vha, 0x103f, "Failed=%x.\n", rval); } /* Issue marker IOCB. */ @@ -983,8 +965,7 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) ql_dbg(ql_dbg_mbx, vha, 0x1040, "Failed to issue marker IOCB (%x).\n", rval2); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1041, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1041, "Done %s.\n", __func__); } return rval; @@ -1002,8 +983,7 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) vha = fcport->vha; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1042, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1042, "Entered %s.\n", __func__); req = vha->hw->req_q_map[0]; rsp = req->rsp; @@ -1032,8 +1012,7 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) ql_dbg(ql_dbg_mbx, vha, 0x1044, "Failed to issue marker IOCB (%x).\n", rval2); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1045, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1045, "Done %s.\n", __func__); } return rval; @@ -1067,8 +1046,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1046, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1046, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_ADAPTER_LOOP_ID; mcp->mb[9] = vha->vp_idx; @@ -1096,8 +1074,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa, /*EMPTY*/ ql_dbg(ql_dbg_mbx, vha, 0x1047, "Failed=%x.\n", rval); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1048, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1048, "Done %s.\n", __func__); if (IS_CNA_CAPABLE(vha->hw)) { vha->fcoe_vlan_id = mcp->mb[9] & 0xfff; @@ -1138,8 +1115,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1049, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1049, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_RETRY_COUNT; mcp->out_mb = MBX_0; @@ -1162,7 +1138,7 @@ qla2x00_get_retry_cnt(scsi_qla_host_t *vha, uint8_t *retry_cnt, uint8_t *tov, *tov = ratov; } - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104b, + ql_dbg(ql_dbg_mbx, vha, 0x104b, "Done %s mb3=%d ratov=%d.\n", __func__, mcp->mb[3], ratov); } @@ -1194,8 +1170,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104c, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x104c, "Entered %s.\n", __func__); if (IS_QLA82XX(ha) && ql2xdbwr) qla82xx_wr_32(ha, ha->nxdb_wr_ptr, @@ -1238,100 +1213,9 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size) rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104e, - "Done %s.\n", __func__); - } - - return rval; -} - -/* - * qla2x00_get_node_name_list - * Issue get node name list mailbox command, kmalloc() - * and return the resulting list. Caller must kfree() it! - * - * Input: - * ha = adapter state pointer. - * out_data = resulting list - * out_len = length of the resulting list - * - * Returns: - * qla2x00 local function return status code. - * - * Context: - * Kernel context. - */ -int -qla2x00_get_node_name_list(scsi_qla_host_t *vha, void **out_data, int *out_len) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_port_24xx_data *list = NULL; - void *pmap; - mbx_cmd_t mc; - dma_addr_t pmap_dma; - ulong dma_size; - int rval, left; - - left = 1; - while (left > 0) { - dma_size = left * sizeof(*list); - pmap = dma_alloc_coherent(&ha->pdev->dev, dma_size, - &pmap_dma, GFP_KERNEL); - if (!pmap) { - ql_log(ql_log_warn, vha, 0x113f, - "%s(%ld): DMA Alloc failed of %ld\n", - __func__, vha->host_no, dma_size); - rval = QLA_MEMORY_ALLOC_FAILED; - goto out; - } - - mc.mb[0] = MBC_PORT_NODE_NAME_LIST; - mc.mb[1] = BIT_1 | BIT_3; - mc.mb[2] = MSW(pmap_dma); - mc.mb[3] = LSW(pmap_dma); - mc.mb[6] = MSW(MSD(pmap_dma)); - mc.mb[7] = LSW(MSD(pmap_dma)); - mc.mb[8] = dma_size; - mc.out_mb = MBX_0|MBX_1|MBX_2|MBX_3|MBX_6|MBX_7|MBX_8; - mc.in_mb = MBX_0|MBX_1; - mc.tov = 30; - mc.flags = MBX_DMA_IN; - - rval = qla2x00_mailbox_command(vha, &mc); - if (rval != QLA_SUCCESS) { - if ((mc.mb[0] == MBS_COMMAND_ERROR) && - (mc.mb[1] == 0xA)) { - left += le16_to_cpu(mc.mb[2]) / - sizeof(struct qla_port_24xx_data); - goto restart; - } - goto out_free; - } - - left = 0; - - list = kzalloc(dma_size, GFP_KERNEL); - if (!list) { - ql_log(ql_log_warn, vha, 0x1140, - "%s(%ld): failed to allocate node names list " - "structure.\n", __func__, vha->host_no); - rval = QLA_MEMORY_ALLOC_FAILED; - goto out_free; - } - - memcpy(list, pmap, dma_size); -restart: - dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma); + ql_dbg(ql_dbg_mbx, vha, 0x104e, "Done %s.\n", __func__); } - *out_data = list; - *out_len = dma_size; - -out: - return rval; - -out_free: - dma_free_coherent(&ha->pdev->dev, dma_size, pmap, pmap_dma); return rval; } @@ -1362,8 +1246,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) dma_addr_t pd_dma; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104f, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x104f, "Entered %s.\n", __func__); pd24 = NULL; pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pd_dma); @@ -1443,13 +1326,6 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) fcport->port_type = FCT_INITIATOR; else fcport->port_type = FCT_TARGET; - - /* Passback COS information. */ - fcport->supported_classes = (pd24->flags & PDF_CLASS_2) ? - FC_COS_CLASS2 : FC_COS_CLASS3; - - if (pd24->prli_svc_param_word_3[0] & BIT_7) - fcport->flags |= FCF_CONF_COMP_SUPPORTED; } else { uint64_t zero = 0; @@ -1502,8 +1378,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt) "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1053, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1053, "Done %s.\n", __func__); } return rval; @@ -1532,8 +1407,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1054, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_FIRMWARE_STATE; mcp->out_mb = MBX_0; @@ -1559,8 +1433,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1056, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1056, "Done %s.\n", __func__); } return rval; @@ -1592,8 +1465,7 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1057, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1057, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_PORT_NAME; mcp->mb[9] = vha->vp_idx; @@ -1627,8 +1499,7 @@ qla2x00_get_port_name(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t *name, name[7] = LSB(mcp->mb[7]); } - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1059, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1059, "Done %s.\n", __func__); } return rval; @@ -1656,8 +1527,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105a, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x105a, "Entered %s.\n", __func__); if (IS_CNA_CAPABLE(vha->hw)) { /* Logout across all FCFs. */ @@ -1694,8 +1564,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x105b, "Failed=%x.\n", rval); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105c, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x105c, "Done %s.\n", __func__); } return rval; @@ -1727,10 +1596,9 @@ qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105d, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x105d, "Entered %s.\n", __func__); - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x105e, + ql_dbg(ql_dbg_mbx, vha, 0x105e, "Retry cnt=%d ratov=%d total tov=%d.\n", vha->hw->retry_count, vha->hw->login_timeout, mcp->tov); @@ -1754,8 +1622,7 @@ qla2x00_send_sns(scsi_qla_host_t *vha, dma_addr_t sns_phys_address, rval, mcp->mb[0], mcp->mb[1]); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1060, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1060, "Done %s.\n", __func__); } return rval; @@ -1774,8 +1641,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, struct req_que *req; struct rsp_que *rsp; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1061, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1061, "Entered %s.\n", __func__); if (ha->flags.cpu_affinity_enabled) req = ha->req_q_map[0]; @@ -1849,8 +1715,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, break; } } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1066, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1066, "Done %s.\n", __func__); iop[0] = le32_to_cpu(lg->io_parameter[0]); @@ -1868,10 +1733,6 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, mb[10] |= BIT_0; /* Class 2. */ if (lg->io_parameter[9] || lg->io_parameter[10]) mb[10] |= BIT_1; /* Class 3. */ - if (lg->io_parameter[0] & __constant_cpu_to_le32(BIT_7)) - mb[10] |= BIT_7; /* Confirmed Completion - * Allowed - */ } dma_pool_free(ha->s_dma_pool, lg, lg_dma); @@ -1909,8 +1770,7 @@ qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1067, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1067, "Entered %s.\n", __func__); mcp->mb[0] = MBC_LOGIN_FABRIC_PORT; mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; @@ -1958,8 +1818,7 @@ qla2x00_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1069, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1069, "Done %s.\n", __func__); } return rval; @@ -1990,8 +1849,7 @@ qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport, mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106a, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x106a, "Entered %s.\n", __func__); if (IS_FWI2_CAPABLE(ha)) return qla24xx_login_fabric(vha, fcport->loop_id, @@ -2033,8 +1891,7 @@ qla2x00_login_local_device(scsi_qla_host_t *vha, fc_port_t *fcport, rval, mcp->mb[0], mcp->mb[1], mcp->mb[6], mcp->mb[7]); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106c, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x106c, "Done %s.\n", __func__); } return (rval); @@ -2051,8 +1908,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, struct req_que *req; struct rsp_que *rsp; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x106d, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x106d, "Entered %s.\n", __func__); lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); if (lg == NULL) { @@ -2096,8 +1952,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, le32_to_cpu(lg->io_parameter[1])); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1072, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1072, "Done %s.\n", __func__); } dma_pool_free(ha->s_dma_pool, lg, lg_dma); @@ -2129,8 +1984,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1073, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1073, "Entered %s.\n", __func__); mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT; mcp->out_mb = MBX_1|MBX_0; @@ -2153,8 +2007,7 @@ qla2x00_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, "Failed=%x mb[1]=%x.\n", rval, mcp->mb[1]); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1075, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1075, "Done %s.\n", __func__); } return rval; @@ -2182,8 +2035,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1076, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1076, "Entered %s.\n", __func__); mcp->mb[0] = MBC_LIP_FULL_LOGIN; mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_3 : 0; @@ -2200,8 +2052,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x1077, "Failed=%x.\n", rval); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1078, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1078, "Done %s.\n", __func__); } return rval; @@ -2227,8 +2078,7 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1079, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1079, "Entered %s.\n", __func__); if (id_list == NULL) return QLA_FUNCTION_FAILED; @@ -2260,8 +2110,7 @@ qla2x00_get_id_list(scsi_qla_host_t *vha, void *id_list, dma_addr_t id_list_dma, ql_dbg(ql_dbg_mbx, vha, 0x107a, "Failed=%x.\n", rval); } else { *entries = mcp->mb[1]; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107b, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x107b, "Done %s.\n", __func__); } return rval; @@ -2289,8 +2138,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107c, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x107c, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; mcp->out_mb = MBX_0; @@ -2306,7 +2154,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, ql_dbg(ql_dbg_mbx, vha, 0x107d, "Failed mb[0]=%x.\n", mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107e, + ql_dbg(ql_dbg_mbx, vha, 0x107e, "Done %s mb1=%x mb2=%x mb3=%x mb6=%x mb7=%x mb10=%x " "mb11=%x mb12=%x.\n", __func__, mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[6], mcp->mb[7], mcp->mb[10], @@ -2353,8 +2201,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) dma_addr_t pmap_dma; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x107f, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x107f, "Entered %s.\n", __func__); pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); if (pmap == NULL) { @@ -2377,7 +2224,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) rval = qla2x00_mailbox_command(vha, mcp); if (rval == QLA_SUCCESS) { - ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1081, + ql_dbg(ql_dbg_mbx, vha, 0x1081, "mb0/mb1=%x/%X FC/AL position map size (%x).\n", mcp->mb[0], mcp->mb[1], (unsigned)pmap[0]); ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111d, @@ -2391,8 +2238,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map) if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x1082, "Failed=%x.\n", rval); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1083, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1083, "Done %s.\n", __func__); } return rval; @@ -2421,8 +2267,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id, uint32_t *siter, *diter, dwords; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1084, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_LINK_STATUS; mcp->mb[2] = MSW(stats_dma); @@ -2456,8 +2301,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id, rval = QLA_FUNCTION_FAILED; } else { /* Copy over data -- firmware data is LE. */ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1086, "Done %s.\n", __func__); dwords = offsetof(struct link_statistics, unused1) / 4; siter = diter = &stats->link_fail_cnt; while (dwords--) @@ -2480,8 +2324,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, mbx_cmd_t *mcp = &mc; uint32_t *siter, *diter, dwords; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1088, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GET_LINK_PRIV_STATS; mcp->mb[2] = MSW(stats_dma); @@ -2503,8 +2346,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, "Failed mb[0]=%x.\n", mcp->mb[0]); rval = QLA_FUNCTION_FAILED; } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x108a, "Done %s.\n", __func__); /* Copy over data -- firmware data is LE. */ dwords = sizeof(struct link_statistics) / 4; siter = diter = &stats->link_fail_cnt; @@ -2533,8 +2375,7 @@ qla24xx_abort_command(srb_t *sp) struct qla_hw_data *ha = vha->hw; struct req_que *req = vha->req; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108c, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x108c, "Entered %s.\n", __func__); spin_lock_irqsave(&ha->hardware_lock, flags); for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { @@ -2563,7 +2404,7 @@ qla24xx_abort_command(srb_t *sp) abt->port_id[0] = fcport->d_id.b.al_pa; abt->port_id[1] = fcport->d_id.b.area; abt->port_id[2] = fcport->d_id.b.domain; - abt->vp_index = fcport->vha->vp_idx; + abt->vp_index = fcport->vp_idx; abt->req_que_no = cpu_to_le16(req->id); @@ -2582,8 +2423,7 @@ qla24xx_abort_command(srb_t *sp) le16_to_cpu(abt->nport_handle)); rval = QLA_FUNCTION_FAILED; } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1091, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1091, "Done %s.\n", __func__); } dma_pool_free(ha->s_dma_pool, abt, abt_dma); @@ -2615,8 +2455,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, ha = vha->hw; req = vha->req; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1092, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1092, "Entered %s.\n", __func__); if (ha->flags.cpu_affinity_enabled) rsp = ha->rsp_q_map[tag + 1]; @@ -2639,7 +2478,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; tsk->p.tsk.port_id[1] = fcport->d_id.b.area; tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; - tsk->p.tsk.vp_index = fcport->vha->vp_idx; + tsk->p.tsk.vp_index = fcport->vp_idx; if (type == TCF_LUN_RESET) { int_to_scsilun(l, &tsk->p.tsk.lun); host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun, @@ -2665,7 +2504,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, } else if (le16_to_cpu(sts->scsi_status) & SS_RESPONSE_INFO_LEN_VALID) { if (le32_to_cpu(sts->rsp_data_len) < 4) { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1097, + ql_dbg(ql_dbg_mbx, vha, 0x1097, "Ignoring inconsistent data length -- not enough " "response info (%d).\n", le32_to_cpu(sts->rsp_data_len)); @@ -2684,8 +2523,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, ql_dbg(ql_dbg_mbx, vha, 0x1099, "Failed to issue marker IOCB (%x).\n", rval2); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109a, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x109a, "Done %s.\n", __func__); } dma_pool_free(ha->s_dma_pool, tsk, tsk_dma); @@ -2726,8 +2564,7 @@ qla2x00_system_error(scsi_qla_host_t *vha) if (!IS_QLA23XX(ha) && !IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109b, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x109b, "Entered %s.\n", __func__); mcp->mb[0] = MBC_GEN_SYSTEM_ERROR; mcp->out_mb = MBX_0; @@ -2739,8 +2576,7 @@ qla2x00_system_error(scsi_qla_host_t *vha) if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x109c, "Failed=%x.\n", rval); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109d, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x109d, "Done %s.\n", __func__); } return rval; @@ -2760,8 +2596,7 @@ qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x109e, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x109e, "Entered %s.\n", __func__); mcp->mb[0] = MBC_SERDES_PARAMS; mcp->mb[1] = BIT_0; @@ -2780,8 +2615,7 @@ qla2x00_set_serdes_params(scsi_qla_host_t *vha, uint16_t sw_em_1g, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { /*EMPTY*/ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a0, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10a0, "Done %s.\n", __func__); } return rval; @@ -2797,8 +2631,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha) if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a1, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10a1, "Entered %s.\n", __func__); mcp->mb[0] = MBC_STOP_FIRMWARE; mcp->mb[1] = 0; @@ -2813,8 +2646,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *vha) if (mcp->mb[0] == MBS_INVALID_COMMAND) rval = QLA_INVALID_COMMAND; } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a3, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10a3, "Done %s.\n", __func__); } return rval; @@ -2828,8 +2660,7 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a4, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10a4, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -2855,8 +2686,7 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma, "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a6, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10a6, "Done %s.\n", __func__); } return rval; @@ -2869,8 +2699,7 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a7, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10a7, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -2890,8 +2719,7 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha) "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10a9, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10a9, "Done %s.\n", __func__); } return rval; @@ -2905,8 +2733,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10aa, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10aa, "Entered %s.\n", __func__); if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) @@ -2937,8 +2764,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ac, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10ac, "Done %s.\n", __func__); if (mb) memcpy(mb, mcp->mb, 8 * sizeof(*mb)); @@ -2956,8 +2782,7 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ad, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10ad, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -2979,8 +2804,7 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd) "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10af, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10af, "Done %s.\n", __func__); if (wr) *wr = (uint64_t) mcp->mb[5] << 48 | @@ -3005,8 +2829,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b0, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10b0, "Entered %s.\n", __func__); if (!IS_IIDMA_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -3031,8 +2854,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x10b1, "Failed=%x.\n", rval); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b2, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10b2, "Done %s.\n", __func__); if (port_speed) *port_speed = mcp->mb[3]; } @@ -3048,8 +2870,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b3, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10b3, "Entered %s.\n", __func__); if (!IS_IIDMA_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -3076,11 +2897,9 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, } if (rval != QLA_SUCCESS) { - ql_dbg(ql_dbg_mbx, vha, 0x10b4, - "Failed=%x.\n", rval); + ql_dbg(ql_dbg_mbx, vha, 0x10b4, "Failed=%x.\n", rval); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b5, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10b5, "Done %s.\n", __func__); } return rval; @@ -3096,25 +2915,24 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, scsi_qla_host_t *vp; unsigned long flags; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b6, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10b6, "Entered %s.\n", __func__); if (rptid_entry->entry_status != 0) return; if (rptid_entry->format == 0) { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b7, + ql_dbg(ql_dbg_mbx, vha, 0x10b7, "Format 0 : Number of VPs setup %d, number of " "VPs acquired %d.\n", MSB(le16_to_cpu(rptid_entry->vp_count)), LSB(le16_to_cpu(rptid_entry->vp_count))); - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b8, + ql_dbg(ql_dbg_mbx, vha, 0x10b8, "Primary port id %02x%02x%02x.\n", rptid_entry->port_id[2], rptid_entry->port_id[1], rptid_entry->port_id[0]); } else if (rptid_entry->format == 1) { vp_idx = LSB(stat); - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10b9, + ql_dbg(ql_dbg_mbx, vha, 0x10b9, "Format 1: VP[%d] enabled - status %d - with " "port id %02x%02x%02x.\n", vp_idx, MSB(stat), rptid_entry->port_id[2], rptid_entry->port_id[1], @@ -3181,8 +2999,7 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha) /* This can be called by the parent */ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10bb, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10bb, "Entered %s.\n", __func__); vpmod = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &vpmod_dma); if (!vpmod) { @@ -3198,9 +3015,6 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha) vpmod->vp_count = 1; vpmod->vp_index1 = vha->vp_idx; vpmod->options_idx1 = BIT_3|BIT_4|BIT_5; - - qlt_modify_vp_config(vha, vpmod); - memcpy(vpmod->node_name_idx1, vha->node_name, WWN_SIZE); memcpy(vpmod->port_name_idx1, vha->port_name, WWN_SIZE); vpmod->entry_count = 1; @@ -3221,8 +3035,7 @@ qla24xx_modify_vp_config(scsi_qla_host_t *vha) rval = QLA_FUNCTION_FAILED; } else { /* EMPTY */ - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c0, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10c0, "Done %s.\n", __func__); fc_vport_set_state(vha->fc_vport, FC_VPORT_INITIALIZING); } dma_pool_free(ha->s_dma_pool, vpmod, vpmod_dma); @@ -3256,7 +3069,7 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) int vp_index = vha->vp_idx; struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c1, + ql_dbg(ql_dbg_mbx, vha, 0x10c1, "Entered %s enabling index %d.\n", __func__, vp_index); if (vp_index == 0 || vp_index >= ha->max_npiv_vports) @@ -3299,8 +3112,7 @@ qla24xx_control_vp(scsi_qla_host_t *vha, int cmd) le16_to_cpu(vce->comp_status)); rval = QLA_FUNCTION_FAILED; } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c6, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10c6, "Done %s.\n", __func__); } dma_pool_free(ha->s_dma_pool, vce, vce_dma); @@ -3337,8 +3149,14 @@ qla2x00_send_change_request(scsi_qla_host_t *vha, uint16_t format, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c7, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10c7, "Entered %s.\n", __func__); + + /* + * This command is implicitly executed by firmware during login for the + * physical hosts + */ + if (vp_idx == 0) + return QLA_FUNCTION_FAILED; mcp->mb[0] = MBC_SEND_CHANGE_REQUEST; mcp->mb[1] = format; @@ -3367,8 +3185,7 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1009, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1009, "Entered %s.\n", __func__); if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) { mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED; @@ -3402,8 +3219,7 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr, ql_dbg(ql_dbg_mbx, vha, 0x1008, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1007, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1007, "Done %s.\n", __func__); } return rval; @@ -3428,8 +3244,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) unsigned long flags; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10c8, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10c8, "Entered %s.\n", __func__); mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); if (mn == NULL) { @@ -3470,7 +3285,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) status[0] = le16_to_cpu(mn->p.rsp.comp_status); status[1] = status[0] == CS_VCS_CHIP_FAILURE ? le16_to_cpu(mn->p.rsp.failure_code) : 0; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ce, + ql_dbg(ql_dbg_mbx, vha, 0x10ce, "cs=%x fc=%x.\n", status[0], status[1]); if (status[0] != CS_COMPLETE) { @@ -3484,7 +3299,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) retry = 1; } } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d0, + ql_dbg(ql_dbg_mbx, vha, 0x10d0, "Firmware updated to %x.\n", le32_to_cpu(mn->p.rsp.fw_ver)); @@ -3501,11 +3316,9 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status) dma_pool_free(ha->s_dma_pool, mn, mn_dma); if (rval != QLA_SUCCESS) { - ql_dbg(ql_dbg_mbx, vha, 0x10d1, - "Failed=%x.\n", rval); + ql_dbg(ql_dbg_mbx, vha, 0x10d1, "Failed=%x.\n", rval); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d2, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10d2, "Done %s.\n", __func__); } return rval; @@ -3521,8 +3334,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) struct device_reg_25xxmq __iomem *reg; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d3, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10d3, "Entered %s.\n", __func__); mcp->mb[0] = MBC_INITIALIZE_MULTIQ; mcp->mb[1] = req->options; @@ -3576,8 +3388,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req) ql_dbg(ql_dbg_mbx, vha, 0x10d4, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d5, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10d5, "Done %s.\n", __func__); } return rval; @@ -3593,8 +3404,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) struct device_reg_25xxmq __iomem *reg; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d6, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10d6, "Entered %s.\n", __func__); mcp->mb[0] = MBC_INITIALIZE_MULTIQ; mcp->mb[1] = rsp->options; @@ -3646,8 +3456,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) ql_dbg(ql_dbg_mbx, vha, 0x10d7, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d8, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10d8, "Done %s.\n", __func__); } return rval; @@ -3660,8 +3469,7 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10d9, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10d9, "Entered %s.\n", __func__); mcp->mb[0] = MBC_IDC_ACK; memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t)); @@ -3675,8 +3483,7 @@ qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb) ql_dbg(ql_dbg_mbx, vha, 0x10da, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10db, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10db, "Done %s.\n", __func__); } return rval; @@ -3689,8 +3496,7 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10dc, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10dc, "Entered %s.\n", __func__); if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) return QLA_FUNCTION_FAILED; @@ -3708,8 +3514,7 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size) "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10de, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10de, "Done %s.\n", __func__); *sector_size = mcp->mb[1]; } @@ -3726,8 +3531,7 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable) if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) return QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10df, "Entered %s.\n", __func__); mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE : @@ -3743,8 +3547,7 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable) "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e1, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10e1, "Done %s.\n", __func__); } return rval; @@ -3760,8 +3563,7 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw)) return QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10e2, "Entered %s.\n", __func__); mcp->mb[0] = MBC_FLASH_ACCESS_CTRL; mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR; @@ -3780,8 +3582,7 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish) "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10e4, "Done %s.\n", __func__); } return rval; @@ -3794,8 +3595,7 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e5, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10e5, "Entered %s.\n", __func__); mcp->mb[0] = MBC_RESTART_MPI_FW; mcp->out_mb = MBX_0; @@ -3809,8 +3609,7 @@ qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha) "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e7, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10e7, "Done %s.\n", __func__); } return rval; @@ -3825,8 +3624,7 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10e8, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; @@ -3856,8 +3654,7 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, ql_dbg(ql_dbg_mbx, vha, 0x10e9, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10ea, "Done %s.\n", __func__); } return rval; @@ -3872,8 +3669,7 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10eb, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10eb, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; @@ -3903,8 +3699,7 @@ qla2x00_write_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, ql_dbg(ql_dbg_mbx, vha, 0x10ec, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ed, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10ed, "Done %s.\n", __func__); } return rval; @@ -3918,8 +3713,7 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ee, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10ee, "Entered %s.\n", __func__); if (!IS_CNA_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -3941,8 +3735,7 @@ qla2x00_get_xgmac_stats(scsi_qla_host_t *vha, dma_addr_t stats_dma, "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f0, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10f0, "Done %s.\n", __func__); *actual_size = mcp->mb[2] << 2; @@ -3959,8 +3752,7 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f1, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10f1, "Entered %s.\n", __func__); if (!IS_CNA_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -3983,8 +3775,7 @@ qla2x00_get_dcbx_params(scsi_qla_host_t *vha, dma_addr_t tlv_dma, "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f3, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10f3, "Done %s.\n", __func__); } return rval; @@ -3997,8 +3788,7 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f4, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10f4, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -4015,8 +3805,7 @@ qla2x00_read_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t *data) ql_dbg(ql_dbg_mbx, vha, 0x10f5, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f6, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10f6, "Done %s.\n", __func__); *data = mcp->mb[3] << 16 | mcp->mb[2]; } @@ -4032,8 +3821,7 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, mbx_cmd_t *mcp = &mc; uint32_t iter_cnt = 0x1; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f7, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10f7, "Entered %s.\n", __func__); memset(mcp->mb, 0 , sizeof(mcp->mb)); mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK; @@ -4077,8 +3865,7 @@ qla2x00_loopback_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, "mb[19]=%x.\n", rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[18], mcp->mb[19]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10f9, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10f9, "Done %s.\n", __func__); } /* Copy mailbox information */ @@ -4095,8 +3882,7 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fa, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10fa, "Entered %s.\n", __func__); memset(mcp->mb, 0 , sizeof(mcp->mb)); mcp->mb[0] = MBC_DIAGNOSTIC_ECHO; @@ -4140,8 +3926,7 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq, "Failed=%x mb[0]=%x mb[1]=%x.\n", rval, mcp->mb[0], mcp->mb[1]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fc, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10fc, "Done %s.\n", __func__); } /* Copy mailbox information */ @@ -4156,7 +3941,7 @@ qla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10fd, + ql_dbg(ql_dbg_mbx, vha, 0x10fd, "Entered %s enable_diag=%d.\n", __func__, enable_diagnostic); mcp->mb[0] = MBC_ISP84XX_RESET; @@ -4170,8 +3955,7 @@ qla84xx_reset_chip(scsi_qla_host_t *vha, uint16_t enable_diagnostic) if (rval != QLA_SUCCESS) ql_dbg(ql_dbg_mbx, vha, 0x10fe, "Failed=%x.\n", rval); else - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ff, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10ff, "Done %s.\n", __func__); return rval; } @@ -4183,8 +3967,7 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1100, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1100, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; @@ -4203,8 +3986,7 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) ql_dbg(ql_dbg_mbx, vha, 0x1101, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1102, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1102, "Done %s.\n", __func__); } return rval; @@ -4221,8 +4003,7 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb) rval = QLA_SUCCESS; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1103, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1103, "Entered %s.\n", __func__); clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); @@ -4265,8 +4046,7 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb) ql_dbg(ql_dbg_mbx, vha, 0x1104, "Failed=%x mb[0]=%x.\n", rval, mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1105, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1105, "Done %s.\n", __func__); } return rval; @@ -4280,8 +4060,7 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1106, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; @@ -4299,8 +4078,7 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x1107, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1108, "Done %s.\n", __func__); if (mcp->mb[1] != 0x7) ha->link_data_rate = mcp->mb[1]; } @@ -4316,8 +4094,7 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1109, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1109, "Entered %s.\n", __func__); if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha)) return QLA_FUNCTION_FAILED; @@ -4336,8 +4113,7 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb) /* Copy all bits to preserve original value */ memcpy(mb, &mcp->mb[1], sizeof(uint16_t) * 4); - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110b, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x110b, "Done %s.\n", __func__); } return rval; } @@ -4349,8 +4125,7 @@ qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110c, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x110c, "Entered %s.\n", __func__); mcp->mb[0] = MBC_SET_PORT_CONFIG; /* Copy all bits to preserve original setting */ @@ -4365,8 +4140,7 @@ qla81xx_set_port_config(scsi_qla_host_t *vha, uint16_t *mb) ql_dbg(ql_dbg_mbx, vha, 0x110d, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110e, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x110e, "Done %s.\n", __func__); return rval; } @@ -4381,8 +4155,7 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, mbx_cmd_t *mcp = &mc; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x110f, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x110f, "Entered %s.\n", __func__); if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) return QLA_FUNCTION_FAILED; @@ -4410,8 +4183,7 @@ qla24xx_set_fcp_prio(scsi_qla_host_t *vha, uint16_t loop_id, uint16_t priority, if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x10cd, "Failed=%x.\n", rval); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10cc, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10cc, "Done %s.\n", __func__); } return rval; @@ -4424,8 +4196,7 @@ qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac) uint8_t byte; struct qla_hw_data *ha = vha->hw; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ca, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x10ca, "Entered %s.\n", __func__); /* Integer part */ rval = qla2x00_read_sfp(vha, 0, &byte, 0x98, 0x01, 1, BIT_13|BIT_0); @@ -4445,8 +4216,7 @@ qla2x00_get_thermal_temp(scsi_qla_host_t *vha, uint16_t *temp, uint16_t *frac) } *frac = (byte >> 6) * 25; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1018, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1018, "Done %s.\n", __func__); fail: return rval; } @@ -4459,8 +4229,7 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1017, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1017, "Entered %s.\n", __func__); if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; @@ -4479,8 +4248,7 @@ qla82xx_mbx_intr_enable(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x1016, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100e, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x100e, "Done %s.\n", __func__); } return rval; @@ -4494,8 +4262,7 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100d, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x100d, "Entered %s.\n", __func__); if (!IS_QLA82XX(ha)) return QLA_FUNCTION_FAILED; @@ -4514,8 +4281,7 @@ qla82xx_mbx_intr_disable(scsi_qla_host_t *vha) ql_dbg(ql_dbg_mbx, vha, 0x100c, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x100b, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x100b, "Done %s.\n", __func__); } return rval; @@ -4529,8 +4295,7 @@ qla82xx_md_get_template_size(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; int rval = QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111f, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x111f, "Entered %s.\n", __func__); memset(mcp->mb, 0 , sizeof(mcp->mb)); mcp->mb[0] = LSW(MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE); @@ -4553,8 +4318,7 @@ qla82xx_md_get_template_size(scsi_qla_host_t *vha) (mcp->mb[1] << 16) | mcp->mb[0], (mcp->mb[3] << 16) | mcp->mb[2]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1121, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1121, "Done %s.\n", __func__); ha->md_template_size = ((mcp->mb[3] << 16) | mcp->mb[2]); if (!ha->md_template_size) { ql_dbg(ql_dbg_mbx, vha, 0x1122, @@ -4573,8 +4337,7 @@ qla82xx_md_get_template(scsi_qla_host_t *vha) mbx_cmd_t *mcp = &mc; int rval = QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1123, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1123, "Entered %s.\n", __func__); ha->md_tmplt_hdr = dma_alloc_coherent(&ha->pdev->dev, ha->md_template_size, &ha->md_tmplt_hdr_dma, GFP_KERNEL); @@ -4609,8 +4372,7 @@ qla82xx_md_get_template(scsi_qla_host_t *vha) ((mcp->mb[1] << 16) | mcp->mb[0]), ((mcp->mb[3] << 16) | mcp->mb[2])); } else - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1126, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1126, "Done %s.\n", __func__); return rval; } @@ -4625,8 +4387,7 @@ qla81xx_set_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) return QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1133, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1133, "Entered %s.\n", __func__); memset(mcp, 0, sizeof(mbx_cmd_t)); mcp->mb[0] = MBC_SET_LED_CONFIG; @@ -4651,8 +4412,7 @@ qla81xx_set_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) ql_dbg(ql_dbg_mbx, vha, 0x1134, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1135, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1135, "Done %s.\n", __func__); } return rval; @@ -4669,8 +4429,7 @@ qla81xx_get_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) if (!IS_QLA81XX(ha) && !IS_QLA8031(ha)) return QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1136, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1136, "Entered %s.\n", __func__); memset(mcp, 0, sizeof(mbx_cmd_t)); mcp->mb[0] = MBC_GET_LED_CONFIG; @@ -4695,8 +4454,7 @@ qla81xx_get_led_config(scsi_qla_host_t *vha, uint16_t *led_cfg) led_cfg[4] = mcp->mb[5]; led_cfg[5] = mcp->mb[6]; } - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1138, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1138, "Done %s.\n", __func__); } return rval; @@ -4713,7 +4471,7 @@ qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable) if (!IS_QLA82XX(ha)) return QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1127, + ql_dbg(ql_dbg_mbx, vha, 0x1127, "Entered %s.\n", __func__); memset(mcp, 0, sizeof(mbx_cmd_t)); @@ -4733,7 +4491,7 @@ qla82xx_mbx_beacon_ctl(scsi_qla_host_t *vha, int enable) ql_dbg(ql_dbg_mbx, vha, 0x1128, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1129, + ql_dbg(ql_dbg_mbx, vha, 0x1129, "Done %s.\n", __func__); } @@ -4751,8 +4509,7 @@ qla83xx_write_remote_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data) if (!IS_QLA83XX(ha)) return QLA_FUNCTION_FAILED; - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130, - "Entered %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x1130, "Entered %s.\n", __func__); mcp->mb[0] = MBC_WRITE_REMOTE_REG; mcp->mb[1] = LSW(reg); @@ -4770,7 +4527,7 @@ qla83xx_write_remote_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data) ql_dbg(ql_dbg_mbx, vha, 0x1131, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); } else { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1132, + ql_dbg(ql_dbg_mbx, vha, 0x1132, "Done %s.\n", __func__); } @@ -4786,14 +4543,13 @@ qla2x00_port_logout(scsi_qla_host_t *vha, struct fc_port *fcport) mbx_cmd_t *mcp = &mc; if (IS_QLA2100(ha) || IS_QLA2200(ha)) { - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113b, + ql_dbg(ql_dbg_mbx, vha, 0x113b, "Implicit LOGO Unsupported.\n"); return QLA_FUNCTION_FAILED; } - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113c, - "Entering %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x113c, "Done %s.\n", __func__); /* Perform Implicit LOGO. */ mcp->mb[0] = MBC_PORT_LOGOUT; @@ -4808,8 +4564,7 @@ qla2x00_port_logout(scsi_qla_host_t *vha, struct fc_port *fcport) ql_dbg(ql_dbg_mbx, vha, 0x113d, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); else - ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x113e, - "Done %s.\n", __func__); + ql_dbg(ql_dbg_mbx, vha, 0x113e, "Done %s.\n", __func__); return rval; } diff --git a/trunk/drivers/scsi/qla2xxx/qla_mid.c b/trunk/drivers/scsi/qla2xxx/qla_mid.c index 3e8b32419e68..aa062a1b0ca4 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_mid.c +++ b/trunk/drivers/scsi/qla2xxx/qla_mid.c @@ -6,7 +6,6 @@ */ #include "qla_def.h" #include "qla_gbl.h" -#include "qla_target.h" #include #include @@ -50,9 +49,6 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) spin_lock_irqsave(&ha->vport_slock, flags); list_add_tail(&vha->list, &ha->vp_list); - - qlt_update_vp_map(vha, SET_VP_IDX); - spin_unlock_irqrestore(&ha->vport_slock, flags); mutex_unlock(&ha->vport_lock); @@ -83,7 +79,6 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) spin_lock_irqsave(&ha->vport_slock, flags); } list_del(&vha->list); - qlt_update_vp_map(vha, RESET_VP_IDX); spin_unlock_irqrestore(&ha->vport_slock, flags); vp_id = vha->vp_idx; @@ -139,7 +134,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) list_for_each_entry(fcport, &vha->vp_fcports, list) { ql_dbg(ql_dbg_vport, vha, 0xa001, "Marking port dead, loop_id=0x%04x : %x.\n", - fcport->loop_id, fcport->vha->vp_idx); + fcport->loop_id, fcport->vp_idx); qla2x00_mark_device_lost(vha, fcport, 0, 0); qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED); @@ -155,9 +150,6 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) atomic_set(&vha->loop_state, LOOP_DOWN); atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); - /* Remove port id from vp target map */ - qlt_update_vp_map(vha, RESET_AL_PA); - qla2x00_mark_vp_devices_dead(vha); atomic_set(&vha->vp_state, VP_FAILED); vha->flags.management_server_logged_in = 0; @@ -303,8 +295,10 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha) static int qla2x00_do_dpc_vp(scsi_qla_host_t *vha) { - ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x4012, - "Entering %s vp_flags: 0x%lx.\n", __func__, vha->vp_flags); + ql_dbg(ql_dbg_dpc, vha, 0x4012, + "Entering %s.\n", __func__); + ql_dbg(ql_dbg_dpc, vha, 0x4013, + "vp_flags: 0x%lx.\n", vha->vp_flags); qla2x00_do_work(vha); @@ -354,7 +348,7 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) } } - ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x401c, + ql_dbg(ql_dbg_dpc, vha, 0x401c, "Exiting %s.\n", __func__); return 0; } diff --git a/trunk/drivers/scsi/qla2xxx/qla_nx.c b/trunk/drivers/scsi/qla2xxx/qla_nx.c index caf627ba7fa8..de722a933438 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_nx.c +++ b/trunk/drivers/scsi/qla2xxx/qla_nx.c @@ -1190,12 +1190,12 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha) } /* Offset in flash = lower 16 bits - * Number of entries = upper 16 bits + * Number of enteries = upper 16 bits */ offset = n & 0xffffU; n = (n >> 16) & 0xffffU; - /* number of addr/value pair should not exceed 1024 entries */ + /* number of addr/value pair should not exceed 1024 enteries */ if (n >= 1024) { ql_log(ql_log_fatal, vha, 0x0071, "Card flash not initialized:n=0x%x.\n", n); @@ -2050,7 +2050,7 @@ qla82xx_intr_handler(int irq, void *dev_id) rsp = (struct rsp_que *) dev_id; if (!rsp) { - ql_log(ql_log_info, NULL, 0xb053, + ql_log(ql_log_info, NULL, 0xb054, "%s: NULL response queue pointer.\n", __func__); return IRQ_NONE; } @@ -2446,7 +2446,7 @@ qla82xx_load_fw(scsi_qla_host_t *vha) if (qla82xx_fw_load_from_flash(ha) == QLA_SUCCESS) { ql_log(ql_log_info, vha, 0x00a1, - "Firmware loaded successfully from flash.\n"); + "Firmware loaded successully from flash.\n"); return QLA_SUCCESS; } else { ql_log(ql_log_warn, vha, 0x0108, @@ -2461,7 +2461,7 @@ qla82xx_load_fw(scsi_qla_host_t *vha) blob = ha->hablob = qla2x00_request_firmware(vha); if (!blob) { ql_log(ql_log_fatal, vha, 0x00a3, - "Firmware image not present.\n"); + "Firmware image not preset.\n"); goto fw_load_failed; } @@ -2689,7 +2689,7 @@ qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr, if (!optrom) { ql_log(ql_log_warn, vha, 0xb01b, "Unable to allocate memory " - "for optrom burst write (%x KB).\n", + "for optron burst write (%x KB).\n", OPTROM_BURST_SIZE / 1024); } } @@ -2960,8 +2960,9 @@ qla82xx_need_qsnt_handler(scsi_qla_host_t *vha) * changing the state to DEV_READY */ ql_log(ql_log_info, vha, 0xb023, - "%s : QUIESCENT TIMEOUT DRV_ACTIVE:%d " - "DRV_STATE:%d.\n", QLA2XXX_DRIVER_NAME, + "%s : QUIESCENT TIMEOUT.\n", QLA2XXX_DRIVER_NAME); + ql_log(ql_log_info, vha, 0xb024, + "DRV_ACTIVE:%d DRV_STATE:%d.\n", drv_active, drv_state); qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY); @@ -3128,7 +3129,7 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha) if (ql2xmdenable) { if (qla82xx_md_collect(vha)) ql_log(ql_log_warn, vha, 0xb02c, - "Minidump not collected.\n"); + "Not able to collect minidump.\n"); } else ql_log(ql_log_warn, vha, 0xb04f, "Minidump disabled.\n"); @@ -3159,11 +3160,11 @@ qla82xx_check_md_needed(scsi_qla_host_t *vha) "Firmware version differs " "Previous version: %d:%d:%d - " "New version: %d:%d:%d\n", - fw_major_version, fw_minor_version, - fw_subminor_version, ha->fw_major_version, ha->fw_minor_version, - ha->fw_subminor_version); + ha->fw_subminor_version, + fw_major_version, fw_minor_version, + fw_subminor_version); /* Release MiniDump resources */ qla82xx_md_free(vha); /* ALlocate MiniDump resources */ @@ -3324,30 +3325,6 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha) return rval; } -static int qla82xx_check_temp(scsi_qla_host_t *vha) -{ - uint32_t temp, temp_state, temp_val; - struct qla_hw_data *ha = vha->hw; - - temp = qla82xx_rd_32(ha, CRB_TEMP_STATE); - temp_state = qla82xx_get_temp_state(temp); - temp_val = qla82xx_get_temp_val(temp); - - if (temp_state == QLA82XX_TEMP_PANIC) { - ql_log(ql_log_warn, vha, 0x600e, - "Device temperature %d degrees C exceeds " - " maximum allowed. Hardware has been shut down.\n", - temp_val); - return 1; - } else if (temp_state == QLA82XX_TEMP_WARN) { - ql_log(ql_log_warn, vha, 0x600f, - "Device temperature %d degrees C exceeds " - "operating range. Immediate action needed.\n", - temp_val); - } - return 0; -} - void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; @@ -3370,20 +3347,18 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) /* don't poll if reset is going on */ if (!ha->flags.isp82xx_reset_hdlr_active) { dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE); - if (qla82xx_check_temp(vha)) { - set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); - ha->flags.isp82xx_fw_hung = 1; - qla82xx_clear_pending_mbx(vha); - } else if (dev_state == QLA82XX_DEV_NEED_RESET && + if (dev_state == QLA82XX_DEV_NEED_RESET && !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) { ql_log(ql_log_warn, vha, 0x6001, "Adapter reset needed.\n"); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) { ql_log(ql_log_warn, vha, 0x6002, "Quiescent needed.\n"); set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); } else { if (qla82xx_check_fw_alive(vha)) { ql_dbg(ql_dbg_timer, vha, 0x6011, @@ -3423,6 +3398,7 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } + qla2xxx_wake_dpc(vha); ha->flags.isp82xx_fw_hung = 1; ql_log(ql_log_warn, vha, 0x6007, "Firmware hung.\n"); qla82xx_clear_pending_mbx(vha); @@ -4137,14 +4113,6 @@ qla82xx_md_collect(scsi_qla_host_t *vha) goto md_failed; } - if (ha->flags.isp82xx_no_md_cap) { - ql_log(ql_log_warn, vha, 0xb054, - "Forced reset from application, " - "ignore minidump capture\n"); - ha->flags.isp82xx_no_md_cap = 0; - goto md_failed; - } - if (qla82xx_validate_template_chksum(vha)) { ql_log(ql_log_info, vha, 0xb039, "Template checksum validation error\n"); diff --git a/trunk/drivers/scsi/qla2xxx/qla_nx.h b/trunk/drivers/scsi/qla2xxx/qla_nx.h index 6eb210e3cc63..4ac50e274661 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_nx.h +++ b/trunk/drivers/scsi/qla2xxx/qla_nx.h @@ -26,7 +26,6 @@ #define CRB_RCVPEG_STATE QLA82XX_REG(0x13c) #define BOOT_LOADER_DIMM_STATUS QLA82XX_REG(0x54) #define CRB_DMA_SHIFT QLA82XX_REG(0xcc) -#define CRB_TEMP_STATE QLA82XX_REG(0x1b4) #define QLA82XX_DMA_SHIFT_VALUE 0x55555555 #define QLA82XX_HW_H0_CH_HUB_ADR 0x05 @@ -562,6 +561,7 @@ #define QLA82XX_FW_VERSION_SUB (QLA82XX_CAM_RAM(0x158)) #define QLA82XX_PCIE_REG(reg) (QLA82XX_CRB_PCIE + (reg)) +#define PCIE_CHICKEN3 (0x120c8) #define PCIE_SETUP_FUNCTION (0x12040) #define PCIE_SETUP_FUNCTION2 (0x12048) @@ -1178,16 +1178,4 @@ static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC, #define CRB_NIU_XG_PAUSE_CTL_P0 0x1 #define CRB_NIU_XG_PAUSE_CTL_P1 0x8 -#define qla82xx_get_temp_val(x) ((x) >> 16) -#define qla82xx_get_temp_state(x) ((x) & 0xffff) -#define qla82xx_encode_temp(val, state) (((val) << 16) | (state)) - -/* - * Temperature control. - */ -enum { - QLA82XX_TEMP_NORMAL = 0x1, /* Normal operating range */ - QLA82XX_TEMP_WARN, /* Sound alert, temperature getting high */ - QLA82XX_TEMP_PANIC /* Fatal error, hardware has shut down. */ -}; #endif diff --git a/trunk/drivers/scsi/qla2xxx/qla_os.c b/trunk/drivers/scsi/qla2xxx/qla_os.c index 6d1d873a20e2..c9c56a8427f3 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_os.c +++ b/trunk/drivers/scsi/qla2xxx/qla_os.c @@ -13,13 +13,12 @@ #include #include #include + #include #include #include #include -#include "qla_target.h" - /* * Driver version */ @@ -41,12 +40,6 @@ static struct kmem_cache *ctx_cachep; */ int ql_errlev = ql_log_all; -int ql2xenableclass2; -module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR); -MODULE_PARM_DESC(ql2xenableclass2, - "Specify if Class 2 operations are supported from the very " - "beginning. Default is 0 - class 2 not supported."); - int ql2xlogintimeout = 20; module_param(ql2xlogintimeout, int, S_IRUGO); MODULE_PARM_DESC(ql2xlogintimeout, @@ -262,8 +255,6 @@ struct scsi_host_template qla2xxx_driver_template = { .max_sectors = 0xFFFF, .shost_attrs = qla2x00_host_attrs, - - .supported_mode = MODE_INITIATOR, }; static struct scsi_transport_template *qla2xxx_transport_template = NULL; @@ -315,8 +306,7 @@ static void qla2x00_free_fw_dump(struct qla_hw_data *); static void qla2x00_mem_free(struct qla_hw_data *); /* -------------------------------------------------------------------------- */ -static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, - struct rsp_que *rsp) +static int qla2x00_alloc_queues(struct qla_hw_data *ha) { scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues, @@ -334,12 +324,6 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, "Unable to allocate memory for response queue ptrs.\n"); goto fail_rsp_map; } - /* - * Make sure we record at least the request and response queue zero in - * case we need to free them if part of the probe fails. - */ - ha->rsp_q_map[0] = rsp; - ha->req_q_map[0] = req; set_bit(0, ha->rsp_qid_map); set_bit(0, ha->req_qid_map); return 1; @@ -658,12 +642,12 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) if (ha->flags.eeh_busy) { if (ha->flags.pci_channel_io_perm_failure) { - ql_dbg(ql_dbg_aer, vha, 0x9010, + ql_dbg(ql_dbg_io, vha, 0x3001, "PCI Channel IO permanent failure, exiting " "cmd=%p.\n", cmd); cmd->result = DID_NO_CONNECT << 16; } else { - ql_dbg(ql_dbg_aer, vha, 0x9011, + ql_dbg(ql_dbg_io, vha, 0x3002, "EEH_Busy, Requeuing the cmd=%p.\n", cmd); cmd->result = DID_REQUEUE << 16; } @@ -673,7 +657,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) rval = fc_remote_port_chkready(rport); if (rval) { cmd->result = rval; - ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3003, + ql_dbg(ql_dbg_io, vha, 0x3003, "fc_remote_port_chkready failed for cmd=%p, rval=0x%x.\n", cmd, rval); goto qc24_fail_command; @@ -1152,7 +1136,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) ret = FAILED; ql_log(ql_log_info, vha, 0x8012, - "BUS RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun); + "BUS RESET ISSUED nexus=%ld:%d%d.\n", vha->host_no, id, lun); if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { ql_log(ql_log_fatal, vha, 0x8013, @@ -2196,7 +2180,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql_dbg_pci(ql_dbg_init, pdev, 0x000a, "Memory allocated for ha=%p.\n", ha); ha->pdev = pdev; - ha->tgt.enable_class_2 = ql2xenableclass2; /* Clear our data area */ ha->bars = bars; @@ -2260,7 +2243,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->mbx_count = MAILBOX_REGISTER_COUNT; req_length = REQUEST_ENTRY_CNT_24XX; rsp_length = RESPONSE_ENTRY_CNT_2300; - ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; ha->max_loop_id = SNS_LAST_LOOP_ID_2300; ha->init_cb_size = sizeof(struct mid_init_cb_24xx); ha->gid_list_info_size = 8; @@ -2276,7 +2258,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->mbx_count = MAILBOX_REGISTER_COUNT; req_length = REQUEST_ENTRY_CNT_24XX; rsp_length = RESPONSE_ENTRY_CNT_2300; - ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; ha->max_loop_id = SNS_LAST_LOOP_ID_2300; ha->init_cb_size = sizeof(struct mid_init_cb_24xx); ha->gid_list_info_size = 8; @@ -2436,17 +2417,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->max_cmd_len, host->max_channel, host->max_lun, host->transportt, sht->vendor_id); -que_init: - /* Alloc arrays of request and response ring ptrs */ - if (!qla2x00_alloc_queues(ha, req, rsp)) { - ql_log(ql_log_fatal, base_vha, 0x003d, - "Failed to allocate memory for queue pointers..." - "aborting.\n"); - goto probe_init_failed; - } - - qlt_probe_one_stage1(base_vha, ha); - /* Set up the irqs */ ret = qla2x00_request_irqs(ha, rsp); if (ret) @@ -2454,10 +2424,20 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pci_save_state(pdev); - /* Assign back pointers */ + /* Alloc arrays of request and response ring ptrs */ +que_init: + if (!qla2x00_alloc_queues(ha)) { + ql_log(ql_log_fatal, base_vha, 0x003d, + "Failed to allocate memory for queue pointers.. aborting.\n"); + goto probe_init_failed; + } + + ha->rsp_q_map[0] = rsp; + ha->req_q_map[0] = req; rsp->req = req; req->rsp = rsp; - + set_bit(0, ha->req_qid_map); + set_bit(0, ha->rsp_qid_map); /* FWI2-capable only. */ req->req_q_in = &ha->iobase->isp24.req_q_in; req->req_q_out = &ha->iobase->isp24.req_q_out; @@ -2534,14 +2514,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql_dbg(ql_dbg_init, base_vha, 0x00ee, "DPC thread started successfully.\n"); - /* - * If we're not coming up in initiator mode, we might sit for - * a while without waking up the dpc thread, which leads to a - * stuck process warning. So just kick the dpc once here and - * let the kthread start (and go back to sleep in qla2x00_do_dpc). - */ - qla2xxx_wake_dpc(base_vha); - skip_dpc: list_add_tail(&base_vha->list, &ha->vp_list); base_vha->host->irq = ha->pdev->irq; @@ -2587,11 +2559,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql_dbg(ql_dbg_init, base_vha, 0x00f2, "Init done and hba is online.\n"); - if (qla_ini_mode_enabled(base_vha)) - scsi_scan_host(host); - else - ql_dbg(ql_dbg_init, base_vha, 0x0122, - "skipping scsi_scan_host() for non-initiator port\n"); + scsi_scan_host(host); qla2x00_alloc_sysfs_attr(base_vha); @@ -2609,17 +2577,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) base_vha->host_no, ha->isp_ops->fw_version_str(base_vha, fw_str)); - qlt_add_target(ha, base_vha); - return 0; probe_init_failed: qla2x00_free_req_que(ha, req); - ha->req_q_map[0] = NULL; - clear_bit(0, ha->req_qid_map); qla2x00_free_rsp_que(ha, rsp); - ha->rsp_q_map[0] = NULL; - clear_bit(0, ha->rsp_qid_map); ha->max_req_queues = ha->max_rsp_queues = 0; probe_failed: @@ -2658,22 +2620,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) return ret; } -static void -qla2x00_stop_dpc_thread(scsi_qla_host_t *vha) -{ - struct qla_hw_data *ha = vha->hw; - struct task_struct *t = ha->dpc_thread; - - if (ha->dpc_thread == NULL) - return; - /* - * qla2xxx_wake_dpc checks for ->dpc_thread - * so we need to zero it out. - */ - ha->dpc_thread = NULL; - kthread_stop(t); -} - static void qla2x00_shutdown(struct pci_dev *pdev) { @@ -2717,18 +2663,9 @@ qla2x00_remove_one(struct pci_dev *pdev) struct qla_hw_data *ha; unsigned long flags; - /* - * If the PCI device is disabled that means that probe failed and any - * resources should be have cleaned up on probe exit. - */ - if (!atomic_read(&pdev->enable_cnt)) - return; - base_vha = pci_get_drvdata(pdev); ha = base_vha->hw; - ha->flags.host_shutting_down = 1; - mutex_lock(&ha->vport_lock); while (ha->cur_vport_count) { struct Scsi_Host *scsi_host; @@ -2782,7 +2719,6 @@ qla2x00_remove_one(struct pci_dev *pdev) ha->dpc_thread = NULL; kthread_stop(t); } - qlt_remove_target(ha, base_vha); qla2x00_free_sysfs_attr(base_vha); @@ -2834,7 +2770,17 @@ qla2x00_free_device(scsi_qla_host_t *vha) if (vha->timer_active) qla2x00_stop_timer(vha); - qla2x00_stop_dpc_thread(vha); + /* Kill the kernel thread for this host */ + if (ha->dpc_thread) { + struct task_struct *t = ha->dpc_thread; + + /* + * qla2xxx_wake_dpc checks for ->dpc_thread + * so we need to zero it out. + */ + ha->dpc_thread = NULL; + kthread_stop(t); + } qla25xx_delete_queues(vha); @@ -2896,10 +2842,8 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport, spin_unlock_irqrestore(vha->host->host_lock, flags); set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); qla2xxx_wake_dpc(base_vha); - } else { + } else fc_remote_port_delete(rport); - qlt_fc_port_deleted(vha, fcport); - } } /* @@ -2915,7 +2859,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport, int do_login, int defer) { if (atomic_read(&fcport->state) == FCS_ONLINE && - vha->vp_idx == fcport->vha->vp_idx) { + vha->vp_idx == fcport->vp_idx) { qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); qla2x00_schedule_rport_del(vha, fcport, defer); } @@ -2964,7 +2908,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer) fc_port_t *fcport; list_for_each_entry(fcport, &vha->vp_fcports, list) { - if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx) + if (vha->vp_idx != 0 && vha->vp_idx != fcport->vp_idx) continue; /* @@ -2977,7 +2921,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer) qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); if (defer) qla2x00_schedule_rport_del(vha, fcport, defer); - else if (vha->vp_idx == fcport->vha->vp_idx) + else if (vha->vp_idx == fcport->vp_idx) qla2x00_schedule_rport_del(vha, fcport, defer); } } @@ -3002,13 +2946,10 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, if (!ha->init_cb) goto fail; - if (qlt_mem_alloc(ha) < 0) - goto fail_free_init_cb; - ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL); if (!ha->gid_list) - goto fail_free_tgt_mem; + goto fail_free_init_cb; ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); if (!ha->srb_mempool) @@ -3226,8 +3167,6 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, ha->gid_list_dma); ha->gid_list = NULL; ha->gid_list_dma = 0; -fail_free_tgt_mem: - qlt_mem_free(ha); fail_free_init_cb: dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, ha->init_cb_dma); @@ -3343,8 +3282,6 @@ qla2x00_mem_free(struct qla_hw_data *ha) if (ha->ctx_mempool) mempool_destroy(ha->ctx_mempool); - qlt_mem_free(ha); - if (ha->init_cb) dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, ha->init_cb_dma); @@ -3374,10 +3311,6 @@ qla2x00_mem_free(struct qla_hw_data *ha) ha->gid_list = NULL; ha->gid_list_dma = 0; - - ha->tgt.atio_ring = NULL; - ha->tgt.atio_dma = 0; - ha->tgt.tgt_vp_map = NULL; } struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, @@ -3738,9 +3671,10 @@ qla2x00_do_dpc(void *data) ha->dpc_active = 1; - ql_dbg(ql_dbg_dpc + ql_dbg_verbose, base_vha, 0x4001, - "DPC handler waking up, dpc_flags=0x%lx.\n", - base_vha->dpc_flags); + ql_dbg(ql_dbg_dpc, base_vha, 0x4001, + "DPC handler waking up.\n"); + ql_dbg(ql_dbg_dpc, base_vha, 0x4002, + "dpc_flags=0x%lx.\n", base_vha->dpc_flags); qla2x00_do_work(base_vha); @@ -3806,16 +3740,6 @@ qla2x00_do_dpc(void *data) clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); } - if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) { - int ret; - ret = qla2x00_send_change_request(base_vha, 0x3, 0); - if (ret != QLA_SUCCESS) - ql_log(ql_log_warn, base_vha, 0x121, - "Failed to enable receiving of RSCN " - "requests: 0x%x.\n", ret); - clear_bit(SCR_PENDING, &base_vha->dpc_flags); - } - if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { ql_dbg(ql_dbg_dpc, base_vha, 0x4009, "Quiescence mode scheduled.\n"); @@ -4533,21 +4457,6 @@ qla2x00_module_init(void) return -ENOMEM; } - /* Initialize target kmem_cache and mem_pools */ - ret = qlt_init(); - if (ret < 0) { - kmem_cache_destroy(srb_cachep); - return ret; - } else if (ret > 0) { - /* - * If initiator mode is explictly disabled by qlt_init(), - * prevent scsi_transport_fc.c:fc_scsi_scan_rport() from - * performing scsi_scan_target() during LOOP UP event. - */ - qla2xxx_transport_functions.disable_target_scan = 1; - qla2xxx_transport_vport_functions.disable_target_scan = 1; - } - /* Derive version string. */ strcpy(qla2x00_version_str, QLA2XXX_VERSION); if (ql2xextended_error_logging) @@ -4559,7 +4468,6 @@ qla2x00_module_init(void) kmem_cache_destroy(srb_cachep); ql_log(ql_log_fatal, NULL, 0x0002, "fc_attach_transport failed...Failing load!.\n"); - qlt_exit(); return -ENODEV; } @@ -4573,7 +4481,6 @@ qla2x00_module_init(void) fc_attach_transport(&qla2xxx_transport_vport_functions); if (!qla2xxx_transport_vport_template) { kmem_cache_destroy(srb_cachep); - qlt_exit(); fc_release_transport(qla2xxx_transport_template); ql_log(ql_log_fatal, NULL, 0x0004, "fc_attach_transport vport failed...Failing load!.\n"); @@ -4585,7 +4492,6 @@ qla2x00_module_init(void) ret = pci_register_driver(&qla2xxx_pci_driver); if (ret) { kmem_cache_destroy(srb_cachep); - qlt_exit(); fc_release_transport(qla2xxx_transport_template); fc_release_transport(qla2xxx_transport_vport_template); ql_log(ql_log_fatal, NULL, 0x0006, @@ -4605,7 +4511,6 @@ qla2x00_module_exit(void) pci_unregister_driver(&qla2xxx_pci_driver); qla2x00_release_firmware(); kmem_cache_destroy(srb_cachep); - qlt_exit(); if (ctx_cachep) kmem_cache_destroy(ctx_cachep); fc_release_transport(qla2xxx_transport_template); diff --git a/trunk/drivers/scsi/qla2xxx/qla_target.c b/trunk/drivers/scsi/qla2xxx/qla_target.c deleted file mode 100644 index 6986552b47e6..000000000000 --- a/trunk/drivers/scsi/qla2xxx/qla_target.c +++ /dev/null @@ -1,4972 +0,0 @@ -/* - * qla_target.c SCSI LLD infrastructure for QLogic 22xx/23xx/24xx/25xx - * - * based on qla2x00t.c code: - * - * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin - * Copyright (C) 2004 - 2005 Leonid Stoljar - * Copyright (C) 2006 Nathaniel Clark - * Copyright (C) 2006 - 2010 ID7 Ltd. - * - * Forward port and refactoring to modern qla2xxx and target/configfs - * - * Copyright (C) 2010-2011 Nicholas A. Bellinger - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, version 2 - * of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qla_def.h" -#include "qla_target.h" - -static char *qlini_mode = QLA2XXX_INI_MODE_STR_ENABLED; -module_param(qlini_mode, charp, S_IRUGO); -MODULE_PARM_DESC(qlini_mode, - "Determines when initiator mode will be enabled. Possible values: " - "\"exclusive\" - initiator mode will be enabled on load, " - "disabled on enabling target mode and then on disabling target mode " - "enabled back; " - "\"disabled\" - initiator mode will never be enabled; " - "\"enabled\" (default) - initiator mode will always stay enabled."); - -static int ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE; - -/* - * From scsi/fc/fc_fcp.h - */ -enum fcp_resp_rsp_codes { - FCP_TMF_CMPL = 0, - FCP_DATA_LEN_INVALID = 1, - FCP_CMND_FIELDS_INVALID = 2, - FCP_DATA_PARAM_MISMATCH = 3, - FCP_TMF_REJECTED = 4, - FCP_TMF_FAILED = 5, - FCP_TMF_INVALID_LUN = 9, -}; - -/* - * fc_pri_ta from scsi/fc/fc_fcp.h - */ -#define FCP_PTA_SIMPLE 0 /* simple task attribute */ -#define FCP_PTA_HEADQ 1 /* head of queue task attribute */ -#define FCP_PTA_ORDERED 2 /* ordered task attribute */ -#define FCP_PTA_ACA 4 /* auto. contigent allegiance */ -#define FCP_PTA_MASK 7 /* mask for task attribute field */ -#define FCP_PRI_SHIFT 3 /* priority field starts in bit 3 */ -#define FCP_PRI_RESVD_MASK 0x80 /* reserved bits in priority field */ - -/* - * This driver calls qla2x00_alloc_iocbs() and qla2x00_issue_marker(), which - * must be called under HW lock and could unlock/lock it inside. - * It isn't an issue, since in the current implementation on the time when - * those functions are called: - * - * - Either context is IRQ and only IRQ handler can modify HW data, - * including rings related fields, - * - * - Or access to target mode variables from struct qla_tgt doesn't - * cross those functions boundaries, except tgt_stop, which - * additionally protected by irq_cmd_count. - */ -/* Predefs for callbacks handed to qla2xxx LLD */ -static void qlt_24xx_atio_pkt(struct scsi_qla_host *ha, - struct atio_from_isp *pkt); -static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt); -static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, - int fn, void *iocb, int flags); -static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd - *cmd, struct atio_from_isp *atio, int ha_locked); -static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha, - struct qla_tgt_srr_imm *imm, int ha_lock); -/* - * Global Variables - */ -static struct kmem_cache *qla_tgt_cmd_cachep; -static struct kmem_cache *qla_tgt_mgmt_cmd_cachep; -static mempool_t *qla_tgt_mgmt_cmd_mempool; -static struct workqueue_struct *qla_tgt_wq; -static DEFINE_MUTEX(qla_tgt_mutex); -static LIST_HEAD(qla_tgt_glist); - -/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */ -static struct qla_tgt_sess *qlt_find_sess_by_port_name( - struct qla_tgt *tgt, - const uint8_t *port_name) -{ - struct qla_tgt_sess *sess; - - list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { - if (!memcmp(sess->port_name, port_name, WWN_SIZE)) - return sess; - } - - return NULL; -} - -/* Might release hw lock, then reaquire!! */ -static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked) -{ - /* Send marker if required */ - if (unlikely(vha->marker_needed != 0)) { - int rc = qla2x00_issue_marker(vha, vha_locked); - if (rc != QLA_SUCCESS) { - ql_dbg(ql_dbg_tgt, vha, 0xe03d, - "qla_target(%d): issue_marker() failed\n", - vha->vp_idx); - } - return rc; - } - return QLA_SUCCESS; -} - -static inline -struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha, - uint8_t *d_id) -{ - struct qla_hw_data *ha = vha->hw; - uint8_t vp_idx; - - if ((vha->d_id.b.area != d_id[1]) || (vha->d_id.b.domain != d_id[0])) - return NULL; - - if (vha->d_id.b.al_pa == d_id[2]) - return vha; - - BUG_ON(ha->tgt.tgt_vp_map == NULL); - vp_idx = ha->tgt.tgt_vp_map[d_id[2]].idx; - if (likely(test_bit(vp_idx, ha->vp_idx_map))) - return ha->tgt.tgt_vp_map[vp_idx].vha; - - return NULL; -} - -static inline -struct scsi_qla_host *qlt_find_host_by_vp_idx(struct scsi_qla_host *vha, - uint16_t vp_idx) -{ - struct qla_hw_data *ha = vha->hw; - - if (vha->vp_idx == vp_idx) - return vha; - - BUG_ON(ha->tgt.tgt_vp_map == NULL); - if (likely(test_bit(vp_idx, ha->vp_idx_map))) - return ha->tgt.tgt_vp_map[vp_idx].vha; - - return NULL; -} - -void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha, - struct atio_from_isp *atio) -{ - switch (atio->u.raw.entry_type) { - case ATIO_TYPE7: - { - struct scsi_qla_host *host = qlt_find_host_by_d_id(vha, - atio->u.isp24.fcp_hdr.d_id); - if (unlikely(NULL == host)) { - ql_dbg(ql_dbg_tgt, vha, 0xe03e, - "qla_target(%d): Received ATIO_TYPE7 " - "with unknown d_id %x:%x:%x\n", vha->vp_idx, - atio->u.isp24.fcp_hdr.d_id[0], - atio->u.isp24.fcp_hdr.d_id[1], - atio->u.isp24.fcp_hdr.d_id[2]); - break; - } - qlt_24xx_atio_pkt(host, atio); - break; - } - - case IMMED_NOTIFY_TYPE: - { - struct scsi_qla_host *host = vha; - struct imm_ntfy_from_isp *entry = - (struct imm_ntfy_from_isp *)atio; - - if ((entry->u.isp24.vp_index != 0xFF) && - (entry->u.isp24.nport_handle != 0xFFFF)) { - host = qlt_find_host_by_vp_idx(vha, - entry->u.isp24.vp_index); - if (unlikely(!host)) { - ql_dbg(ql_dbg_tgt, vha, 0xe03f, - "qla_target(%d): Received " - "ATIO (IMMED_NOTIFY_TYPE) " - "with unknown vp_index %d\n", - vha->vp_idx, entry->u.isp24.vp_index); - break; - } - } - qlt_24xx_atio_pkt(host, atio); - break; - } - - default: - ql_dbg(ql_dbg_tgt, vha, 0xe040, - "qla_target(%d): Received unknown ATIO atio " - "type %x\n", vha->vp_idx, atio->u.raw.entry_type); - break; - } - - return; -} - -void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) -{ - switch (pkt->entry_type) { - case CTIO_TYPE7: - { - struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt; - struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha, - entry->vp_index); - if (unlikely(!host)) { - ql_dbg(ql_dbg_tgt, vha, 0xe041, - "qla_target(%d): Response pkt (CTIO_TYPE7) " - "received, with unknown vp_index %d\n", - vha->vp_idx, entry->vp_index); - break; - } - qlt_response_pkt(host, pkt); - break; - } - - case IMMED_NOTIFY_TYPE: - { - struct scsi_qla_host *host = vha; - struct imm_ntfy_from_isp *entry = - (struct imm_ntfy_from_isp *)pkt; - - host = qlt_find_host_by_vp_idx(vha, entry->u.isp24.vp_index); - if (unlikely(!host)) { - ql_dbg(ql_dbg_tgt, vha, 0xe042, - "qla_target(%d): Response pkt (IMMED_NOTIFY_TYPE) " - "received, with unknown vp_index %d\n", - vha->vp_idx, entry->u.isp24.vp_index); - break; - } - qlt_response_pkt(host, pkt); - break; - } - - case NOTIFY_ACK_TYPE: - { - struct scsi_qla_host *host = vha; - struct nack_to_isp *entry = (struct nack_to_isp *)pkt; - - if (0xFF != entry->u.isp24.vp_index) { - host = qlt_find_host_by_vp_idx(vha, - entry->u.isp24.vp_index); - if (unlikely(!host)) { - ql_dbg(ql_dbg_tgt, vha, 0xe043, - "qla_target(%d): Response " - "pkt (NOTIFY_ACK_TYPE) " - "received, with unknown " - "vp_index %d\n", vha->vp_idx, - entry->u.isp24.vp_index); - break; - } - } - qlt_response_pkt(host, pkt); - break; - } - - case ABTS_RECV_24XX: - { - struct abts_recv_from_24xx *entry = - (struct abts_recv_from_24xx *)pkt; - struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha, - entry->vp_index); - if (unlikely(!host)) { - ql_dbg(ql_dbg_tgt, vha, 0xe044, - "qla_target(%d): Response pkt " - "(ABTS_RECV_24XX) received, with unknown " - "vp_index %d\n", vha->vp_idx, entry->vp_index); - break; - } - qlt_response_pkt(host, pkt); - break; - } - - case ABTS_RESP_24XX: - { - struct abts_resp_to_24xx *entry = - (struct abts_resp_to_24xx *)pkt; - struct scsi_qla_host *host = qlt_find_host_by_vp_idx(vha, - entry->vp_index); - if (unlikely(!host)) { - ql_dbg(ql_dbg_tgt, vha, 0xe045, - "qla_target(%d): Response pkt " - "(ABTS_RECV_24XX) received, with unknown " - "vp_index %d\n", vha->vp_idx, entry->vp_index); - break; - } - qlt_response_pkt(host, pkt); - break; - } - - default: - qlt_response_pkt(vha, pkt); - break; - } - -} - -static void qlt_free_session_done(struct work_struct *work) -{ - struct qla_tgt_sess *sess = container_of(work, struct qla_tgt_sess, - free_work); - struct qla_tgt *tgt = sess->tgt; - struct scsi_qla_host *vha = sess->vha; - struct qla_hw_data *ha = vha->hw; - - BUG_ON(!tgt); - /* - * Release the target session for FC Nexus from fabric module code. - */ - if (sess->se_sess != NULL) - ha->tgt.tgt_ops->free_session(sess); - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001, - "Unregistration of sess %p finished\n", sess); - - kfree(sess); - /* - * We need to protect against race, when tgt is freed before or - * inside wake_up() - */ - tgt->sess_count--; - if (tgt->sess_count == 0) - wake_up_all(&tgt->waitQ); -} - -/* ha->hardware_lock supposed to be held on entry */ -void qlt_unreg_sess(struct qla_tgt_sess *sess) -{ - struct scsi_qla_host *vha = sess->vha; - - vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); - - list_del(&sess->sess_list_entry); - if (sess->deleted) - list_del(&sess->del_list_entry); - - INIT_WORK(&sess->free_work, qlt_free_session_done); - schedule_work(&sess->free_work); -} -EXPORT_SYMBOL(qlt_unreg_sess); - -/* ha->hardware_lock supposed to be held on entry */ -static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_sess *sess = NULL; - uint32_t unpacked_lun, lun = 0; - uint16_t loop_id; - int res = 0; - struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb; - struct atio_from_isp *a = (struct atio_from_isp *)iocb; - - loop_id = le16_to_cpu(n->u.isp24.nport_handle); - if (loop_id == 0xFFFF) { -#if 0 /* FIXME: Re-enable Global event handling.. */ - /* Global event */ - atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count); - qlt_clear_tgt_db(ha->tgt.qla_tgt, 1); - if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { - sess = list_entry(ha->tgt.qla_tgt->sess_list.next, - typeof(*sess), sess_list_entry); - switch (mcmd) { - case QLA_TGT_NEXUS_LOSS_SESS: - mcmd = QLA_TGT_NEXUS_LOSS; - break; - case QLA_TGT_ABORT_ALL_SESS: - mcmd = QLA_TGT_ABORT_ALL; - break; - case QLA_TGT_NEXUS_LOSS: - case QLA_TGT_ABORT_ALL: - break; - default: - ql_dbg(ql_dbg_tgt, vha, 0xe046, - "qla_target(%d): Not allowed " - "command %x in %s", vha->vp_idx, - mcmd, __func__); - sess = NULL; - break; - } - } else - sess = NULL; -#endif - } else { - sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); - } - - ql_dbg(ql_dbg_tgt, vha, 0xe000, - "Using sess for qla_tgt_reset: %p\n", sess); - if (!sess) { - res = -ESRCH; - return res; - } - - ql_dbg(ql_dbg_tgt, vha, 0xe047, - "scsi(%ld): resetting (session %p from port " - "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, " - "mcmd %x, loop_id %d)\n", vha->host_no, sess, - sess->port_name[0], sess->port_name[1], - sess->port_name[2], sess->port_name[3], - sess->port_name[4], sess->port_name[5], - sess->port_name[6], sess->port_name[7], - mcmd, loop_id); - - lun = a->u.isp24.fcp_cmnd.lun; - unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); - - return qlt_issue_task_mgmt(sess, unpacked_lun, mcmd, - iocb, QLA24XX_MGMT_SEND_NACK); -} - -/* ha->hardware_lock supposed to be held on entry */ -static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, - bool immediate) -{ - struct qla_tgt *tgt = sess->tgt; - uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5; - - if (sess->deleted) - return; - - ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, - "Scheduling sess %p for deletion\n", sess); - list_add_tail(&sess->del_list_entry, &tgt->del_sess_list); - sess->deleted = 1; - - if (immediate) - dev_loss_tmo = 0; - - sess->expires = jiffies + dev_loss_tmo * HZ; - - ql_dbg(ql_dbg_tgt, sess->vha, 0xe048, - "qla_target(%d): session for port %02x:%02x:%02x:" - "%02x:%02x:%02x:%02x:%02x (loop ID %d) scheduled for " - "deletion in %u secs (expires: %lu) immed: %d\n", - sess->vha->vp_idx, - sess->port_name[0], sess->port_name[1], - sess->port_name[2], sess->port_name[3], - sess->port_name[4], sess->port_name[5], - sess->port_name[6], sess->port_name[7], - sess->loop_id, dev_loss_tmo, sess->expires, immediate); - - if (immediate) - schedule_delayed_work(&tgt->sess_del_work, 0); - else - schedule_delayed_work(&tgt->sess_del_work, - jiffies - sess->expires); -} - -/* ha->hardware_lock supposed to be held on entry */ -static void qlt_clear_tgt_db(struct qla_tgt *tgt, bool local_only) -{ - struct qla_tgt_sess *sess; - - list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) - qlt_schedule_sess_for_deletion(sess, true); - - /* At this point tgt could be already dead */ -} - -static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, - uint16_t *loop_id) -{ - struct qla_hw_data *ha = vha->hw; - dma_addr_t gid_list_dma; - struct gid_list_info *gid_list; - char *id_iter; - int res, rc, i; - uint16_t entries; - - gid_list = dma_alloc_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), - &gid_list_dma, GFP_KERNEL); - if (!gid_list) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf044, - "qla_target(%d): DMA Alloc failed of %u\n", - vha->vp_idx, qla2x00_gid_list_size(ha)); - return -ENOMEM; - } - - /* Get list of logged in devices */ - rc = qla2x00_get_id_list(vha, gid_list, gid_list_dma, &entries); - if (rc != QLA_SUCCESS) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf045, - "qla_target(%d): get_id_list() failed: %x\n", - vha->vp_idx, rc); - res = -1; - goto out_free_id_list; - } - - id_iter = (char *)gid_list; - res = -1; - for (i = 0; i < entries; i++) { - struct gid_list_info *gid = (struct gid_list_info *)id_iter; - if ((gid->al_pa == s_id[2]) && - (gid->area == s_id[1]) && - (gid->domain == s_id[0])) { - *loop_id = le16_to_cpu(gid->loop_id); - res = 0; - break; - } - id_iter += ha->gid_list_info_size; - } - -out_free_id_list: - dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), - gid_list, gid_list_dma); - return res; -} - -static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, - struct qla_tgt_sess *sess) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_port_24xx_data *pmap24; - bool res, found = false; - int rc, i; - uint16_t loop_id = 0xFFFF; /* to eliminate compiler's warning */ - uint16_t entries; - void *pmap; - int pmap_len; - fc_port_t *fcport; - int global_resets; - -retry: - global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); - - rc = qla2x00_get_node_name_list(vha, &pmap, &pmap_len); - if (rc != QLA_SUCCESS) { - res = false; - goto out; - } - - pmap24 = pmap; - entries = pmap_len/sizeof(*pmap24); - - for (i = 0; i < entries; ++i) { - if (!memcmp(sess->port_name, pmap24[i].port_name, WWN_SIZE)) { - loop_id = le16_to_cpu(pmap24[i].loop_id); - found = true; - break; - } - } - - kfree(pmap); - - if (!found) { - res = false; - goto out; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf046, - "qlt_check_fcport_exist(): loop_id %d", loop_id); - - fcport = kzalloc(sizeof(*fcport), GFP_KERNEL); - if (fcport == NULL) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf047, - "qla_target(%d): Allocation of tmp FC port failed", - vha->vp_idx); - res = false; - goto out; - } - - fcport->loop_id = loop_id; - - rc = qla2x00_get_port_database(vha, fcport, 0); - if (rc != QLA_SUCCESS) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf048, - "qla_target(%d): Failed to retrieve fcport " - "information -- get_port_database() returned %x " - "(loop_id=0x%04x)", vha->vp_idx, rc, loop_id); - res = false; - goto out_free_fcport; - } - - if (global_resets != - atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf002, - "qla_target(%d): global reset during session discovery" - " (counter was %d, new %d), retrying", - vha->vp_idx, global_resets, - atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)); - goto retry; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003, - "Updating sess %p s_id %x:%x:%x, loop_id %d) to d_id %x:%x:%x, " - "loop_id %d", sess, sess->s_id.b.domain, sess->s_id.b.al_pa, - sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain, - fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); - - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); - - res = true; - -out_free_fcport: - kfree(fcport); - -out: - return res; -} - -/* ha->hardware_lock supposed to be held on entry */ -static void qlt_undelete_sess(struct qla_tgt_sess *sess) -{ - BUG_ON(!sess->deleted); - - list_del(&sess->del_list_entry); - sess->deleted = 0; -} - -static void qlt_del_sess_work_fn(struct delayed_work *work) -{ - struct qla_tgt *tgt = container_of(work, struct qla_tgt, - sess_del_work); - struct scsi_qla_host *vha = tgt->vha; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_sess *sess; - unsigned long flags; - - spin_lock_irqsave(&ha->hardware_lock, flags); - while (!list_empty(&tgt->del_sess_list)) { - sess = list_entry(tgt->del_sess_list.next, typeof(*sess), - del_list_entry); - if (time_after_eq(jiffies, sess->expires)) { - bool cancel; - - qlt_undelete_sess(sess); - - spin_unlock_irqrestore(&ha->hardware_lock, flags); - cancel = qlt_check_fcport_exist(vha, sess); - - if (cancel) { - if (sess->deleted) { - /* - * sess was again deleted while we were - * discovering it - */ - spin_lock_irqsave(&ha->hardware_lock, - flags); - continue; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf049, - "qla_target(%d): cancel deletion of " - "session for port %02x:%02x:%02x:%02x:%02x:" - "%02x:%02x:%02x (loop ID %d), because " - " it isn't deleted by firmware", - vha->vp_idx, sess->port_name[0], - sess->port_name[1], sess->port_name[2], - sess->port_name[3], sess->port_name[4], - sess->port_name[5], sess->port_name[6], - sess->port_name[7], sess->loop_id); - } else { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, - "Timeout: sess %p about to be deleted\n", - sess); - ha->tgt.tgt_ops->shutdown_sess(sess); - ha->tgt.tgt_ops->put_sess(sess); - } - - spin_lock_irqsave(&ha->hardware_lock, flags); - } else { - schedule_delayed_work(&tgt->sess_del_work, - jiffies - sess->expires); - break; - } - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - -/* - * Adds an extra ref to allow to drop hw lock after adding sess to the list. - * Caller must put it. - */ -static struct qla_tgt_sess *qlt_create_sess( - struct scsi_qla_host *vha, - fc_port_t *fcport, - bool local) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_sess *sess; - unsigned long flags; - unsigned char be_sid[3]; - - /* Check to avoid double sessions */ - spin_lock_irqsave(&ha->hardware_lock, flags); - list_for_each_entry(sess, &ha->tgt.qla_tgt->sess_list, - sess_list_entry) { - if (!memcmp(sess->port_name, fcport->port_name, WWN_SIZE)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf005, - "Double sess %p found (s_id %x:%x:%x, " - "loop_id %d), updating to d_id %x:%x:%x, " - "loop_id %d", sess, sess->s_id.b.domain, - sess->s_id.b.al_pa, sess->s_id.b.area, - sess->loop_id, fcport->d_id.b.domain, - fcport->d_id.b.al_pa, fcport->d_id.b.area, - fcport->loop_id); - - if (sess->deleted) - qlt_undelete_sess(sess); - - kref_get(&sess->se_sess->sess_kref); - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); - if (sess->local && !local) - sess->local = 0; - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return sess; - } - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - sess = kzalloc(sizeof(*sess), GFP_KERNEL); - if (!sess) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04a, - "qla_target(%u): session allocation failed, " - "all commands from port %02x:%02x:%02x:%02x:" - "%02x:%02x:%02x:%02x will be refused", vha->vp_idx, - fcport->port_name[0], fcport->port_name[1], - fcport->port_name[2], fcport->port_name[3], - fcport->port_name[4], fcport->port_name[5], - fcport->port_name[6], fcport->port_name[7]); - - return NULL; - } - sess->tgt = ha->tgt.qla_tgt; - sess->vha = vha; - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->local = local; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006, - "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", - sess, ha->tgt.qla_tgt); - - be_sid[0] = sess->s_id.b.domain; - be_sid[1] = sess->s_id.b.area; - be_sid[2] = sess->s_id.b.al_pa; - /* - * Determine if this fc_port->port_name is allowed to access - * target mode using explict NodeACLs+MappedLUNs, or using - * TPG demo mode. If this is successful a target mode FC nexus - * is created. - */ - if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, - &fcport->port_name[0], sess, &be_sid[0], fcport->loop_id) < 0) { - kfree(sess); - return NULL; - } - /* - * Take an extra reference to ->sess_kref here to handle qla_tgt_sess - * access across ->hardware_lock reaquire. - */ - kref_get(&sess->se_sess->sess_kref); - - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); - BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); - memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); - - spin_lock_irqsave(&ha->hardware_lock, flags); - list_add_tail(&sess->sess_list_entry, &ha->tgt.qla_tgt->sess_list); - ha->tgt.qla_tgt->sess_count++; - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, - "qla_target(%d): %ssession for wwn %02x:%02x:%02x:%02x:" - "%02x:%02x:%02x:%02x (loop_id %d, s_id %x:%x:%x, confirmed" - " completion %ssupported) added\n", - vha->vp_idx, local ? "local " : "", fcport->port_name[0], - fcport->port_name[1], fcport->port_name[2], fcport->port_name[3], - fcport->port_name[4], fcport->port_name[5], fcport->port_name[6], - fcport->port_name[7], fcport->loop_id, sess->s_id.b.domain, - sess->s_id.b.area, sess->s_id.b.al_pa, sess->conf_compl_supported ? - "" : "not "); - - return sess; -} - -/* - * Called from drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port() - */ -void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - struct qla_tgt_sess *sess; - unsigned long flags; - - if (!vha->hw->tgt.tgt_ops) - return; - - if (!tgt || (fcport->port_type != FCT_INITIATOR)) - return; - - spin_lock_irqsave(&ha->hardware_lock, flags); - if (tgt->tgt_stop) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); - return; - } - sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); - if (!sess) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - mutex_lock(&ha->tgt.tgt_mutex); - sess = qlt_create_sess(vha, fcport, false); - mutex_unlock(&ha->tgt.tgt_mutex); - - spin_lock_irqsave(&ha->hardware_lock, flags); - } else { - kref_get(&sess->se_sess->sess_kref); - - if (sess->deleted) { - qlt_undelete_sess(sess); - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04c, - "qla_target(%u): %ssession for port %02x:" - "%02x:%02x:%02x:%02x:%02x:%02x:%02x (loop ID %d) " - "reappeared\n", vha->vp_idx, sess->local ? "local " - : "", sess->port_name[0], sess->port_name[1], - sess->port_name[2], sess->port_name[3], - sess->port_name[4], sess->port_name[5], - sess->port_name[6], sess->port_name[7], - sess->loop_id); - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007, - "Reappeared sess %p\n", sess); - } - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); - } - - if (sess && sess->local) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04d, - "qla_target(%u): local session for " - "port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " - "(loop ID %d) became global\n", vha->vp_idx, - fcport->port_name[0], fcport->port_name[1], - fcport->port_name[2], fcport->port_name[3], - fcport->port_name[4], fcport->port_name[5], - fcport->port_name[6], fcport->port_name[7], - sess->loop_id); - sess->local = 0; - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - ha->tgt.tgt_ops->put_sess(sess); -} - -void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - struct qla_tgt_sess *sess; - unsigned long flags; - - if (!vha->hw->tgt.tgt_ops) - return; - - if (!tgt || (fcport->port_type != FCT_INITIATOR)) - return; - - spin_lock_irqsave(&ha->hardware_lock, flags); - if (tgt->tgt_stop) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); - return; - } - sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); - if (!sess) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); - return; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf008, "qla_tgt_fc_port_deleted %p", sess); - - sess->local = 1; - qlt_schedule_sess_for_deletion(sess, false); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - -static inline int test_tgt_sess_count(struct qla_tgt *tgt) -{ - struct qla_hw_data *ha = tgt->ha; - unsigned long flags; - int res; - /* - * We need to protect against race, when tgt is freed before or - * inside wake_up() - */ - spin_lock_irqsave(&ha->hardware_lock, flags); - ql_dbg(ql_dbg_tgt, tgt->vha, 0xe002, - "tgt %p, empty(sess_list)=%d sess_count=%d\n", - tgt, list_empty(&tgt->sess_list), tgt->sess_count); - res = (tgt->sess_count == 0); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return res; -} - -/* Called by tcm_qla2xxx configfs code */ -void qlt_stop_phase1(struct qla_tgt *tgt) -{ - struct scsi_qla_host *vha = tgt->vha; - struct qla_hw_data *ha = tgt->ha; - unsigned long flags; - - if (tgt->tgt_stop || tgt->tgt_stopped) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04e, - "Already in tgt->tgt_stop or tgt_stopped state\n"); - dump_stack(); - return; - } - - ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n", - vha->host_no, vha); - /* - * Mutex needed to sync with qla_tgt_fc_port_[added,deleted]. - * Lock is needed, because we still can get an incoming packet. - */ - mutex_lock(&ha->tgt.tgt_mutex); - spin_lock_irqsave(&ha->hardware_lock, flags); - tgt->tgt_stop = 1; - qlt_clear_tgt_db(tgt, true); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - mutex_unlock(&ha->tgt.tgt_mutex); - - flush_delayed_work_sync(&tgt->sess_del_work); - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf009, - "Waiting for sess works (tgt %p)", tgt); - spin_lock_irqsave(&tgt->sess_work_lock, flags); - while (!list_empty(&tgt->sess_works_list)) { - spin_unlock_irqrestore(&tgt->sess_work_lock, flags); - flush_scheduled_work(); - spin_lock_irqsave(&tgt->sess_work_lock, flags); - } - spin_unlock_irqrestore(&tgt->sess_work_lock, flags); - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00a, - "Waiting for tgt %p: list_empty(sess_list)=%d " - "sess_count=%d\n", tgt, list_empty(&tgt->sess_list), - tgt->sess_count); - - wait_event(tgt->waitQ, test_tgt_sess_count(tgt)); - - /* Big hammer */ - if (!ha->flags.host_shutting_down && qla_tgt_mode_enabled(vha)) - qlt_disable_vha(vha); - - /* Wait for sessions to clear out (just in case) */ - wait_event(tgt->waitQ, test_tgt_sess_count(tgt)); -} -EXPORT_SYMBOL(qlt_stop_phase1); - -/* Called by tcm_qla2xxx configfs code */ -void qlt_stop_phase2(struct qla_tgt *tgt) -{ - struct qla_hw_data *ha = tgt->ha; - unsigned long flags; - - if (tgt->tgt_stopped) { - ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf04f, - "Already in tgt->tgt_stopped state\n"); - dump_stack(); - return; - } - - ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00b, - "Waiting for %d IRQ commands to complete (tgt %p)", - tgt->irq_cmd_count, tgt); - - mutex_lock(&ha->tgt.tgt_mutex); - spin_lock_irqsave(&ha->hardware_lock, flags); - while (tgt->irq_cmd_count != 0) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); - udelay(2); - spin_lock_irqsave(&ha->hardware_lock, flags); - } - tgt->tgt_stop = 0; - tgt->tgt_stopped = 1; - spin_unlock_irqrestore(&ha->hardware_lock, flags); - mutex_unlock(&ha->tgt.tgt_mutex); - - ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00c, "Stop of tgt %p finished", - tgt); -} -EXPORT_SYMBOL(qlt_stop_phase2); - -/* Called from qlt_remove_target() -> qla2x00_remove_one() */ -void qlt_release(struct qla_tgt *tgt) -{ - struct qla_hw_data *ha = tgt->ha; - - if ((ha->tgt.qla_tgt != NULL) && !tgt->tgt_stopped) - qlt_stop_phase2(tgt); - - ha->tgt.qla_tgt = NULL; - - ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00d, - "Release of tgt %p finished\n", tgt); - - kfree(tgt); -} - -/* ha->hardware_lock supposed to be held on entry */ -static int qlt_sched_sess_work(struct qla_tgt *tgt, int type, - const void *param, unsigned int param_size) -{ - struct qla_tgt_sess_work_param *prm; - unsigned long flags; - - prm = kzalloc(sizeof(*prm), GFP_ATOMIC); - if (!prm) { - ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf050, - "qla_target(%d): Unable to create session " - "work, command will be refused", 0); - return -ENOMEM; - } - - ql_dbg(ql_dbg_tgt_mgt, tgt->vha, 0xf00e, - "Scheduling work (type %d, prm %p)" - " to find session for param %p (size %d, tgt %p)\n", - type, prm, param, param_size, tgt); - - prm->type = type; - memcpy(&prm->tm_iocb, param, param_size); - - spin_lock_irqsave(&tgt->sess_work_lock, flags); - list_add_tail(&prm->sess_works_list_entry, &tgt->sess_works_list); - spin_unlock_irqrestore(&tgt->sess_work_lock, flags); - - schedule_work(&tgt->sess_work); - - return 0; -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static void qlt_send_notify_ack(struct scsi_qla_host *vha, - struct imm_ntfy_from_isp *ntfy, - uint32_t add_flags, uint16_t resp_code, int resp_code_valid, - uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan) -{ - struct qla_hw_data *ha = vha->hw; - request_t *pkt; - struct nack_to_isp *nack; - - ql_dbg(ql_dbg_tgt, vha, 0xe004, "Sending NOTIFY_ACK (ha=%p)\n", ha); - - /* Send marker if required */ - if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) - return; - - pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); - if (!pkt) { - ql_dbg(ql_dbg_tgt, vha, 0xe049, - "qla_target(%d): %s failed: unable to allocate " - "request packet\n", vha->vp_idx, __func__); - return; - } - - if (ha->tgt.qla_tgt != NULL) - ha->tgt.qla_tgt->notify_ack_expected++; - - pkt->entry_type = NOTIFY_ACK_TYPE; - pkt->entry_count = 1; - - nack = (struct nack_to_isp *)pkt; - nack->ox_id = ntfy->ox_id; - - nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle; - if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) { - nack->u.isp24.flags = ntfy->u.isp24.flags & - __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB); - } - nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id; - nack->u.isp24.status = ntfy->u.isp24.status; - nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode; - nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address; - nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs; - nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui; - nack->u.isp24.srr_flags = cpu_to_le16(srr_flags); - nack->u.isp24.srr_reject_code = srr_reject_code; - nack->u.isp24.srr_reject_code_expl = srr_explan; - nack->u.isp24.vp_index = ntfy->u.isp24.vp_index; - - ql_dbg(ql_dbg_tgt, vha, 0xe005, - "qla_target(%d): Sending 24xx Notify Ack %d\n", - vha->vp_idx, nack->u.isp24.status); - - qla2x00_start_iocbs(vha, vha->req); -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static void qlt_24xx_send_abts_resp(struct scsi_qla_host *vha, - struct abts_recv_from_24xx *abts, uint32_t status, - bool ids_reversed) -{ - struct qla_hw_data *ha = vha->hw; - struct abts_resp_to_24xx *resp; - uint32_t f_ctl; - uint8_t *p; - - ql_dbg(ql_dbg_tgt, vha, 0xe006, - "Sending task mgmt ABTS response (ha=%p, atio=%p, status=%x\n", - ha, abts, status); - - /* Send marker if required */ - if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) - return; - - resp = (struct abts_resp_to_24xx *)qla2x00_alloc_iocbs(vha, NULL); - if (!resp) { - ql_dbg(ql_dbg_tgt, vha, 0xe04a, - "qla_target(%d): %s failed: unable to allocate " - "request packet", vha->vp_idx, __func__); - return; - } - - resp->entry_type = ABTS_RESP_24XX; - resp->entry_count = 1; - resp->nport_handle = abts->nport_handle; - resp->vp_index = vha->vp_idx; - resp->sof_type = abts->sof_type; - resp->exchange_address = abts->exchange_address; - resp->fcp_hdr_le = abts->fcp_hdr_le; - f_ctl = __constant_cpu_to_le32(F_CTL_EXCH_CONTEXT_RESP | - F_CTL_LAST_SEQ | F_CTL_END_SEQ | - F_CTL_SEQ_INITIATIVE); - p = (uint8_t *)&f_ctl; - resp->fcp_hdr_le.f_ctl[0] = *p++; - resp->fcp_hdr_le.f_ctl[1] = *p++; - resp->fcp_hdr_le.f_ctl[2] = *p; - if (ids_reversed) { - resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.d_id[0]; - resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.d_id[1]; - resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.d_id[2]; - resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.s_id[0]; - resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.s_id[1]; - resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.s_id[2]; - } else { - resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0]; - resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1]; - resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2]; - resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0]; - resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1]; - resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2]; - } - resp->exchange_addr_to_abort = abts->exchange_addr_to_abort; - if (status == FCP_TMF_CMPL) { - resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_ACC; - resp->payload.ba_acct.seq_id_valid = SEQ_ID_INVALID; - resp->payload.ba_acct.low_seq_cnt = 0x0000; - resp->payload.ba_acct.high_seq_cnt = 0xFFFF; - resp->payload.ba_acct.ox_id = abts->fcp_hdr_le.ox_id; - resp->payload.ba_acct.rx_id = abts->fcp_hdr_le.rx_id; - } else { - resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_RJT; - resp->payload.ba_rjt.reason_code = - BA_RJT_REASON_CODE_UNABLE_TO_PERFORM; - /* Other bytes are zero */ - } - - ha->tgt.qla_tgt->abts_resp_expected++; - - qla2x00_start_iocbs(vha, vha->req); -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, - struct abts_resp_from_24xx_fw *entry) -{ - struct ctio7_to_24xx *ctio; - - ql_dbg(ql_dbg_tgt, vha, 0xe007, - "Sending retry TERM EXCH CTIO7 (ha=%p)\n", vha->hw); - /* Send marker if required */ - if (qlt_issue_marker(vha, 1) != QLA_SUCCESS) - return; - - ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(vha, NULL); - if (ctio == NULL) { - ql_dbg(ql_dbg_tgt, vha, 0xe04b, - "qla_target(%d): %s failed: unable to allocate " - "request packet\n", vha->vp_idx, __func__); - return; - } - - /* - * We've got on entrance firmware's response on by us generated - * ABTS response. So, in it ID fields are reversed. - */ - - ctio->entry_type = CTIO_TYPE7; - ctio->entry_count = 1; - ctio->nport_handle = entry->nport_handle; - ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; - ctio->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); - ctio->vp_index = vha->vp_idx; - ctio->initiator_id[0] = entry->fcp_hdr_le.d_id[0]; - ctio->initiator_id[1] = entry->fcp_hdr_le.d_id[1]; - ctio->initiator_id[2] = entry->fcp_hdr_le.d_id[2]; - ctio->exchange_addr = entry->exchange_addr_to_abort; - ctio->u.status1.flags = - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | - CTIO7_FLAGS_TERMINATE); - ctio->u.status1.ox_id = entry->fcp_hdr_le.ox_id; - - qla2x00_start_iocbs(vha, vha->req); - - qlt_24xx_send_abts_resp(vha, (struct abts_recv_from_24xx *)entry, - FCP_TMF_CMPL, true); -} - -/* ha->hardware_lock supposed to be held on entry */ -static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, - struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_mgmt_cmd *mcmd; - int rc; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, - "qla_target(%d): task abort (tag=%d)\n", - vha->vp_idx, abts->exchange_addr_to_abort); - - mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC); - if (mcmd == NULL) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf051, - "qla_target(%d): %s: Allocation of ABORT cmd failed", - vha->vp_idx, __func__); - return -ENOMEM; - } - memset(mcmd, 0, sizeof(*mcmd)); - - mcmd->sess = sess; - memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); - - rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, TMR_ABORT_TASK, - abts->exchange_addr_to_abort); - if (rc != 0) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, - "qla_target(%d): tgt_ops->handle_tmr()" - " failed: %d", vha->vp_idx, rc); - mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); - return -EFAULT; - } - - return 0; -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, - struct abts_recv_from_24xx *abts) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_sess *sess; - uint32_t tag = abts->exchange_addr_to_abort; - uint8_t s_id[3]; - int rc; - - if (le32_to_cpu(abts->fcp_hdr_le.parameter) & ABTS_PARAM_ABORT_SEQ) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf053, - "qla_target(%d): ABTS: Abort Sequence not " - "supported\n", vha->vp_idx); - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); - return; - } - - if (tag == ATIO_EXCHANGE_ADDRESS_UNKNOWN) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf010, - "qla_target(%d): ABTS: Unknown Exchange " - "Address received\n", vha->vp_idx); - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); - return; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf011, - "qla_target(%d): task abort (s_id=%x:%x:%x, " - "tag=%d, param=%x)\n", vha->vp_idx, abts->fcp_hdr_le.s_id[2], - abts->fcp_hdr_le.s_id[1], abts->fcp_hdr_le.s_id[0], tag, - le32_to_cpu(abts->fcp_hdr_le.parameter)); - - s_id[0] = abts->fcp_hdr_le.s_id[2]; - s_id[1] = abts->fcp_hdr_le.s_id[1]; - s_id[2] = abts->fcp_hdr_le.s_id[0]; - - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); - if (!sess) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf012, - "qla_target(%d): task abort for non-existant session\n", - vha->vp_idx); - rc = qlt_sched_sess_work(ha->tgt.qla_tgt, - QLA_TGT_SESS_WORK_ABORT, abts, sizeof(*abts)); - if (rc != 0) { - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, - false); - } - return; - } - - rc = __qlt_24xx_handle_abts(vha, abts, sess); - if (rc != 0) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054, - "qla_target(%d): __qlt_24xx_handle_abts() failed: %d\n", - vha->vp_idx, rc); - qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); - return; - } -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static void qlt_24xx_send_task_mgmt_ctio(struct scsi_qla_host *ha, - struct qla_tgt_mgmt_cmd *mcmd, uint32_t resp_code) -{ - struct atio_from_isp *atio = &mcmd->orig_iocb.atio; - struct ctio7_to_24xx *ctio; - - ql_dbg(ql_dbg_tgt, ha, 0xe008, - "Sending task mgmt CTIO7 (ha=%p, atio=%p, resp_code=%x\n", - ha, atio, resp_code); - - /* Send marker if required */ - if (qlt_issue_marker(ha, 1) != QLA_SUCCESS) - return; - - ctio = (struct ctio7_to_24xx *)qla2x00_alloc_iocbs(ha, NULL); - if (ctio == NULL) { - ql_dbg(ql_dbg_tgt, ha, 0xe04c, - "qla_target(%d): %s failed: unable to allocate " - "request packet\n", ha->vp_idx, __func__); - return; - } - - ctio->entry_type = CTIO_TYPE7; - ctio->entry_count = 1; - ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; - ctio->nport_handle = mcmd->sess->loop_id; - ctio->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); - ctio->vp_index = ha->vp_idx; - ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; - ctio->exchange_addr = atio->u.isp24.exchange_addr; - ctio->u.status1.flags = (atio->u.isp24.attr << 9) | - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | - CTIO7_FLAGS_SEND_STATUS); - ctio->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); - ctio->u.status1.scsi_status = - __constant_cpu_to_le16(SS_RESPONSE_INFO_LEN_VALID); - ctio->u.status1.response_len = __constant_cpu_to_le16(8); - ((uint32_t *)ctio->u.status1.sense_data)[0] = cpu_to_be32(resp_code); - - qla2x00_start_iocbs(ha, ha->req); -} - -void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) -{ - mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); -} -EXPORT_SYMBOL(qlt_free_mcmd); - -/* callback from target fabric module code */ -void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd) -{ - struct scsi_qla_host *vha = mcmd->sess->vha; - struct qla_hw_data *ha = vha->hw; - unsigned long flags; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf013, - "TM response mcmd (%p) status %#x state %#x", - mcmd, mcmd->fc_tm_rsp, mcmd->flags); - - spin_lock_irqsave(&ha->hardware_lock, flags); - if (mcmd->flags == QLA24XX_MGMT_SEND_NACK) - qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy, - 0, 0, 0, 0, 0, 0); - else { - if (mcmd->se_cmd.se_tmr_req->function == TMR_ABORT_TASK) - qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts, - mcmd->fc_tm_rsp, false); - else - qlt_24xx_send_task_mgmt_ctio(vha, mcmd, - mcmd->fc_tm_rsp); - } - /* - * Make the callback for ->free_mcmd() to queue_work() and invoke - * target_put_sess_cmd() to drop cmd_kref to 1. The final - * target_put_sess_cmd() call will be made from TFO->check_stop_free() - * -> tcm_qla2xxx_check_stop_free() to release the TMR associated se_cmd - * descriptor after TFO->queue_tm_rsp() -> tcm_qla2xxx_queue_tm_rsp() -> - * qlt_xmit_tm_rsp() returns here.. - */ - ha->tgt.tgt_ops->free_mcmd(mcmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} -EXPORT_SYMBOL(qlt_xmit_tm_rsp); - -/* No locks */ -static int qlt_pci_map_calc_cnt(struct qla_tgt_prm *prm) -{ - struct qla_tgt_cmd *cmd = prm->cmd; - - BUG_ON(cmd->sg_cnt == 0); - - prm->sg = (struct scatterlist *)cmd->sg; - prm->seg_cnt = pci_map_sg(prm->tgt->ha->pdev, cmd->sg, - cmd->sg_cnt, cmd->dma_data_direction); - if (unlikely(prm->seg_cnt == 0)) - goto out_err; - - prm->cmd->sg_mapped = 1; - - /* - * If greater than four sg entries then we need to allocate - * the continuation entries - */ - if (prm->seg_cnt > prm->tgt->datasegs_per_cmd) - prm->req_cnt += DIV_ROUND_UP(prm->seg_cnt - - prm->tgt->datasegs_per_cmd, prm->tgt->datasegs_per_cont); - - ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe009, "seg_cnt=%d, req_cnt=%d\n", - prm->seg_cnt, prm->req_cnt); - return 0; - -out_err: - ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe04d, - "qla_target(%d): PCI mapping failed: sg_cnt=%d", - 0, prm->cmd->sg_cnt); - return -1; -} - -static inline void qlt_unmap_sg(struct scsi_qla_host *vha, - struct qla_tgt_cmd *cmd) -{ - struct qla_hw_data *ha = vha->hw; - - BUG_ON(!cmd->sg_mapped); - pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); - cmd->sg_mapped = 0; -} - -static int qlt_check_reserve_free_req(struct scsi_qla_host *vha, - uint32_t req_cnt) -{ - struct qla_hw_data *ha = vha->hw; - device_reg_t __iomem *reg = ha->iobase; - uint32_t cnt; - - if (vha->req->cnt < (req_cnt + 2)) { - cnt = (uint16_t)RD_REG_DWORD(®->isp24.req_q_out); - - ql_dbg(ql_dbg_tgt, vha, 0xe00a, - "Request ring circled: cnt=%d, vha->->ring_index=%d, " - "vha->req->cnt=%d, req_cnt=%d\n", cnt, - vha->req->ring_index, vha->req->cnt, req_cnt); - if (vha->req->ring_index < cnt) - vha->req->cnt = cnt - vha->req->ring_index; - else - vha->req->cnt = vha->req->length - - (vha->req->ring_index - cnt); - } - - if (unlikely(vha->req->cnt < (req_cnt + 2))) { - ql_dbg(ql_dbg_tgt, vha, 0xe00b, - "qla_target(%d): There is no room in the " - "request ring: vha->req->ring_index=%d, vha->req->cnt=%d, " - "req_cnt=%d\n", vha->vp_idx, vha->req->ring_index, - vha->req->cnt, req_cnt); - return -EAGAIN; - } - vha->req->cnt -= req_cnt; - - return 0; -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static inline void *qlt_get_req_pkt(struct scsi_qla_host *vha) -{ - /* Adjust ring index. */ - vha->req->ring_index++; - if (vha->req->ring_index == vha->req->length) { - vha->req->ring_index = 0; - vha->req->ring_ptr = vha->req->ring; - } else { - vha->req->ring_ptr++; - } - return (cont_entry_t *)vha->req->ring_ptr; -} - -/* ha->hardware_lock supposed to be held on entry */ -static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - uint32_t h; - - h = ha->tgt.current_handle; - /* always increment cmd handle */ - do { - ++h; - if (h > MAX_OUTSTANDING_COMMANDS) - h = 1; /* 0 is QLA_TGT_NULL_HANDLE */ - if (h == ha->tgt.current_handle) { - ql_dbg(ql_dbg_tgt, vha, 0xe04e, - "qla_target(%d): Ran out of " - "empty cmd slots in ha %p\n", vha->vp_idx, ha); - h = QLA_TGT_NULL_HANDLE; - break; - } - } while ((h == QLA_TGT_NULL_HANDLE) || - (h == QLA_TGT_SKIP_HANDLE) || - (ha->tgt.cmds[h-1] != NULL)); - - if (h != QLA_TGT_NULL_HANDLE) - ha->tgt.current_handle = h; - - return h; -} - -/* ha->hardware_lock supposed to be held on entry */ -static int qlt_24xx_build_ctio_pkt(struct qla_tgt_prm *prm, - struct scsi_qla_host *vha) -{ - uint32_t h; - struct ctio7_to_24xx *pkt; - struct qla_hw_data *ha = vha->hw; - struct atio_from_isp *atio = &prm->cmd->atio; - - pkt = (struct ctio7_to_24xx *)vha->req->ring_ptr; - prm->pkt = pkt; - memset(pkt, 0, sizeof(*pkt)); - - pkt->entry_type = CTIO_TYPE7; - pkt->entry_count = (uint8_t)prm->req_cnt; - pkt->vp_index = vha->vp_idx; - - h = qlt_make_handle(vha); - if (unlikely(h == QLA_TGT_NULL_HANDLE)) { - /* - * CTIO type 7 from the firmware doesn't provide a way to - * know the initiator's LOOP ID, hence we can't find - * the session and, so, the command. - */ - return -EAGAIN; - } else - ha->tgt.cmds[h-1] = prm->cmd; - - pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK; - pkt->nport_handle = prm->cmd->loop_id; - pkt->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); - pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; - pkt->exchange_addr = atio->u.isp24.exchange_addr; - pkt->u.status0.flags |= (atio->u.isp24.attr << 9); - pkt->u.status0.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); - pkt->u.status0.relative_offset = cpu_to_le32(prm->cmd->offset); - - ql_dbg(ql_dbg_tgt, vha, 0xe00c, - "qla_target(%d): handle(cmd) -> %08x, timeout %d, ox_id %#x\n", - vha->vp_idx, pkt->handle, QLA_TGT_TIMEOUT, - le16_to_cpu(pkt->u.status0.ox_id)); - return 0; -} - -/* - * ha->hardware_lock supposed to be held on entry. We have already made sure - * that there is sufficient amount of request entries to not drop it. - */ -static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm, - struct scsi_qla_host *vha) -{ - int cnt; - uint32_t *dword_ptr; - int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr; - - /* Build continuation packets */ - while (prm->seg_cnt > 0) { - cont_a64_entry_t *cont_pkt64 = - (cont_a64_entry_t *)qlt_get_req_pkt(vha); - - /* - * Make sure that from cont_pkt64 none of - * 64-bit specific fields used for 32-bit - * addressing. Cast to (cont_entry_t *) for - * that. - */ - - memset(cont_pkt64, 0, sizeof(*cont_pkt64)); - - cont_pkt64->entry_count = 1; - cont_pkt64->sys_define = 0; - - if (enable_64bit_addressing) { - cont_pkt64->entry_type = CONTINUE_A64_TYPE; - dword_ptr = - (uint32_t *)&cont_pkt64->dseg_0_address; - } else { - cont_pkt64->entry_type = CONTINUE_TYPE; - dword_ptr = - (uint32_t *)&((cont_entry_t *) - cont_pkt64)->dseg_0_address; - } - - /* Load continuation entry data segments */ - for (cnt = 0; - cnt < prm->tgt->datasegs_per_cont && prm->seg_cnt; - cnt++, prm->seg_cnt--) { - *dword_ptr++ = - cpu_to_le32(pci_dma_lo32 - (sg_dma_address(prm->sg))); - if (enable_64bit_addressing) { - *dword_ptr++ = - cpu_to_le32(pci_dma_hi32 - (sg_dma_address - (prm->sg))); - } - *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg)); - - ql_dbg(ql_dbg_tgt, vha, 0xe00d, - "S/G Segment Cont. phys_addr=%llx:%llx, len=%d\n", - (long long unsigned int) - pci_dma_hi32(sg_dma_address(prm->sg)), - (long long unsigned int) - pci_dma_lo32(sg_dma_address(prm->sg)), - (int)sg_dma_len(prm->sg)); - - prm->sg = sg_next(prm->sg); - } - } -} - -/* - * ha->hardware_lock supposed to be held on entry. We have already made sure - * that there is sufficient amount of request entries to not drop it. - */ -static void qlt_load_data_segments(struct qla_tgt_prm *prm, - struct scsi_qla_host *vha) -{ - int cnt; - uint32_t *dword_ptr; - int enable_64bit_addressing = prm->tgt->tgt_enable_64bit_addr; - struct ctio7_to_24xx *pkt24 = (struct ctio7_to_24xx *)prm->pkt; - - ql_dbg(ql_dbg_tgt, vha, 0xe00e, - "iocb->scsi_status=%x, iocb->flags=%x\n", - le16_to_cpu(pkt24->u.status0.scsi_status), - le16_to_cpu(pkt24->u.status0.flags)); - - pkt24->u.status0.transfer_length = cpu_to_le32(prm->cmd->bufflen); - - /* Setup packet address segment pointer */ - dword_ptr = pkt24->u.status0.dseg_0_address; - - /* Set total data segment count */ - if (prm->seg_cnt) - pkt24->dseg_count = cpu_to_le16(prm->seg_cnt); - - if (prm->seg_cnt == 0) { - /* No data transfer */ - *dword_ptr++ = 0; - *dword_ptr = 0; - return; - } - - /* If scatter gather */ - ql_dbg(ql_dbg_tgt, vha, 0xe00f, "%s", "Building S/G data segments..."); - - /* Load command entry data segments */ - for (cnt = 0; - (cnt < prm->tgt->datasegs_per_cmd) && prm->seg_cnt; - cnt++, prm->seg_cnt--) { - *dword_ptr++ = - cpu_to_le32(pci_dma_lo32(sg_dma_address(prm->sg))); - if (enable_64bit_addressing) { - *dword_ptr++ = - cpu_to_le32(pci_dma_hi32( - sg_dma_address(prm->sg))); - } - *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg)); - - ql_dbg(ql_dbg_tgt, vha, 0xe010, - "S/G Segment phys_addr=%llx:%llx, len=%d\n", - (long long unsigned int)pci_dma_hi32(sg_dma_address( - prm->sg)), - (long long unsigned int)pci_dma_lo32(sg_dma_address( - prm->sg)), - (int)sg_dma_len(prm->sg)); - - prm->sg = sg_next(prm->sg); - } - - qlt_load_cont_data_segments(prm, vha); -} - -static inline int qlt_has_data(struct qla_tgt_cmd *cmd) -{ - return cmd->bufflen > 0; -} - -/* - * Called without ha->hardware_lock held - */ -static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, - struct qla_tgt_prm *prm, int xmit_type, uint8_t scsi_status, - uint32_t *full_req_cnt) -{ - struct qla_tgt *tgt = cmd->tgt; - struct scsi_qla_host *vha = tgt->vha; - struct qla_hw_data *ha = vha->hw; - struct se_cmd *se_cmd = &cmd->se_cmd; - - if (unlikely(cmd->aborted)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, - "qla_target(%d): terminating exchange " - "for aborted cmd=%p (se_cmd=%p, tag=%d)", vha->vp_idx, cmd, - se_cmd, cmd->tag); - - cmd->state = QLA_TGT_STATE_ABORTED; - - qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); - - /* !! At this point cmd could be already freed !! */ - return QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED; - } - - ql_dbg(ql_dbg_tgt, vha, 0xe011, "qla_target(%d): tag=%u\n", - vha->vp_idx, cmd->tag); - - prm->cmd = cmd; - prm->tgt = tgt; - prm->rq_result = scsi_status; - prm->sense_buffer = &cmd->sense_buffer[0]; - prm->sense_buffer_len = TRANSPORT_SENSE_BUFFER; - prm->sg = NULL; - prm->seg_cnt = -1; - prm->req_cnt = 1; - prm->add_status_pkt = 0; - - ql_dbg(ql_dbg_tgt, vha, 0xe012, "rq_result=%x, xmit_type=%x\n", - prm->rq_result, xmit_type); - - /* Send marker if required */ - if (qlt_issue_marker(vha, 0) != QLA_SUCCESS) - return -EFAULT; - - ql_dbg(ql_dbg_tgt, vha, 0xe013, "CTIO start: vha(%d)\n", vha->vp_idx); - - if ((xmit_type & QLA_TGT_XMIT_DATA) && qlt_has_data(cmd)) { - if (qlt_pci_map_calc_cnt(prm) != 0) - return -EAGAIN; - } - - *full_req_cnt = prm->req_cnt; - - if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { - prm->residual = se_cmd->residual_count; - ql_dbg(ql_dbg_tgt, vha, 0xe014, - "Residual underflow: %d (tag %d, " - "op %x, bufflen %d, rq_result %x)\n", prm->residual, - cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, - cmd->bufflen, prm->rq_result); - prm->rq_result |= SS_RESIDUAL_UNDER; - } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { - prm->residual = se_cmd->residual_count; - ql_dbg(ql_dbg_tgt, vha, 0xe015, - "Residual overflow: %d (tag %d, " - "op %x, bufflen %d, rq_result %x)\n", prm->residual, - cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, - cmd->bufflen, prm->rq_result); - prm->rq_result |= SS_RESIDUAL_OVER; - } - - if (xmit_type & QLA_TGT_XMIT_STATUS) { - /* - * If QLA_TGT_XMIT_DATA is not set, add_status_pkt will be - * ignored in *xmit_response() below - */ - if (qlt_has_data(cmd)) { - if (QLA_TGT_SENSE_VALID(prm->sense_buffer) || - (IS_FWI2_CAPABLE(ha) && - (prm->rq_result != 0))) { - prm->add_status_pkt = 1; - (*full_req_cnt)++; - } - } - } - - ql_dbg(ql_dbg_tgt, vha, 0xe016, - "req_cnt=%d, full_req_cnt=%d, add_status_pkt=%d\n", - prm->req_cnt, *full_req_cnt, prm->add_status_pkt); - - return 0; -} - -static inline int qlt_need_explicit_conf(struct qla_hw_data *ha, - struct qla_tgt_cmd *cmd, int sending_sense) -{ - if (ha->tgt.enable_class_2) - return 0; - - if (sending_sense) - return cmd->conf_compl_supported; - else - return ha->tgt.enable_explicit_conf && - cmd->conf_compl_supported; -} - -#ifdef CONFIG_QLA_TGT_DEBUG_SRR -/* - * Original taken from the XFS code - */ -static unsigned long qlt_srr_random(void) -{ - static int Inited; - static unsigned long RandomValue; - static DEFINE_SPINLOCK(lock); - /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */ - register long rv; - register long lo; - register long hi; - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - if (!Inited) { - RandomValue = jiffies; - Inited = 1; - } - rv = RandomValue; - hi = rv / 127773; - lo = rv % 127773; - rv = 16807 * lo - 2836 * hi; - if (rv <= 0) - rv += 2147483647; - RandomValue = rv; - spin_unlock_irqrestore(&lock, flags); - return rv; -} - -static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type) -{ -#if 0 /* This is not a real status packets lost, so it won't lead to SRR */ - if ((*xmit_type & QLA_TGT_XMIT_STATUS) && (qlt_srr_random() % 200) - == 50) { - *xmit_type &= ~QLA_TGT_XMIT_STATUS; - ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf015, - "Dropping cmd %p (tag %d) status", cmd, cmd->tag); - } -#endif - /* - * It's currently not possible to simulate SRRs for FCP_WRITE without - * a physical link layer failure, so don't even try here.. - */ - if (cmd->dma_data_direction != DMA_FROM_DEVICE) - return; - - if (qlt_has_data(cmd) && (cmd->sg_cnt > 1) && - ((qlt_srr_random() % 100) == 20)) { - int i, leave = 0; - unsigned int tot_len = 0; - - while (leave == 0) - leave = qlt_srr_random() % cmd->sg_cnt; - - for (i = 0; i < leave; i++) - tot_len += cmd->sg[i].length; - - ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf016, - "Cutting cmd %p (tag %d) buffer" - " tail to len %d, sg_cnt %d (cmd->bufflen %d," - " cmd->sg_cnt %d)", cmd, cmd->tag, tot_len, leave, - cmd->bufflen, cmd->sg_cnt); - - cmd->bufflen = tot_len; - cmd->sg_cnt = leave; - } - - if (qlt_has_data(cmd) && ((qlt_srr_random() % 100) == 70)) { - unsigned int offset = qlt_srr_random() % cmd->bufflen; - - ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf017, - "Cutting cmd %p (tag %d) buffer head " - "to offset %d (cmd->bufflen %d)", cmd, cmd->tag, offset, - cmd->bufflen); - if (offset == 0) - *xmit_type &= ~QLA_TGT_XMIT_DATA; - else if (qlt_set_data_offset(cmd, offset)) { - ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf018, - "qlt_set_data_offset() failed (tag %d)", cmd->tag); - } - } -} -#else -static inline void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type) -{} -#endif - -static void qlt_24xx_init_ctio_to_isp(struct ctio7_to_24xx *ctio, - struct qla_tgt_prm *prm) -{ - prm->sense_buffer_len = min_t(uint32_t, prm->sense_buffer_len, - (uint32_t)sizeof(ctio->u.status1.sense_data)); - ctio->u.status0.flags |= - __constant_cpu_to_le16(CTIO7_FLAGS_SEND_STATUS); - if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 0)) { - ctio->u.status0.flags |= __constant_cpu_to_le16( - CTIO7_FLAGS_EXPLICIT_CONFORM | - CTIO7_FLAGS_CONFORM_REQ); - } - ctio->u.status0.residual = cpu_to_le32(prm->residual); - ctio->u.status0.scsi_status = cpu_to_le16(prm->rq_result); - if (QLA_TGT_SENSE_VALID(prm->sense_buffer)) { - int i; - - if (qlt_need_explicit_conf(prm->tgt->ha, prm->cmd, 1)) { - if (prm->cmd->se_cmd.scsi_status != 0) { - ql_dbg(ql_dbg_tgt, prm->cmd->vha, 0xe017, - "Skipping EXPLICIT_CONFORM and " - "CTIO7_FLAGS_CONFORM_REQ for FCP READ w/ " - "non GOOD status\n"); - goto skip_explict_conf; - } - ctio->u.status1.flags |= __constant_cpu_to_le16( - CTIO7_FLAGS_EXPLICIT_CONFORM | - CTIO7_FLAGS_CONFORM_REQ); - } -skip_explict_conf: - ctio->u.status1.flags &= - ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); - ctio->u.status1.flags |= - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1); - ctio->u.status1.scsi_status |= - __constant_cpu_to_le16(SS_SENSE_LEN_VALID); - ctio->u.status1.sense_length = - cpu_to_le16(prm->sense_buffer_len); - for (i = 0; i < prm->sense_buffer_len/4; i++) - ((uint32_t *)ctio->u.status1.sense_data)[i] = - cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]); -#if 0 - if (unlikely((prm->sense_buffer_len % 4) != 0)) { - static int q; - if (q < 10) { - ql_dbg(ql_dbg_tgt, vha, 0xe04f, - "qla_target(%d): %d bytes of sense " - "lost", prm->tgt->ha->vp_idx, - prm->sense_buffer_len % 4); - q++; - } - } -#endif - } else { - ctio->u.status1.flags &= - ~__constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_0); - ctio->u.status1.flags |= - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1); - ctio->u.status1.sense_length = 0; - memset(ctio->u.status1.sense_data, 0, - sizeof(ctio->u.status1.sense_data)); - } - - /* Sense with len > 24, is it possible ??? */ -} - -/* - * Callback to setup response of xmit_type of QLA_TGT_XMIT_DATA and * - * QLA_TGT_XMIT_STATUS for >= 24xx silicon - */ -int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, - uint8_t scsi_status) -{ - struct scsi_qla_host *vha = cmd->vha; - struct qla_hw_data *ha = vha->hw; - struct ctio7_to_24xx *pkt; - struct qla_tgt_prm prm; - uint32_t full_req_cnt = 0; - unsigned long flags = 0; - int res; - - memset(&prm, 0, sizeof(prm)); - qlt_check_srr_debug(cmd, &xmit_type); - - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe018, - "is_send_status=%d, cmd->bufflen=%d, cmd->sg_cnt=%d, " - "cmd->dma_data_direction=%d\n", (xmit_type & QLA_TGT_XMIT_STATUS) ? - 1 : 0, cmd->bufflen, cmd->sg_cnt, cmd->dma_data_direction); - - res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, - &full_req_cnt); - if (unlikely(res != 0)) { - if (res == QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED) - return 0; - - return res; - } - - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Does F/W have an IOCBs for this request */ - res = qlt_check_reserve_free_req(vha, full_req_cnt); - if (unlikely(res)) - goto out_unmap_unlock; - - res = qlt_24xx_build_ctio_pkt(&prm, vha); - if (unlikely(res != 0)) - goto out_unmap_unlock; - - - pkt = (struct ctio7_to_24xx *)prm.pkt; - - if (qlt_has_data(cmd) && (xmit_type & QLA_TGT_XMIT_DATA)) { - pkt->u.status0.flags |= - __constant_cpu_to_le16(CTIO7_FLAGS_DATA_IN | - CTIO7_FLAGS_STATUS_MODE_0); - - qlt_load_data_segments(&prm, vha); - - if (prm.add_status_pkt == 0) { - if (xmit_type & QLA_TGT_XMIT_STATUS) { - pkt->u.status0.scsi_status = - cpu_to_le16(prm.rq_result); - pkt->u.status0.residual = - cpu_to_le32(prm.residual); - pkt->u.status0.flags |= __constant_cpu_to_le16( - CTIO7_FLAGS_SEND_STATUS); - if (qlt_need_explicit_conf(ha, cmd, 0)) { - pkt->u.status0.flags |= - __constant_cpu_to_le16( - CTIO7_FLAGS_EXPLICIT_CONFORM | - CTIO7_FLAGS_CONFORM_REQ); - } - } - - } else { - /* - * We have already made sure that there is sufficient - * amount of request entries to not drop HW lock in - * req_pkt(). - */ - struct ctio7_to_24xx *ctio = - (struct ctio7_to_24xx *)qlt_get_req_pkt(vha); - - ql_dbg(ql_dbg_tgt, vha, 0xe019, - "Building additional status packet\n"); - - memcpy(ctio, pkt, sizeof(*ctio)); - ctio->entry_count = 1; - ctio->dseg_count = 0; - ctio->u.status1.flags &= ~__constant_cpu_to_le16( - CTIO7_FLAGS_DATA_IN); - - /* Real finish is ctio_m1's finish */ - pkt->handle |= CTIO_INTERMEDIATE_HANDLE_MARK; - pkt->u.status0.flags |= __constant_cpu_to_le16( - CTIO7_FLAGS_DONT_RET_CTIO); - qlt_24xx_init_ctio_to_isp((struct ctio7_to_24xx *)ctio, - &prm); - pr_debug("Status CTIO7: %p\n", ctio); - } - } else - qlt_24xx_init_ctio_to_isp(pkt, &prm); - - - cmd->state = QLA_TGT_STATE_PROCESSED; /* Mid-level is done processing */ - - ql_dbg(ql_dbg_tgt, vha, 0xe01a, - "Xmitting CTIO7 response pkt for 24xx: %p scsi_status: 0x%02x\n", - pkt, scsi_status); - - qla2x00_start_iocbs(vha, vha->req); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return 0; - -out_unmap_unlock: - if (cmd->sg_mapped) - qlt_unmap_sg(vha, cmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return res; -} -EXPORT_SYMBOL(qlt_xmit_response); - -int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) -{ - struct ctio7_to_24xx *pkt; - struct scsi_qla_host *vha = cmd->vha; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = cmd->tgt; - struct qla_tgt_prm prm; - unsigned long flags; - int res = 0; - - memset(&prm, 0, sizeof(prm)); - prm.cmd = cmd; - prm.tgt = tgt; - prm.sg = NULL; - prm.req_cnt = 1; - - /* Send marker if required */ - if (qlt_issue_marker(vha, 0) != QLA_SUCCESS) - return -EIO; - - ql_dbg(ql_dbg_tgt, vha, 0xe01b, "CTIO_start: vha(%d)", - (int)vha->vp_idx); - - /* Calculate number of entries and segments required */ - if (qlt_pci_map_calc_cnt(&prm) != 0) - return -EAGAIN; - - spin_lock_irqsave(&ha->hardware_lock, flags); - - /* Does F/W have an IOCBs for this request */ - res = qlt_check_reserve_free_req(vha, prm.req_cnt); - if (res != 0) - goto out_unlock_free_unmap; - - res = qlt_24xx_build_ctio_pkt(&prm, vha); - if (unlikely(res != 0)) - goto out_unlock_free_unmap; - pkt = (struct ctio7_to_24xx *)prm.pkt; - pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT | - CTIO7_FLAGS_STATUS_MODE_0); - qlt_load_data_segments(&prm, vha); - - cmd->state = QLA_TGT_STATE_NEED_DATA; - - qla2x00_start_iocbs(vha, vha->req); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return res; - -out_unlock_free_unmap: - if (cmd->sg_mapped) - qlt_unmap_sg(vha, cmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - return res; -} -EXPORT_SYMBOL(qlt_rdy_to_xfer); - -/* If hardware_lock held on entry, might drop it, then reaquire */ -/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ -static int __qlt_send_term_exchange(struct scsi_qla_host *vha, - struct qla_tgt_cmd *cmd, - struct atio_from_isp *atio) -{ - struct ctio7_to_24xx *ctio24; - struct qla_hw_data *ha = vha->hw; - request_t *pkt; - int ret = 0; - - ql_dbg(ql_dbg_tgt, vha, 0xe01c, "Sending TERM EXCH CTIO (ha=%p)\n", ha); - - pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); - if (pkt == NULL) { - ql_dbg(ql_dbg_tgt, vha, 0xe050, - "qla_target(%d): %s failed: unable to allocate " - "request packet\n", vha->vp_idx, __func__); - return -ENOMEM; - } - - if (cmd != NULL) { - if (cmd->state < QLA_TGT_STATE_PROCESSED) { - ql_dbg(ql_dbg_tgt, vha, 0xe051, - "qla_target(%d): Terminating cmd %p with " - "incorrect state %d\n", vha->vp_idx, cmd, - cmd->state); - } else - ret = 1; - } - - pkt->entry_count = 1; - pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; - - ctio24 = (struct ctio7_to_24xx *)pkt; - ctio24->entry_type = CTIO_TYPE7; - ctio24->nport_handle = cmd ? cmd->loop_id : CTIO7_NHANDLE_UNRECOGNIZED; - ctio24->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); - ctio24->vp_index = vha->vp_idx; - ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; - ctio24->exchange_addr = atio->u.isp24.exchange_addr; - ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | - __constant_cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | - CTIO7_FLAGS_TERMINATE); - ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); - - /* Most likely, it isn't needed */ - ctio24->u.status1.residual = get_unaligned((uint32_t *) - &atio->u.isp24.fcp_cmnd.add_cdb[ - atio->u.isp24.fcp_cmnd.add_cdb_len]); - if (ctio24->u.status1.residual != 0) - ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER; - - qla2x00_start_iocbs(vha, vha->req); - return ret; -} - -static void qlt_send_term_exchange(struct scsi_qla_host *vha, - struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) -{ - unsigned long flags; - int rc; - - if (qlt_issue_marker(vha, ha_locked) < 0) - return; - - if (ha_locked) { - rc = __qlt_send_term_exchange(vha, cmd, atio); - goto done; - } - spin_lock_irqsave(&vha->hw->hardware_lock, flags); - rc = __qlt_send_term_exchange(vha, cmd, atio); - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); -done: - if (rc == 1) { - if (!ha_locked && !in_interrupt()) - msleep(250); /* just in case */ - - vha->hw->tgt.tgt_ops->free_cmd(cmd); - } -} - -void qlt_free_cmd(struct qla_tgt_cmd *cmd) -{ - BUG_ON(cmd->sg_mapped); - - if (unlikely(cmd->free_sg)) - kfree(cmd->sg); - kmem_cache_free(qla_tgt_cmd_cachep, cmd); -} -EXPORT_SYMBOL(qlt_free_cmd); - -/* ha->hardware_lock supposed to be held on entry */ -static int qlt_prepare_srr_ctio(struct scsi_qla_host *vha, - struct qla_tgt_cmd *cmd, void *ctio) -{ - struct qla_tgt_srr_ctio *sc; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - struct qla_tgt_srr_imm *imm; - - tgt->ctio_srr_id++; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf019, - "qla_target(%d): CTIO with SRR status received\n", vha->vp_idx); - - if (!ctio) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf055, - "qla_target(%d): SRR CTIO, but ctio is NULL\n", - vha->vp_idx); - return -EINVAL; - } - - sc = kzalloc(sizeof(*sc), GFP_ATOMIC); - if (sc != NULL) { - sc->cmd = cmd; - /* IRQ is already OFF */ - spin_lock(&tgt->srr_lock); - sc->srr_id = tgt->ctio_srr_id; - list_add_tail(&sc->srr_list_entry, - &tgt->srr_ctio_list); - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01a, - "CTIO SRR %p added (id %d)\n", sc, sc->srr_id); - if (tgt->imm_srr_id == tgt->ctio_srr_id) { - int found = 0; - list_for_each_entry(imm, &tgt->srr_imm_list, - srr_list_entry) { - if (imm->srr_id == sc->srr_id) { - found = 1; - break; - } - } - if (found) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01b, - "Scheduling srr work\n"); - schedule_work(&tgt->srr_work); - } else { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf056, - "qla_target(%d): imm_srr_id " - "== ctio_srr_id (%d), but there is no " - "corresponding SRR IMM, deleting CTIO " - "SRR %p\n", vha->vp_idx, - tgt->ctio_srr_id, sc); - list_del(&sc->srr_list_entry); - spin_unlock(&tgt->srr_lock); - - kfree(sc); - return -EINVAL; - } - } - spin_unlock(&tgt->srr_lock); - } else { - struct qla_tgt_srr_imm *ti; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf057, - "qla_target(%d): Unable to allocate SRR CTIO entry\n", - vha->vp_idx); - spin_lock(&tgt->srr_lock); - list_for_each_entry_safe(imm, ti, &tgt->srr_imm_list, - srr_list_entry) { - if (imm->srr_id == tgt->ctio_srr_id) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01c, - "IMM SRR %p deleted (id %d)\n", - imm, imm->srr_id); - list_del(&imm->srr_list_entry); - qlt_reject_free_srr_imm(vha, imm, 1); - } - } - spin_unlock(&tgt->srr_lock); - - return -ENOMEM; - } - - return 0; -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio, - struct qla_tgt_cmd *cmd, uint32_t status) -{ - int term = 0; - - if (ctio != NULL) { - struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio; - term = !(c->flags & - __constant_cpu_to_le16(OF_TERM_EXCH)); - } else - term = 1; - - if (term) - qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); - - return term; -} - -/* ha->hardware_lock supposed to be held on entry */ -static inline struct qla_tgt_cmd *qlt_get_cmd(struct scsi_qla_host *vha, - uint32_t handle) -{ - struct qla_hw_data *ha = vha->hw; - - handle--; - if (ha->tgt.cmds[handle] != NULL) { - struct qla_tgt_cmd *cmd = ha->tgt.cmds[handle]; - ha->tgt.cmds[handle] = NULL; - return cmd; - } else - return NULL; -} - -/* ha->hardware_lock supposed to be held on entry */ -static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha, - uint32_t handle, void *ctio) -{ - struct qla_tgt_cmd *cmd = NULL; - - /* Clear out internal marks */ - handle &= ~(CTIO_COMPLETION_HANDLE_MARK | - CTIO_INTERMEDIATE_HANDLE_MARK); - - if (handle != QLA_TGT_NULL_HANDLE) { - if (unlikely(handle == QLA_TGT_SKIP_HANDLE)) { - ql_dbg(ql_dbg_tgt, vha, 0xe01d, "%s", - "SKIP_HANDLE CTIO\n"); - return NULL; - } - /* handle-1 is actually used */ - if (unlikely(handle > MAX_OUTSTANDING_COMMANDS)) { - ql_dbg(ql_dbg_tgt, vha, 0xe052, - "qla_target(%d): Wrong handle %x received\n", - vha->vp_idx, handle); - return NULL; - } - cmd = qlt_get_cmd(vha, handle); - if (unlikely(cmd == NULL)) { - ql_dbg(ql_dbg_tgt, vha, 0xe053, - "qla_target(%d): Suspicious: unable to " - "find the command with handle %x\n", vha->vp_idx, - handle); - return NULL; - } - } else if (ctio != NULL) { - /* We can't get loop ID from CTIO7 */ - ql_dbg(ql_dbg_tgt, vha, 0xe054, - "qla_target(%d): Wrong CTIO received: QLA24xx doesn't " - "support NULL handles\n", vha->vp_idx); - return NULL; - } - - return cmd; -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, - uint32_t status, void *ctio) -{ - struct qla_hw_data *ha = vha->hw; - struct se_cmd *se_cmd; - struct target_core_fabric_ops *tfo; - struct qla_tgt_cmd *cmd; - - ql_dbg(ql_dbg_tgt, vha, 0xe01e, - "qla_target(%d): handle(ctio %p status %#x) <- %08x\n", - vha->vp_idx, ctio, status, handle); - - if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) { - /* That could happen only in case of an error/reset/abort */ - if (status != CTIO_SUCCESS) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01d, - "Intermediate CTIO received" - " (status %x)\n", status); - } - return; - } - - cmd = qlt_ctio_to_cmd(vha, handle, ctio); - if (cmd == NULL) - return; - - se_cmd = &cmd->se_cmd; - tfo = se_cmd->se_tfo; - - if (cmd->sg_mapped) - qlt_unmap_sg(vha, cmd); - - if (unlikely(status != CTIO_SUCCESS)) { - switch (status & 0xFFFF) { - case CTIO_LIP_RESET: - case CTIO_TARGET_RESET: - case CTIO_ABORTED: - case CTIO_TIMEOUT: - case CTIO_INVALID_RX_ID: - /* They are OK */ - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf058, - "qla_target(%d): CTIO with " - "status %#x received, state %x, se_cmd %p, " - "(LIP_RESET=e, ABORTED=2, TARGET_RESET=17, " - "TIMEOUT=b, INVALID_RX_ID=8)\n", vha->vp_idx, - status, cmd->state, se_cmd); - break; - - case CTIO_PORT_LOGGED_OUT: - case CTIO_PORT_UNAVAILABLE: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059, - "qla_target(%d): CTIO with PORT LOGGED " - "OUT (29) or PORT UNAVAILABLE (28) status %x " - "received (state %x, se_cmd %p)\n", vha->vp_idx, - status, cmd->state, se_cmd); - break; - - case CTIO_SRR_RECEIVED: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05a, - "qla_target(%d): CTIO with SRR_RECEIVED" - " status %x received (state %x, se_cmd %p)\n", - vha->vp_idx, status, cmd->state, se_cmd); - if (qlt_prepare_srr_ctio(vha, cmd, ctio) != 0) - break; - else - return; - - default: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05b, - "qla_target(%d): CTIO with error status " - "0x%x received (state %x, se_cmd %p\n", - vha->vp_idx, status, cmd->state, se_cmd); - break; - } - - if (cmd->state != QLA_TGT_STATE_NEED_DATA) - if (qlt_term_ctio_exchange(vha, ctio, cmd, status)) - return; - } - - if (cmd->state == QLA_TGT_STATE_PROCESSED) { - ql_dbg(ql_dbg_tgt, vha, 0xe01f, "Command %p finished\n", cmd); - } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { - int rx_status = 0; - - cmd->state = QLA_TGT_STATE_DATA_IN; - - if (unlikely(status != CTIO_SUCCESS)) - rx_status = -EIO; - else - cmd->write_data_transferred = 1; - - ql_dbg(ql_dbg_tgt, vha, 0xe020, - "Data received, context %x, rx_status %d\n", - 0x0, rx_status); - - ha->tgt.tgt_ops->handle_data(cmd); - return; - } else if (cmd->state == QLA_TGT_STATE_ABORTED) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e, - "Aborted command %p (tag %d) finished\n", cmd, cmd->tag); - } else { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c, - "qla_target(%d): A command in state (%d) should " - "not return a CTIO complete\n", vha->vp_idx, cmd->state); - } - - if (unlikely(status != CTIO_SUCCESS)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01f, "Finishing failed CTIO\n"); - dump_stack(); - } - - ha->tgt.tgt_ops->free_cmd(cmd); -} - -/* ha->hardware_lock supposed to be held on entry */ -/* called via callback from qla2xxx */ -void qlt_ctio_completion(struct scsi_qla_host *vha, uint32_t handle) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - - if (likely(tgt == NULL)) { - ql_dbg(ql_dbg_tgt, vha, 0xe021, - "CTIO, but target mode not enabled" - " (ha %d %p handle %#x)", vha->vp_idx, ha, handle); - return; - } - - tgt->irq_cmd_count++; - qlt_do_ctio_completion(vha, handle, CTIO_SUCCESS, NULL); - tgt->irq_cmd_count--; -} - -static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha, - uint8_t task_codes) -{ - int fcp_task_attr; - - switch (task_codes) { - case ATIO_SIMPLE_QUEUE: - fcp_task_attr = MSG_SIMPLE_TAG; - break; - case ATIO_HEAD_OF_QUEUE: - fcp_task_attr = MSG_HEAD_TAG; - break; - case ATIO_ORDERED_QUEUE: - fcp_task_attr = MSG_ORDERED_TAG; - break; - case ATIO_ACA_QUEUE: - fcp_task_attr = MSG_ACA_TAG; - break; - case ATIO_UNTAGGED: - fcp_task_attr = MSG_SIMPLE_TAG; - break; - default: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05d, - "qla_target: unknown task code %x, use ORDERED instead\n", - task_codes); - fcp_task_attr = MSG_ORDERED_TAG; - break; - } - - return fcp_task_attr; -} - -static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *, - uint8_t *); -/* - * Process context for I/O path into tcm_qla2xxx code - */ -static void qlt_do_work(struct work_struct *work) -{ - struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); - scsi_qla_host_t *vha = cmd->vha; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - struct qla_tgt_sess *sess = NULL; - struct atio_from_isp *atio = &cmd->atio; - unsigned char *cdb; - unsigned long flags; - uint32_t data_length; - int ret, fcp_task_attr, data_dir, bidi = 0; - - if (tgt->tgt_stop) - goto out_term; - - spin_lock_irqsave(&ha->hardware_lock, flags); - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, - atio->u.isp24.fcp_hdr.s_id); - if (sess) { - if (unlikely(sess->tearing_down)) { - sess = NULL; - spin_unlock_irqrestore(&ha->hardware_lock, flags); - goto out_term; - } else { - /* - * Do the extra kref_get() before dropping - * qla_hw_data->hardware_lock. - */ - kref_get(&sess->se_sess->sess_kref); - } - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - if (unlikely(!sess)) { - uint8_t *s_id = atio->u.isp24.fcp_hdr.s_id; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, - "qla_target(%d): Unable to find wwn login" - " (s_id %x:%x:%x), trying to create it manually\n", - vha->vp_idx, s_id[0], s_id[1], s_id[2]); - - if (atio->u.raw.entry_count > 1) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, - "Dropping multy entry cmd %p\n", cmd); - goto out_term; - } - - mutex_lock(&ha->tgt.tgt_mutex); - sess = qlt_make_local_sess(vha, s_id); - /* sess has an extra creation ref. */ - mutex_unlock(&ha->tgt.tgt_mutex); - - if (!sess) - goto out_term; - } - - cmd->sess = sess; - cmd->loop_id = sess->loop_id; - cmd->conf_compl_supported = sess->conf_compl_supported; - - cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; - cmd->tag = atio->u.isp24.exchange_addr; - cmd->unpacked_lun = scsilun_to_int( - (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun); - - if (atio->u.isp24.fcp_cmnd.rddata && - atio->u.isp24.fcp_cmnd.wrdata) { - bidi = 1; - data_dir = DMA_TO_DEVICE; - } else if (atio->u.isp24.fcp_cmnd.rddata) - data_dir = DMA_FROM_DEVICE; - else if (atio->u.isp24.fcp_cmnd.wrdata) - data_dir = DMA_TO_DEVICE; - else - data_dir = DMA_NONE; - - fcp_task_attr = qlt_get_fcp_task_attr(vha, - atio->u.isp24.fcp_cmnd.task_attr); - data_length = be32_to_cpu(get_unaligned((uint32_t *) - &atio->u.isp24.fcp_cmnd.add_cdb[ - atio->u.isp24.fcp_cmnd.add_cdb_len])); - - ql_dbg(ql_dbg_tgt, vha, 0xe022, - "qla_target: START qla command: %p lun: 0x%04x (tag %d)\n", - cmd, cmd->unpacked_lun, cmd->tag); - - ret = vha->hw->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length, - fcp_task_attr, data_dir, bidi); - if (ret != 0) - goto out_term; - /* - * Drop extra session reference from qla_tgt_handle_cmd_for_atio*( - */ - ha->tgt.tgt_ops->put_sess(sess); - return; - -out_term: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf020, "Terminating work cmd %p", cmd); - /* - * cmd has not sent to target yet, so pass NULL as the second - * argument to qlt_send_term_exchange() and free the memory here. - */ - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_term_exchange(vha, NULL, &cmd->atio, 1); - kmem_cache_free(qla_tgt_cmd_cachep, cmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (sess) - ha->tgt.tgt_ops->put_sess(sess); -} - -/* ha->hardware_lock supposed to be held on entry */ -static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, - struct atio_from_isp *atio) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - struct qla_tgt_cmd *cmd; - - if (unlikely(tgt->tgt_stop)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf021, - "New command while device %p is shutting down\n", tgt); - return -EFAULT; - } - - cmd = kmem_cache_zalloc(qla_tgt_cmd_cachep, GFP_ATOMIC); - if (!cmd) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05e, - "qla_target(%d): Allocation of cmd failed\n", vha->vp_idx); - return -ENOMEM; - } - - INIT_LIST_HEAD(&cmd->cmd_list); - - memcpy(&cmd->atio, atio, sizeof(*atio)); - cmd->state = QLA_TGT_STATE_NEW; - cmd->tgt = ha->tgt.qla_tgt; - cmd->vha = vha; - - INIT_WORK(&cmd->work, qlt_do_work); - queue_work(qla_tgt_wq, &cmd->work); - return 0; - -} - -/* ha->hardware_lock supposed to be held on entry */ -static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, - int fn, void *iocb, int flags) -{ - struct scsi_qla_host *vha = sess->vha; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_mgmt_cmd *mcmd; - int res; - uint8_t tmr_func; - - mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC); - if (!mcmd) { - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10009, - "qla_target(%d): Allocation of management " - "command failed, some commands and their data could " - "leak\n", vha->vp_idx); - return -ENOMEM; - } - memset(mcmd, 0, sizeof(*mcmd)); - mcmd->sess = sess; - - if (iocb) { - memcpy(&mcmd->orig_iocb.imm_ntfy, iocb, - sizeof(mcmd->orig_iocb.imm_ntfy)); - } - mcmd->tmr_func = fn; - mcmd->flags = flags; - - switch (fn) { - case QLA_TGT_CLEAR_ACA: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10000, - "qla_target(%d): CLEAR_ACA received\n", sess->vha->vp_idx); - tmr_func = TMR_CLEAR_ACA; - break; - - case QLA_TGT_TARGET_RESET: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10001, - "qla_target(%d): TARGET_RESET received\n", - sess->vha->vp_idx); - tmr_func = TMR_TARGET_WARM_RESET; - break; - - case QLA_TGT_LUN_RESET: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002, - "qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx); - tmr_func = TMR_LUN_RESET; - break; - - case QLA_TGT_CLEAR_TS: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10003, - "qla_target(%d): CLEAR_TS received\n", sess->vha->vp_idx); - tmr_func = TMR_CLEAR_TASK_SET; - break; - - case QLA_TGT_ABORT_TS: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10004, - "qla_target(%d): ABORT_TS received\n", sess->vha->vp_idx); - tmr_func = TMR_ABORT_TASK_SET; - break; -#if 0 - case QLA_TGT_ABORT_ALL: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10005, - "qla_target(%d): Doing ABORT_ALL_TASKS\n", - sess->vha->vp_idx); - tmr_func = 0; - break; - - case QLA_TGT_ABORT_ALL_SESS: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10006, - "qla_target(%d): Doing ABORT_ALL_TASKS_SESS\n", - sess->vha->vp_idx); - tmr_func = 0; - break; - - case QLA_TGT_NEXUS_LOSS_SESS: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10007, - "qla_target(%d): Doing NEXUS_LOSS_SESS\n", - sess->vha->vp_idx); - tmr_func = 0; - break; - - case QLA_TGT_NEXUS_LOSS: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x10008, - "qla_target(%d): Doing NEXUS_LOSS\n", sess->vha->vp_idx); - tmr_func = 0; - break; -#endif - default: - ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000a, - "qla_target(%d): Unknown task mgmt fn 0x%x\n", - sess->vha->vp_idx, fn); - mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); - return -ENOSYS; - } - - res = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, tmr_func, 0); - if (res != 0) { - ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000b, - "qla_target(%d): tgt.tgt_ops->handle_tmr() failed: %d\n", - sess->vha->vp_idx, res); - mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); - return -EFAULT; - } - - return 0; -} - -/* ha->hardware_lock supposed to be held on entry */ -static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) -{ - struct atio_from_isp *a = (struct atio_from_isp *)iocb; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt; - struct qla_tgt_sess *sess; - uint32_t lun, unpacked_lun; - int lun_size, fn; - - tgt = ha->tgt.qla_tgt; - - lun = a->u.isp24.fcp_cmnd.lun; - lun_size = sizeof(a->u.isp24.fcp_cmnd.lun); - fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, - a->u.isp24.fcp_hdr.s_id); - unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); - - if (!sess) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf024, - "qla_target(%d): task mgmt fn 0x%x for " - "non-existant session\n", vha->vp_idx, fn); - return qlt_sched_sess_work(tgt, QLA_TGT_SESS_WORK_TM, iocb, - sizeof(struct atio_from_isp)); - } - - return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); -} - -/* ha->hardware_lock supposed to be held on entry */ -static int __qlt_abort_task(struct scsi_qla_host *vha, - struct imm_ntfy_from_isp *iocb, struct qla_tgt_sess *sess) -{ - struct atio_from_isp *a = (struct atio_from_isp *)iocb; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_mgmt_cmd *mcmd; - uint32_t lun, unpacked_lun; - int rc; - - mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC); - if (mcmd == NULL) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05f, - "qla_target(%d): %s: Allocation of ABORT cmd failed\n", - vha->vp_idx, __func__); - return -ENOMEM; - } - memset(mcmd, 0, sizeof(*mcmd)); - - mcmd->sess = sess; - memcpy(&mcmd->orig_iocb.imm_ntfy, iocb, - sizeof(mcmd->orig_iocb.imm_ntfy)); - - lun = a->u.isp24.fcp_cmnd.lun; - unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); - - rc = ha->tgt.tgt_ops->handle_tmr(mcmd, unpacked_lun, TMR_ABORT_TASK, - le16_to_cpu(iocb->u.isp2x.seq_id)); - if (rc != 0) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf060, - "qla_target(%d): tgt_ops->handle_tmr() failed: %d\n", - vha->vp_idx, rc); - mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); - return -EFAULT; - } - - return 0; -} - -/* ha->hardware_lock supposed to be held on entry */ -static int qlt_abort_task(struct scsi_qla_host *vha, - struct imm_ntfy_from_isp *iocb) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_sess *sess; - int loop_id; - - loop_id = GET_TARGET_ID(ha, (struct atio_from_isp *)iocb); - - sess = ha->tgt.tgt_ops->find_sess_by_loop_id(vha, loop_id); - if (sess == NULL) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf025, - "qla_target(%d): task abort for unexisting " - "session\n", vha->vp_idx); - return qlt_sched_sess_work(ha->tgt.qla_tgt, - QLA_TGT_SESS_WORK_ABORT, iocb, sizeof(*iocb)); - } - - return __qlt_abort_task(vha, iocb, sess); -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static int qlt_24xx_handle_els(struct scsi_qla_host *vha, - struct imm_ntfy_from_isp *iocb) -{ - struct qla_hw_data *ha = vha->hw; - int res = 0; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026, - "qla_target(%d): Port ID: 0x%02x:%02x:%02x" - " ELS opcode: 0x%02x\n", vha->vp_idx, iocb->u.isp24.port_id[0], - iocb->u.isp24.port_id[1], iocb->u.isp24.port_id[2], - iocb->u.isp24.status_subcode); - - switch (iocb->u.isp24.status_subcode) { - case ELS_PLOGI: - case ELS_FLOGI: - case ELS_PRLI: - case ELS_LOGO: - case ELS_PRLO: - res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); - break; - case ELS_PDISC: - case ELS_ADISC: - { - struct qla_tgt *tgt = ha->tgt.qla_tgt; - if (tgt->link_reinit_iocb_pending) { - qlt_send_notify_ack(vha, &tgt->link_reinit_iocb, - 0, 0, 0, 0, 0, 0); - tgt->link_reinit_iocb_pending = 0; - } - res = 1; /* send notify ack */ - break; - } - - default: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061, - "qla_target(%d): Unsupported ELS command %x " - "received\n", vha->vp_idx, iocb->u.isp24.status_subcode); - res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); - break; - } - - return res; -} - -static int qlt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset) -{ - struct scatterlist *sg, *sgp, *sg_srr, *sg_srr_start = NULL; - size_t first_offset = 0, rem_offset = offset, tmp = 0; - int i, sg_srr_cnt, bufflen = 0; - - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe023, - "Entering qla_tgt_set_data_offset: cmd: %p, cmd->sg: %p, " - "cmd->sg_cnt: %u, direction: %d\n", - cmd, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); - - /* - * FIXME: Reject non zero SRR relative offset until we can test - * this code properly. - */ - pr_debug("Rejecting non zero SRR rel_offs: %u\n", offset); - return -1; - - if (!cmd->sg || !cmd->sg_cnt) { - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe055, - "Missing cmd->sg or zero cmd->sg_cnt in" - " qla_tgt_set_data_offset\n"); - return -EINVAL; - } - /* - * Walk the current cmd->sg list until we locate the new sg_srr_start - */ - for_each_sg(cmd->sg, sg, cmd->sg_cnt, i) { - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe024, - "sg[%d]: %p page: %p, length: %d, offset: %d\n", - i, sg, sg_page(sg), sg->length, sg->offset); - - if ((sg->length + tmp) > offset) { - first_offset = rem_offset; - sg_srr_start = sg; - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe025, - "Found matching sg[%d], using %p as sg_srr_start, " - "and using first_offset: %zu\n", i, sg, - first_offset); - break; - } - tmp += sg->length; - rem_offset -= sg->length; - } - - if (!sg_srr_start) { - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe056, - "Unable to locate sg_srr_start for offset: %u\n", offset); - return -EINVAL; - } - sg_srr_cnt = (cmd->sg_cnt - i); - - sg_srr = kzalloc(sizeof(struct scatterlist) * sg_srr_cnt, GFP_KERNEL); - if (!sg_srr) { - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe057, - "Unable to allocate sgp\n"); - return -ENOMEM; - } - sg_init_table(sg_srr, sg_srr_cnt); - sgp = &sg_srr[0]; - /* - * Walk the remaining list for sg_srr_start, mapping to the newly - * allocated sg_srr taking first_offset into account. - */ - for_each_sg(sg_srr_start, sg, sg_srr_cnt, i) { - if (first_offset) { - sg_set_page(sgp, sg_page(sg), - (sg->length - first_offset), first_offset); - first_offset = 0; - } else { - sg_set_page(sgp, sg_page(sg), sg->length, 0); - } - bufflen += sgp->length; - - sgp = sg_next(sgp); - if (!sgp) - break; - } - - cmd->sg = sg_srr; - cmd->sg_cnt = sg_srr_cnt; - cmd->bufflen = bufflen; - cmd->offset += offset; - cmd->free_sg = 1; - - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe026, "New cmd->sg: %p\n", cmd->sg); - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe027, "New cmd->sg_cnt: %u\n", - cmd->sg_cnt); - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe028, "New cmd->bufflen: %u\n", - cmd->bufflen); - ql_dbg(ql_dbg_tgt, cmd->vha, 0xe029, "New cmd->offset: %u\n", - cmd->offset); - - if (cmd->sg_cnt < 0) - BUG(); - - if (cmd->bufflen < 0) - BUG(); - - return 0; -} - -static inline int qlt_srr_adjust_data(struct qla_tgt_cmd *cmd, - uint32_t srr_rel_offs, int *xmit_type) -{ - int res = 0, rel_offs; - - rel_offs = srr_rel_offs - cmd->offset; - ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf027, "srr_rel_offs=%d, rel_offs=%d", - srr_rel_offs, rel_offs); - - *xmit_type = QLA_TGT_XMIT_ALL; - - if (rel_offs < 0) { - ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf062, - "qla_target(%d): SRR rel_offs (%d) < 0", - cmd->vha->vp_idx, rel_offs); - res = -1; - } else if (rel_offs == cmd->bufflen) - *xmit_type = QLA_TGT_XMIT_STATUS; - else if (rel_offs > 0) - res = qlt_set_data_offset(cmd, rel_offs); - - return res; -} - -/* No locks, thread context */ -static void qlt_handle_srr(struct scsi_qla_host *vha, - struct qla_tgt_srr_ctio *sctio, struct qla_tgt_srr_imm *imm) -{ - struct imm_ntfy_from_isp *ntfy = - (struct imm_ntfy_from_isp *)&imm->imm_ntfy; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_cmd *cmd = sctio->cmd; - struct se_cmd *se_cmd = &cmd->se_cmd; - unsigned long flags; - int xmit_type = 0, resp = 0; - uint32_t offset; - uint16_t srr_ui; - - offset = le32_to_cpu(ntfy->u.isp24.srr_rel_offs); - srr_ui = ntfy->u.isp24.srr_ui; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf028, "SRR cmd %p, srr_ui %x\n", - cmd, srr_ui); - - switch (srr_ui) { - case SRR_IU_STATUS: - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_notify_ack(vha, ntfy, - 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - xmit_type = QLA_TGT_XMIT_STATUS; - resp = 1; - break; - case SRR_IU_DATA_IN: - if (!cmd->sg || !cmd->sg_cnt) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf063, - "Unable to process SRR_IU_DATA_IN due to" - " missing cmd->sg, state: %d\n", cmd->state); - dump_stack(); - goto out_reject; - } - if (se_cmd->scsi_status != 0) { - ql_dbg(ql_dbg_tgt, vha, 0xe02a, - "Rejecting SRR_IU_DATA_IN with non GOOD " - "scsi_status\n"); - goto out_reject; - } - cmd->bufflen = se_cmd->data_length; - - if (qlt_has_data(cmd)) { - if (qlt_srr_adjust_data(cmd, offset, &xmit_type) != 0) - goto out_reject; - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_notify_ack(vha, ntfy, - 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - resp = 1; - } else { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf064, - "qla_target(%d): SRR for in data for cmd " - "without them (tag %d, SCSI status %d), " - "reject", vha->vp_idx, cmd->tag, - cmd->se_cmd.scsi_status); - goto out_reject; - } - break; - case SRR_IU_DATA_OUT: - if (!cmd->sg || !cmd->sg_cnt) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf065, - "Unable to process SRR_IU_DATA_OUT due to" - " missing cmd->sg\n"); - dump_stack(); - goto out_reject; - } - if (se_cmd->scsi_status != 0) { - ql_dbg(ql_dbg_tgt, vha, 0xe02b, - "Rejecting SRR_IU_DATA_OUT" - " with non GOOD scsi_status\n"); - goto out_reject; - } - cmd->bufflen = se_cmd->data_length; - - if (qlt_has_data(cmd)) { - if (qlt_srr_adjust_data(cmd, offset, &xmit_type) != 0) - goto out_reject; - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_notify_ack(vha, ntfy, - 0, 0, 0, NOTIFY_ACK_SRR_FLAGS_ACCEPT, 0, 0); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (xmit_type & QLA_TGT_XMIT_DATA) - qlt_rdy_to_xfer(cmd); - } else { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf066, - "qla_target(%d): SRR for out data for cmd " - "without them (tag %d, SCSI status %d), " - "reject", vha->vp_idx, cmd->tag, - cmd->se_cmd.scsi_status); - goto out_reject; - } - break; - default: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf067, - "qla_target(%d): Unknown srr_ui value %x", - vha->vp_idx, srr_ui); - goto out_reject; - } - - /* Transmit response in case of status and data-in cases */ - if (resp) - qlt_xmit_response(cmd, xmit_type, se_cmd->scsi_status); - - return; - -out_reject: - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_send_notify_ack(vha, ntfy, 0, 0, 0, - NOTIFY_ACK_SRR_FLAGS_REJECT, - NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, - NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); - if (cmd->state == QLA_TGT_STATE_NEED_DATA) { - cmd->state = QLA_TGT_STATE_DATA_IN; - dump_stack(); - } else - qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - -static void qlt_reject_free_srr_imm(struct scsi_qla_host *vha, - struct qla_tgt_srr_imm *imm, int ha_locked) -{ - struct qla_hw_data *ha = vha->hw; - unsigned long flags = 0; - - if (!ha_locked) - spin_lock_irqsave(&ha->hardware_lock, flags); - - qlt_send_notify_ack(vha, (void *)&imm->imm_ntfy, 0, 0, 0, - NOTIFY_ACK_SRR_FLAGS_REJECT, - NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, - NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); - - if (!ha_locked) - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - kfree(imm); -} - -static void qlt_handle_srr_work(struct work_struct *work) -{ - struct qla_tgt *tgt = container_of(work, struct qla_tgt, srr_work); - struct scsi_qla_host *vha = tgt->vha; - struct qla_tgt_srr_ctio *sctio; - unsigned long flags; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf029, "Entering SRR work (tgt %p)\n", - tgt); - -restart: - spin_lock_irqsave(&tgt->srr_lock, flags); - list_for_each_entry(sctio, &tgt->srr_ctio_list, srr_list_entry) { - struct qla_tgt_srr_imm *imm, *i, *ti; - struct qla_tgt_cmd *cmd; - struct se_cmd *se_cmd; - - imm = NULL; - list_for_each_entry_safe(i, ti, &tgt->srr_imm_list, - srr_list_entry) { - if (i->srr_id == sctio->srr_id) { - list_del(&i->srr_list_entry); - if (imm) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf068, - "qla_target(%d): There must be " - "only one IMM SRR per CTIO SRR " - "(IMM SRR %p, id %d, CTIO %p\n", - vha->vp_idx, i, i->srr_id, sctio); - qlt_reject_free_srr_imm(tgt->vha, i, 0); - } else - imm = i; - } - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02a, - "IMM SRR %p, CTIO SRR %p (id %d)\n", imm, sctio, - sctio->srr_id); - - if (imm == NULL) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02b, - "Not found matching IMM for SRR CTIO (id %d)\n", - sctio->srr_id); - continue; - } else - list_del(&sctio->srr_list_entry); - - spin_unlock_irqrestore(&tgt->srr_lock, flags); - - cmd = sctio->cmd; - /* - * Reset qla_tgt_cmd SRR values and SGL pointer+count to follow - * tcm_qla2xxx_write_pending() and tcm_qla2xxx_queue_data_in() - * logic.. - */ - cmd->offset = 0; - if (cmd->free_sg) { - kfree(cmd->sg); - cmd->sg = NULL; - cmd->free_sg = 0; - } - se_cmd = &cmd->se_cmd; - - cmd->sg_cnt = se_cmd->t_data_nents; - cmd->sg = se_cmd->t_data_sg; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c, - "SRR cmd %p (se_cmd %p, tag %d, op %x), " - "sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd, cmd->tag, - se_cmd->t_task_cdb[0], cmd->sg_cnt, cmd->offset); - - qlt_handle_srr(vha, sctio, imm); - - kfree(imm); - kfree(sctio); - goto restart; - } - spin_unlock_irqrestore(&tgt->srr_lock, flags); -} - -/* ha->hardware_lock supposed to be held on entry */ -static void qlt_prepare_srr_imm(struct scsi_qla_host *vha, - struct imm_ntfy_from_isp *iocb) -{ - struct qla_tgt_srr_imm *imm; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - struct qla_tgt_srr_ctio *sctio; - - tgt->imm_srr_id++; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02d, "qla_target(%d): SRR received\n", - vha->vp_idx); - - imm = kzalloc(sizeof(*imm), GFP_ATOMIC); - if (imm != NULL) { - memcpy(&imm->imm_ntfy, iocb, sizeof(imm->imm_ntfy)); - - /* IRQ is already OFF */ - spin_lock(&tgt->srr_lock); - imm->srr_id = tgt->imm_srr_id; - list_add_tail(&imm->srr_list_entry, - &tgt->srr_imm_list); - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02e, - "IMM NTFY SRR %p added (id %d, ui %x)\n", - imm, imm->srr_id, iocb->u.isp24.srr_ui); - if (tgt->imm_srr_id == tgt->ctio_srr_id) { - int found = 0; - list_for_each_entry(sctio, &tgt->srr_ctio_list, - srr_list_entry) { - if (sctio->srr_id == imm->srr_id) { - found = 1; - break; - } - } - if (found) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02f, "%s", - "Scheduling srr work\n"); - schedule_work(&tgt->srr_work); - } else { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf030, - "qla_target(%d): imm_srr_id " - "== ctio_srr_id (%d), but there is no " - "corresponding SRR CTIO, deleting IMM " - "SRR %p\n", vha->vp_idx, tgt->ctio_srr_id, - imm); - list_del(&imm->srr_list_entry); - - kfree(imm); - - spin_unlock(&tgt->srr_lock); - goto out_reject; - } - } - spin_unlock(&tgt->srr_lock); - } else { - struct qla_tgt_srr_ctio *ts; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf069, - "qla_target(%d): Unable to allocate SRR IMM " - "entry, SRR request will be rejected\n", vha->vp_idx); - - /* IRQ is already OFF */ - spin_lock(&tgt->srr_lock); - list_for_each_entry_safe(sctio, ts, &tgt->srr_ctio_list, - srr_list_entry) { - if (sctio->srr_id == tgt->imm_srr_id) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf031, - "CTIO SRR %p deleted (id %d)\n", - sctio, sctio->srr_id); - list_del(&sctio->srr_list_entry); - qlt_send_term_exchange(vha, sctio->cmd, - &sctio->cmd->atio, 1); - kfree(sctio); - } - } - spin_unlock(&tgt->srr_lock); - goto out_reject; - } - - return; - -out_reject: - qlt_send_notify_ack(vha, iocb, 0, 0, 0, - NOTIFY_ACK_SRR_FLAGS_REJECT, - NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM, - NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL); -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -static void qlt_handle_imm_notify(struct scsi_qla_host *vha, - struct imm_ntfy_from_isp *iocb) -{ - struct qla_hw_data *ha = vha->hw; - uint32_t add_flags = 0; - int send_notify_ack = 1; - uint16_t status; - - status = le16_to_cpu(iocb->u.isp2x.status); - switch (status) { - case IMM_NTFY_LIP_RESET: - { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf032, - "qla_target(%d): LIP reset (loop %#x), subcode %x\n", - vha->vp_idx, le16_to_cpu(iocb->u.isp24.nport_handle), - iocb->u.isp24.status_subcode); - - if (qlt_reset(vha, iocb, QLA_TGT_ABORT_ALL) == 0) - send_notify_ack = 0; - break; - } - - case IMM_NTFY_LIP_LINK_REINIT: - { - struct qla_tgt *tgt = ha->tgt.qla_tgt; - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf033, - "qla_target(%d): LINK REINIT (loop %#x, " - "subcode %x)\n", vha->vp_idx, - le16_to_cpu(iocb->u.isp24.nport_handle), - iocb->u.isp24.status_subcode); - if (tgt->link_reinit_iocb_pending) { - qlt_send_notify_ack(vha, &tgt->link_reinit_iocb, - 0, 0, 0, 0, 0, 0); - } - memcpy(&tgt->link_reinit_iocb, iocb, sizeof(*iocb)); - tgt->link_reinit_iocb_pending = 1; - /* - * QLogic requires to wait after LINK REINIT for possible - * PDISC or ADISC ELS commands - */ - send_notify_ack = 0; - break; - } - - case IMM_NTFY_PORT_LOGOUT: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf034, - "qla_target(%d): Port logout (loop " - "%#x, subcode %x)\n", vha->vp_idx, - le16_to_cpu(iocb->u.isp24.nport_handle), - iocb->u.isp24.status_subcode); - - if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS) == 0) - send_notify_ack = 0; - /* The sessions will be cleared in the callback, if needed */ - break; - - case IMM_NTFY_GLBL_TPRLO: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf035, - "qla_target(%d): Global TPRLO (%x)\n", vha->vp_idx, status); - if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS) == 0) - send_notify_ack = 0; - /* The sessions will be cleared in the callback, if needed */ - break; - - case IMM_NTFY_PORT_CONFIG: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf036, - "qla_target(%d): Port config changed (%x)\n", vha->vp_idx, - status); - if (qlt_reset(vha, iocb, QLA_TGT_ABORT_ALL) == 0) - send_notify_ack = 0; - /* The sessions will be cleared in the callback, if needed */ - break; - - case IMM_NTFY_GLBL_LOGO: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06a, - "qla_target(%d): Link failure detected\n", - vha->vp_idx); - /* I_T nexus loss */ - if (qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS) == 0) - send_notify_ack = 0; - break; - - case IMM_NTFY_IOCB_OVERFLOW: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06b, - "qla_target(%d): Cannot provide requested " - "capability (IOCB overflowed the immediate notify " - "resource count)\n", vha->vp_idx); - break; - - case IMM_NTFY_ABORT_TASK: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf037, - "qla_target(%d): Abort Task (S %08x I %#x -> " - "L %#x)\n", vha->vp_idx, - le16_to_cpu(iocb->u.isp2x.seq_id), - GET_TARGET_ID(ha, (struct atio_from_isp *)iocb), - le16_to_cpu(iocb->u.isp2x.lun)); - if (qlt_abort_task(vha, iocb) == 0) - send_notify_ack = 0; - break; - - case IMM_NTFY_RESOURCE: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06c, - "qla_target(%d): Out of resources, host %ld\n", - vha->vp_idx, vha->host_no); - break; - - case IMM_NTFY_MSG_RX: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf038, - "qla_target(%d): Immediate notify task %x\n", - vha->vp_idx, iocb->u.isp2x.task_flags); - if (qlt_handle_task_mgmt(vha, iocb) == 0) - send_notify_ack = 0; - break; - - case IMM_NTFY_ELS: - if (qlt_24xx_handle_els(vha, iocb) == 0) - send_notify_ack = 0; - break; - - case IMM_NTFY_SRR: - qlt_prepare_srr_imm(vha, iocb); - send_notify_ack = 0; - break; - - default: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06d, - "qla_target(%d): Received unknown immediate " - "notify status %x\n", vha->vp_idx, status); - break; - } - - if (send_notify_ack) - qlt_send_notify_ack(vha, iocb, add_flags, 0, 0, 0, 0, 0); -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - * This function sends busy to ISP 2xxx or 24xx. - */ -static void qlt_send_busy(struct scsi_qla_host *vha, - struct atio_from_isp *atio, uint16_t status) -{ - struct ctio7_to_24xx *ctio24; - struct qla_hw_data *ha = vha->hw; - request_t *pkt; - struct qla_tgt_sess *sess = NULL; - - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, - atio->u.isp24.fcp_hdr.s_id); - if (!sess) { - qlt_send_term_exchange(vha, NULL, atio, 1); - return; - } - /* Sending marker isn't necessary, since we called from ISR */ - - pkt = (request_t *)qla2x00_alloc_iocbs(vha, NULL); - if (!pkt) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06e, - "qla_target(%d): %s failed: unable to allocate " - "request packet", vha->vp_idx, __func__); - return; - } - - pkt->entry_count = 1; - pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; - - ctio24 = (struct ctio7_to_24xx *)pkt; - ctio24->entry_type = CTIO_TYPE7; - ctio24->nport_handle = sess->loop_id; - ctio24->timeout = __constant_cpu_to_le16(QLA_TGT_TIMEOUT); - ctio24->vp_index = vha->vp_idx; - ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2]; - ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1]; - ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0]; - ctio24->exchange_addr = atio->u.isp24.exchange_addr; - ctio24->u.status1.flags = (atio->u.isp24.attr << 9) | - __constant_cpu_to_le16( - CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS | - CTIO7_FLAGS_DONT_RET_CTIO); - /* - * CTIO from fw w/o se_cmd doesn't provide enough info to retry it, - * if the explicit conformation is used. - */ - ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id); - ctio24->u.status1.scsi_status = cpu_to_le16(status); - ctio24->u.status1.residual = get_unaligned((uint32_t *) - &atio->u.isp24.fcp_cmnd.add_cdb[ - atio->u.isp24.fcp_cmnd.add_cdb_len]); - if (ctio24->u.status1.residual != 0) - ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER; - - qla2x00_start_iocbs(vha, vha->req); -} - -/* ha->hardware_lock supposed to be held on entry */ -/* called via callback from qla2xxx */ -static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, - struct atio_from_isp *atio) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - int rc; - - if (unlikely(tgt == NULL)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf039, - "ATIO pkt, but no tgt (ha %p)", ha); - return; - } - ql_dbg(ql_dbg_tgt, vha, 0xe02c, - "qla_target(%d): ATIO pkt %p: type %02x count %02x", - vha->vp_idx, atio, atio->u.raw.entry_type, - atio->u.raw.entry_count); - /* - * In tgt_stop mode we also should allow all requests to pass. - * Otherwise, some commands can stuck. - */ - - tgt->irq_cmd_count++; - - switch (atio->u.raw.entry_type) { - case ATIO_TYPE7: - ql_dbg(ql_dbg_tgt, vha, 0xe02d, - "ATIO_TYPE7 instance %d, lun %Lx, read/write %d/%d, " - "add_cdb_len %d, data_length %04x, s_id %x:%x:%x\n", - vha->vp_idx, atio->u.isp24.fcp_cmnd.lun, - atio->u.isp24.fcp_cmnd.rddata, - atio->u.isp24.fcp_cmnd.wrdata, - atio->u.isp24.fcp_cmnd.add_cdb_len, - be32_to_cpu(get_unaligned((uint32_t *) - &atio->u.isp24.fcp_cmnd.add_cdb[ - atio->u.isp24.fcp_cmnd.add_cdb_len])), - atio->u.isp24.fcp_hdr.s_id[0], - atio->u.isp24.fcp_hdr.s_id[1], - atio->u.isp24.fcp_hdr.s_id[2]); - - if (unlikely(atio->u.isp24.exchange_addr == - ATIO_EXCHANGE_ADDRESS_UNKNOWN)) { - ql_dbg(ql_dbg_tgt, vha, 0xe058, - "qla_target(%d): ATIO_TYPE7 " - "received with UNKNOWN exchange address, " - "sending QUEUE_FULL\n", vha->vp_idx); - qlt_send_busy(vha, atio, SAM_STAT_TASK_SET_FULL); - break; - } - if (likely(atio->u.isp24.fcp_cmnd.task_mgmt_flags == 0)) - rc = qlt_handle_cmd_for_atio(vha, atio); - else - rc = qlt_handle_task_mgmt(vha, atio); - if (unlikely(rc != 0)) { - if (rc == -ESRCH) { -#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ - qlt_send_busy(vha, atio, SAM_STAT_BUSY); -#else - qlt_send_term_exchange(vha, NULL, atio, 1); -#endif - } else { - if (tgt->tgt_stop) { - ql_dbg(ql_dbg_tgt, vha, 0xe059, - "qla_target: Unable to send " - "command to target for req, " - "ignoring.\n"); - } else { - ql_dbg(ql_dbg_tgt, vha, 0xe05a, - "qla_target(%d): Unable to send " - "command to target, sending BUSY " - "status.\n", vha->vp_idx); - qlt_send_busy(vha, atio, SAM_STAT_BUSY); - } - } - } - break; - - case IMMED_NOTIFY_TYPE: - { - if (unlikely(atio->u.isp2x.entry_status != 0)) { - ql_dbg(ql_dbg_tgt, vha, 0xe05b, - "qla_target(%d): Received ATIO packet %x " - "with error status %x\n", vha->vp_idx, - atio->u.raw.entry_type, - atio->u.isp2x.entry_status); - break; - } - ql_dbg(ql_dbg_tgt, vha, 0xe02e, "%s", "IMMED_NOTIFY ATIO"); - qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)atio); - break; - } - - default: - ql_dbg(ql_dbg_tgt, vha, 0xe05c, - "qla_target(%d): Received unknown ATIO atio " - "type %x\n", vha->vp_idx, atio->u.raw.entry_type); - break; - } - - tgt->irq_cmd_count--; -} - -/* ha->hardware_lock supposed to be held on entry */ -/* called via callback from qla2xxx */ -static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - - if (unlikely(tgt == NULL)) { - ql_dbg(ql_dbg_tgt, vha, 0xe05d, - "qla_target(%d): Response pkt %x received, but no " - "tgt (ha %p)\n", vha->vp_idx, pkt->entry_type, ha); - return; - } - - ql_dbg(ql_dbg_tgt, vha, 0xe02f, - "qla_target(%d): response pkt %p: T %02x C %02x S %02x " - "handle %#x\n", vha->vp_idx, pkt, pkt->entry_type, - pkt->entry_count, pkt->entry_status, pkt->handle); - - /* - * In tgt_stop mode we also should allow all requests to pass. - * Otherwise, some commands can stuck. - */ - - tgt->irq_cmd_count++; - - switch (pkt->entry_type) { - case CTIO_TYPE7: - { - struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt; - ql_dbg(ql_dbg_tgt, vha, 0xe030, "CTIO_TYPE7: instance %d\n", - vha->vp_idx); - qlt_do_ctio_completion(vha, entry->handle, - le16_to_cpu(entry->status)|(pkt->entry_status << 16), - entry); - break; - } - - case ACCEPT_TGT_IO_TYPE: - { - struct atio_from_isp *atio = (struct atio_from_isp *)pkt; - int rc; - ql_dbg(ql_dbg_tgt, vha, 0xe031, - "ACCEPT_TGT_IO instance %d status %04x " - "lun %04x read/write %d data_length %04x " - "target_id %02x rx_id %04x\n ", vha->vp_idx, - le16_to_cpu(atio->u.isp2x.status), - le16_to_cpu(atio->u.isp2x.lun), - atio->u.isp2x.execution_codes, - le32_to_cpu(atio->u.isp2x.data_length), GET_TARGET_ID(ha, - atio), atio->u.isp2x.rx_id); - if (atio->u.isp2x.status != - __constant_cpu_to_le16(ATIO_CDB_VALID)) { - ql_dbg(ql_dbg_tgt, vha, 0xe05e, - "qla_target(%d): ATIO with error " - "status %x received\n", vha->vp_idx, - le16_to_cpu(atio->u.isp2x.status)); - break; - } - ql_dbg(ql_dbg_tgt, vha, 0xe032, - "FCP CDB: 0x%02x, sizeof(cdb): %lu", - atio->u.isp2x.cdb[0], (unsigned long - int)sizeof(atio->u.isp2x.cdb)); - - rc = qlt_handle_cmd_for_atio(vha, atio); - if (unlikely(rc != 0)) { - if (rc == -ESRCH) { -#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ - qlt_send_busy(vha, atio, 0); -#else - qlt_send_term_exchange(vha, NULL, atio, 1); -#endif - } else { - if (tgt->tgt_stop) { - ql_dbg(ql_dbg_tgt, vha, 0xe05f, - "qla_target: Unable to send " - "command to target, sending TERM " - "EXCHANGE for rsp\n"); - qlt_send_term_exchange(vha, NULL, - atio, 1); - } else { - ql_dbg(ql_dbg_tgt, vha, 0xe060, - "qla_target(%d): Unable to send " - "command to target, sending BUSY " - "status\n", vha->vp_idx); - qlt_send_busy(vha, atio, 0); - } - } - } - } - break; - - case CONTINUE_TGT_IO_TYPE: - { - struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt; - ql_dbg(ql_dbg_tgt, vha, 0xe033, - "CONTINUE_TGT_IO: instance %d\n", vha->vp_idx); - qlt_do_ctio_completion(vha, entry->handle, - le16_to_cpu(entry->status)|(pkt->entry_status << 16), - entry); - break; - } - - case CTIO_A64_TYPE: - { - struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt; - ql_dbg(ql_dbg_tgt, vha, 0xe034, "CTIO_A64: instance %d\n", - vha->vp_idx); - qlt_do_ctio_completion(vha, entry->handle, - le16_to_cpu(entry->status)|(pkt->entry_status << 16), - entry); - break; - } - - case IMMED_NOTIFY_TYPE: - ql_dbg(ql_dbg_tgt, vha, 0xe035, "%s", "IMMED_NOTIFY\n"); - qlt_handle_imm_notify(vha, (struct imm_ntfy_from_isp *)pkt); - break; - - case NOTIFY_ACK_TYPE: - if (tgt->notify_ack_expected > 0) { - struct nack_to_isp *entry = (struct nack_to_isp *)pkt; - ql_dbg(ql_dbg_tgt, vha, 0xe036, - "NOTIFY_ACK seq %08x status %x\n", - le16_to_cpu(entry->u.isp2x.seq_id), - le16_to_cpu(entry->u.isp2x.status)); - tgt->notify_ack_expected--; - if (entry->u.isp2x.status != - __constant_cpu_to_le16(NOTIFY_ACK_SUCCESS)) { - ql_dbg(ql_dbg_tgt, vha, 0xe061, - "qla_target(%d): NOTIFY_ACK " - "failed %x\n", vha->vp_idx, - le16_to_cpu(entry->u.isp2x.status)); - } - } else { - ql_dbg(ql_dbg_tgt, vha, 0xe062, - "qla_target(%d): Unexpected NOTIFY_ACK received\n", - vha->vp_idx); - } - break; - - case ABTS_RECV_24XX: - ql_dbg(ql_dbg_tgt, vha, 0xe037, - "ABTS_RECV_24XX: instance %d\n", vha->vp_idx); - qlt_24xx_handle_abts(vha, (struct abts_recv_from_24xx *)pkt); - break; - - case ABTS_RESP_24XX: - if (tgt->abts_resp_expected > 0) { - struct abts_resp_from_24xx_fw *entry = - (struct abts_resp_from_24xx_fw *)pkt; - ql_dbg(ql_dbg_tgt, vha, 0xe038, - "ABTS_RESP_24XX: compl_status %x\n", - entry->compl_status); - tgt->abts_resp_expected--; - if (le16_to_cpu(entry->compl_status) != - ABTS_RESP_COMPL_SUCCESS) { - if ((entry->error_subcode1 == 0x1E) && - (entry->error_subcode2 == 0)) { - /* - * We've got a race here: aborted - * exchange not terminated, i.e. - * response for the aborted command was - * sent between the abort request was - * received and processed. - * Unfortunately, the firmware has a - * silly requirement that all aborted - * exchanges must be explicitely - * terminated, otherwise it refuses to - * send responses for the abort - * requests. So, we have to - * (re)terminate the exchange and retry - * the abort response. - */ - qlt_24xx_retry_term_exchange(vha, - entry); - } else - ql_dbg(ql_dbg_tgt, vha, 0xe063, - "qla_target(%d): ABTS_RESP_24XX " - "failed %x (subcode %x:%x)", - vha->vp_idx, entry->compl_status, - entry->error_subcode1, - entry->error_subcode2); - } - } else { - ql_dbg(ql_dbg_tgt, vha, 0xe064, - "qla_target(%d): Unexpected ABTS_RESP_24XX " - "received\n", vha->vp_idx); - } - break; - - default: - ql_dbg(ql_dbg_tgt, vha, 0xe065, - "qla_target(%d): Received unknown response pkt " - "type %x\n", vha->vp_idx, pkt->entry_type); - break; - } - - tgt->irq_cmd_count--; -} - -/* - * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire - */ -void qlt_async_event(uint16_t code, struct scsi_qla_host *vha, - uint16_t *mailbox) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - int reason_code; - - ql_dbg(ql_dbg_tgt, vha, 0xe039, - "scsi(%ld): ha state %d init_done %d oper_mode %d topo %d\n", - vha->host_no, atomic_read(&vha->loop_state), vha->flags.init_done, - ha->operating_mode, ha->current_topology); - - if (!ha->tgt.tgt_ops) - return; - - if (unlikely(tgt == NULL)) { - ql_dbg(ql_dbg_tgt, vha, 0xe03a, - "ASYNC EVENT %#x, but no tgt (ha %p)\n", code, ha); - return; - } - - if (((code == MBA_POINT_TO_POINT) || (code == MBA_CHG_IN_CONNECTION)) && - IS_QLA2100(ha)) - return; - /* - * In tgt_stop mode we also should allow all requests to pass. - * Otherwise, some commands can stuck. - */ - - tgt->irq_cmd_count++; - - switch (code) { - case MBA_RESET: /* Reset */ - case MBA_SYSTEM_ERR: /* System Error */ - case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ - case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */ - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03a, - "qla_target(%d): System error async event %#x " - "occured", vha->vp_idx, code); - break; - case MBA_WAKEUP_THRES: /* Request Queue Wake-up. */ - set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); - break; - - case MBA_LOOP_UP: - { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03b, - "qla_target(%d): Async LOOP_UP occured " - "(m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", vha->vp_idx, - le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), - le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4])); - if (tgt->link_reinit_iocb_pending) { - qlt_send_notify_ack(vha, (void *)&tgt->link_reinit_iocb, - 0, 0, 0, 0, 0, 0); - tgt->link_reinit_iocb_pending = 0; - } - break; - } - - case MBA_LIP_OCCURRED: - case MBA_LOOP_DOWN: - case MBA_LIP_RESET: - case MBA_RSCN_UPDATE: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c, - "qla_target(%d): Async event %#x occured " - "(m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", vha->vp_idx, code, - le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), - le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4])); - break; - - case MBA_PORT_UPDATE: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03d, - "qla_target(%d): Port update async event %#x " - "occured: updating the ports database (m[1]=%x, m[2]=%x, " - "m[3]=%x, m[4]=%x)", vha->vp_idx, code, - le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), - le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4])); - reason_code = le16_to_cpu(mailbox[2]); - if (reason_code == 0x4) - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03e, - "Async MB 2: Got PLOGI Complete\n"); - else if (reason_code == 0x7) - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03f, - "Async MB 2: Port Logged Out\n"); - break; - - default: - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf040, - "qla_target(%d): Async event %#x occured: " - "ignore (m[1]=%x, m[2]=%x, m[3]=%x, m[4]=%x)", vha->vp_idx, - code, le16_to_cpu(mailbox[1]), le16_to_cpu(mailbox[2]), - le16_to_cpu(mailbox[3]), le16_to_cpu(mailbox[4])); - break; - } - - tgt->irq_cmd_count--; -} - -static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha, - uint16_t loop_id) -{ - fc_port_t *fcport; - int rc; - - fcport = kzalloc(sizeof(*fcport), GFP_KERNEL); - if (!fcport) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf06f, - "qla_target(%d): Allocation of tmp FC port failed", - vha->vp_idx); - return NULL; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf041, "loop_id %d", loop_id); - - fcport->loop_id = loop_id; - - rc = qla2x00_get_port_database(vha, fcport, 0); - if (rc != QLA_SUCCESS) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf070, - "qla_target(%d): Failed to retrieve fcport " - "information -- get_port_database() returned %x " - "(loop_id=0x%04x)", vha->vp_idx, rc, loop_id); - kfree(fcport); - return NULL; - } - - return fcport; -} - -/* Must be called under tgt_mutex */ -static struct qla_tgt_sess *qlt_make_local_sess(struct scsi_qla_host *vha, - uint8_t *s_id) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_sess *sess = NULL; - fc_port_t *fcport = NULL; - int rc, global_resets; - uint16_t loop_id = 0; - -retry: - global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); - - rc = qla24xx_get_loop_id(vha, s_id, &loop_id); - if (rc != 0) { - if ((s_id[0] == 0xFF) && - (s_id[1] == 0xFC)) { - /* - * This is Domain Controller, so it should be - * OK to drop SCSI commands from it. - */ - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf042, - "Unable to find initiator with S_ID %x:%x:%x", - s_id[0], s_id[1], s_id[2]); - } else - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf071, - "qla_target(%d): Unable to find " - "initiator with S_ID %x:%x:%x", - vha->vp_idx, s_id[0], s_id[1], - s_id[2]); - return NULL; - } - - fcport = qlt_get_port_database(vha, loop_id); - if (!fcport) - return NULL; - - if (global_resets != - atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf043, - "qla_target(%d): global reset during session discovery " - "(counter was %d, new %d), retrying", vha->vp_idx, - global_resets, - atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)); - goto retry; - } - - sess = qlt_create_sess(vha, fcport, true); - - kfree(fcport); - return sess; -} - -static void qlt_abort_work(struct qla_tgt *tgt, - struct qla_tgt_sess_work_param *prm) -{ - struct scsi_qla_host *vha = tgt->vha; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_sess *sess = NULL; - unsigned long flags; - uint32_t be_s_id; - uint8_t s_id[3]; - int rc; - - spin_lock_irqsave(&ha->hardware_lock, flags); - - if (tgt->tgt_stop) - goto out_term; - - s_id[0] = prm->abts.fcp_hdr_le.s_id[2]; - s_id[1] = prm->abts.fcp_hdr_le.s_id[1]; - s_id[2] = prm->abts.fcp_hdr_le.s_id[0]; - - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, - (unsigned char *)&be_s_id); - if (!sess) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - mutex_lock(&ha->tgt.tgt_mutex); - sess = qlt_make_local_sess(vha, s_id); - /* sess has got an extra creation ref */ - mutex_unlock(&ha->tgt.tgt_mutex); - - spin_lock_irqsave(&ha->hardware_lock, flags); - if (!sess) - goto out_term; - } else { - kref_get(&sess->se_sess->sess_kref); - } - - if (tgt->tgt_stop) - goto out_term; - - rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess); - if (rc != 0) - goto out_term; - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - ha->tgt.tgt_ops->put_sess(sess); - return; - -out_term: - qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (sess) - ha->tgt.tgt_ops->put_sess(sess); -} - -static void qlt_tmr_work(struct qla_tgt *tgt, - struct qla_tgt_sess_work_param *prm) -{ - struct atio_from_isp *a = &prm->tm_iocb2; - struct scsi_qla_host *vha = tgt->vha; - struct qla_hw_data *ha = vha->hw; - struct qla_tgt_sess *sess = NULL; - unsigned long flags; - uint8_t *s_id = NULL; /* to hide compiler warnings */ - int rc; - uint32_t lun, unpacked_lun; - int lun_size, fn; - void *iocb; - - spin_lock_irqsave(&ha->hardware_lock, flags); - - if (tgt->tgt_stop) - goto out_term; - - s_id = prm->tm_iocb2.u.isp24.fcp_hdr.s_id; - sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id); - if (!sess) { - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - mutex_lock(&ha->tgt.tgt_mutex); - sess = qlt_make_local_sess(vha, s_id); - /* sess has got an extra creation ref */ - mutex_unlock(&ha->tgt.tgt_mutex); - - spin_lock_irqsave(&ha->hardware_lock, flags); - if (!sess) - goto out_term; - } else { - kref_get(&sess->se_sess->sess_kref); - } - - iocb = a; - lun = a->u.isp24.fcp_cmnd.lun; - lun_size = sizeof(lun); - fn = a->u.isp24.fcp_cmnd.task_mgmt_flags; - unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun); - - rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); - if (rc != 0) - goto out_term; - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - ha->tgt.tgt_ops->put_sess(sess); - return; - -out_term: - qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (sess) - ha->tgt.tgt_ops->put_sess(sess); -} - -static void qlt_sess_work_fn(struct work_struct *work) -{ - struct qla_tgt *tgt = container_of(work, struct qla_tgt, sess_work); - struct scsi_qla_host *vha = tgt->vha; - unsigned long flags; - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf000, "Sess work (tgt %p)", tgt); - - spin_lock_irqsave(&tgt->sess_work_lock, flags); - while (!list_empty(&tgt->sess_works_list)) { - struct qla_tgt_sess_work_param *prm = list_entry( - tgt->sess_works_list.next, typeof(*prm), - sess_works_list_entry); - - /* - * This work can be scheduled on several CPUs at time, so we - * must delete the entry to eliminate double processing - */ - list_del(&prm->sess_works_list_entry); - - spin_unlock_irqrestore(&tgt->sess_work_lock, flags); - - switch (prm->type) { - case QLA_TGT_SESS_WORK_ABORT: - qlt_abort_work(tgt, prm); - break; - case QLA_TGT_SESS_WORK_TM: - qlt_tmr_work(tgt, prm); - break; - default: - BUG_ON(1); - break; - } - - spin_lock_irqsave(&tgt->sess_work_lock, flags); - - kfree(prm); - } - spin_unlock_irqrestore(&tgt->sess_work_lock, flags); -} - -/* Must be called under tgt_host_action_mutex */ -int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha) -{ - struct qla_tgt *tgt; - - if (!QLA_TGT_MODE_ENABLED()) - return 0; - - ql_dbg(ql_dbg_tgt, base_vha, 0xe03b, - "Registering target for host %ld(%p)", base_vha->host_no, ha); - - BUG_ON((ha->tgt.qla_tgt != NULL) || (ha->tgt.tgt_ops != NULL)); - - tgt = kzalloc(sizeof(struct qla_tgt), GFP_KERNEL); - if (!tgt) { - ql_dbg(ql_dbg_tgt, base_vha, 0xe066, - "Unable to allocate struct qla_tgt\n"); - return -ENOMEM; - } - - if (!(base_vha->host->hostt->supported_mode & MODE_TARGET)) - base_vha->host->hostt->supported_mode |= MODE_TARGET; - - tgt->ha = ha; - tgt->vha = base_vha; - init_waitqueue_head(&tgt->waitQ); - INIT_LIST_HEAD(&tgt->sess_list); - INIT_LIST_HEAD(&tgt->del_sess_list); - INIT_DELAYED_WORK(&tgt->sess_del_work, - (void (*)(struct work_struct *))qlt_del_sess_work_fn); - spin_lock_init(&tgt->sess_work_lock); - INIT_WORK(&tgt->sess_work, qlt_sess_work_fn); - INIT_LIST_HEAD(&tgt->sess_works_list); - spin_lock_init(&tgt->srr_lock); - INIT_LIST_HEAD(&tgt->srr_ctio_list); - INIT_LIST_HEAD(&tgt->srr_imm_list); - INIT_WORK(&tgt->srr_work, qlt_handle_srr_work); - atomic_set(&tgt->tgt_global_resets_count, 0); - - ha->tgt.qla_tgt = tgt; - - ql_dbg(ql_dbg_tgt, base_vha, 0xe067, - "qla_target(%d): using 64 Bit PCI addressing", - base_vha->vp_idx); - tgt->tgt_enable_64bit_addr = 1; - /* 3 is reserved */ - tgt->sg_tablesize = QLA_TGT_MAX_SG_24XX(base_vha->req->length - 3); - tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX; - tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX; - - mutex_lock(&qla_tgt_mutex); - list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist); - mutex_unlock(&qla_tgt_mutex); - - return 0; -} - -/* Must be called under tgt_host_action_mutex */ -int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha) -{ - if (!ha->tgt.qla_tgt) - return 0; - - mutex_lock(&qla_tgt_mutex); - list_del(&ha->tgt.qla_tgt->tgt_list_entry); - mutex_unlock(&qla_tgt_mutex); - - ql_dbg(ql_dbg_tgt, vha, 0xe03c, "Unregistering target for host %ld(%p)", - vha->host_no, ha); - qlt_release(ha->tgt.qla_tgt); - - return 0; -} - -static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn, - unsigned char *b) -{ - int i; - - pr_debug("qla2xxx HW vha->node_name: "); - for (i = 0; i < WWN_SIZE; i++) - pr_debug("%02x ", vha->node_name[i]); - pr_debug("\n"); - pr_debug("qla2xxx HW vha->port_name: "); - for (i = 0; i < WWN_SIZE; i++) - pr_debug("%02x ", vha->port_name[i]); - pr_debug("\n"); - - pr_debug("qla2xxx passed configfs WWPN: "); - put_unaligned_be64(wwpn, b); - for (i = 0; i < WWN_SIZE; i++) - pr_debug("%02x ", b[i]); - pr_debug("\n"); -} - -/** - * qla_tgt_lport_register - register lport with external module - * - * @qla_tgt_ops: Pointer for tcm_qla2xxx qla_tgt_ops - * @wwpn: Passwd FC target WWPN - * @callback: lport initialization callback for tcm_qla2xxx code - * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data - */ -int qlt_lport_register(struct qla_tgt_func_tmpl *qla_tgt_ops, u64 wwpn, - int (*callback)(struct scsi_qla_host *), void *target_lport_ptr) -{ - struct qla_tgt *tgt; - struct scsi_qla_host *vha; - struct qla_hw_data *ha; - struct Scsi_Host *host; - unsigned long flags; - int rc; - u8 b[WWN_SIZE]; - - mutex_lock(&qla_tgt_mutex); - list_for_each_entry(tgt, &qla_tgt_glist, tgt_list_entry) { - vha = tgt->vha; - ha = vha->hw; - - host = vha->host; - if (!host) - continue; - - if (ha->tgt.tgt_ops != NULL) - continue; - - if (!(host->hostt->supported_mode & MODE_TARGET)) - continue; - - spin_lock_irqsave(&ha->hardware_lock, flags); - if (host->active_mode & MODE_TARGET) { - pr_debug("MODE_TARGET already active on qla2xxx(%d)\n", - host->host_no); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - continue; - } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - if (!scsi_host_get(host)) { - ql_dbg(ql_dbg_tgt, vha, 0xe068, - "Unable to scsi_host_get() for" - " qla2xxx scsi_host\n"); - continue; - } - qlt_lport_dump(vha, wwpn, b); - - if (memcmp(vha->port_name, b, WWN_SIZE)) { - scsi_host_put(host); - continue; - } - /* - * Setup passed parameters ahead of invoking callback - */ - ha->tgt.tgt_ops = qla_tgt_ops; - ha->tgt.target_lport_ptr = target_lport_ptr; - rc = (*callback)(vha); - if (rc != 0) { - ha->tgt.tgt_ops = NULL; - ha->tgt.target_lport_ptr = NULL; - } - mutex_unlock(&qla_tgt_mutex); - return rc; - } - mutex_unlock(&qla_tgt_mutex); - - return -ENODEV; -} -EXPORT_SYMBOL(qlt_lport_register); - -/** - * qla_tgt_lport_deregister - Degister lport - * - * @vha: Registered scsi_qla_host pointer - */ -void qlt_lport_deregister(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - struct Scsi_Host *sh = vha->host; - /* - * Clear the target_lport_ptr qla_target_template pointer in qla_hw_data - */ - ha->tgt.target_lport_ptr = NULL; - ha->tgt.tgt_ops = NULL; - /* - * Release the Scsi_Host reference for the underlying qla2xxx host - */ - scsi_host_put(sh); -} -EXPORT_SYMBOL(qlt_lport_deregister); - -/* Must be called under HW lock */ -void qlt_set_mode(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - - switch (ql2x_ini_mode) { - case QLA2XXX_INI_MODE_DISABLED: - case QLA2XXX_INI_MODE_EXCLUSIVE: - vha->host->active_mode = MODE_TARGET; - break; - case QLA2XXX_INI_MODE_ENABLED: - vha->host->active_mode |= MODE_TARGET; - break; - default: - break; - } - - if (ha->tgt.ini_mode_force_reverse) - qla_reverse_ini_mode(vha); -} - -/* Must be called under HW lock */ -void qlt_clear_mode(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - - switch (ql2x_ini_mode) { - case QLA2XXX_INI_MODE_DISABLED: - vha->host->active_mode = MODE_UNKNOWN; - break; - case QLA2XXX_INI_MODE_EXCLUSIVE: - vha->host->active_mode = MODE_INITIATOR; - break; - case QLA2XXX_INI_MODE_ENABLED: - vha->host->active_mode &= ~MODE_TARGET; - break; - default: - break; - } - - if (ha->tgt.ini_mode_force_reverse) - qla_reverse_ini_mode(vha); -} - -/* - * qla_tgt_enable_vha - NO LOCK HELD - * - * host_reset, bring up w/ Target Mode Enabled - */ -void -qlt_enable_vha(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - unsigned long flags; - - if (!tgt) { - ql_dbg(ql_dbg_tgt, vha, 0xe069, - "Unable to locate qla_tgt pointer from" - " struct qla_hw_data\n"); - dump_stack(); - return; - } - - spin_lock_irqsave(&ha->hardware_lock, flags); - tgt->tgt_stopped = 0; - qlt_set_mode(vha); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); - qla2xxx_wake_dpc(vha); - qla2x00_wait_for_hba_online(vha); -} -EXPORT_SYMBOL(qlt_enable_vha); - -/* - * qla_tgt_disable_vha - NO LOCK HELD - * - * Disable Target Mode and reset the adapter - */ -void -qlt_disable_vha(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_tgt *tgt = ha->tgt.qla_tgt; - unsigned long flags; - - if (!tgt) { - ql_dbg(ql_dbg_tgt, vha, 0xe06a, - "Unable to locate qla_tgt pointer from" - " struct qla_hw_data\n"); - dump_stack(); - return; - } - - spin_lock_irqsave(&ha->hardware_lock, flags); - qlt_clear_mode(vha); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); - qla2xxx_wake_dpc(vha); - qla2x00_wait_for_hba_online(vha); -} - -/* - * Called from qla_init.c:qla24xx_vport_create() contex to setup - * the target mode specific struct scsi_qla_host and struct qla_hw_data - * members. - */ -void -qlt_vport_create(struct scsi_qla_host *vha, struct qla_hw_data *ha) -{ - if (!qla_tgt_mode_enabled(vha)) - return; - - mutex_init(&ha->tgt.tgt_mutex); - mutex_init(&ha->tgt.tgt_host_action_mutex); - - qlt_clear_mode(vha); - - /* - * NOTE: Currently the value is kept the same for <24xx and - * >=24xx ISPs. If it is necessary to change it, - * the check should be added for specific ISPs, - * assigning the value appropriately. - */ - ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; -} - -void -qlt_rff_id(struct scsi_qla_host *vha, struct ct_sns_req *ct_req) -{ - /* - * FC-4 Feature bit 0 indicates target functionality to the name server. - */ - if (qla_tgt_mode_enabled(vha)) { - if (qla_ini_mode_enabled(vha)) - ct_req->req.rff_id.fc4_feature = BIT_0 | BIT_1; - else - ct_req->req.rff_id.fc4_feature = BIT_0; - } else if (qla_ini_mode_enabled(vha)) { - ct_req->req.rff_id.fc4_feature = BIT_1; - } -} - -/* - * qlt_init_atio_q_entries() - Initializes ATIO queue entries. - * @ha: HA context - * - * Beginning of ATIO ring has initialization control block already built - * by nvram config routine. - * - * Returns 0 on success. - */ -void -qlt_init_atio_q_entries(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - uint16_t cnt; - struct atio_from_isp *pkt = (struct atio_from_isp *)ha->tgt.atio_ring; - - if (!qla_tgt_mode_enabled(vha)) - return; - - for (cnt = 0; cnt < ha->tgt.atio_q_length; cnt++) { - pkt->u.raw.signature = ATIO_PROCESSED; - pkt++; - } - -} - -/* - * qlt_24xx_process_atio_queue() - Process ATIO queue entries. - * @ha: SCSI driver HA context - */ -void -qlt_24xx_process_atio_queue(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; - struct atio_from_isp *pkt; - int cnt, i; - - if (!vha->flags.online) - return; - - while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) { - pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr; - cnt = pkt->u.raw.entry_count; - - qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt); - - for (i = 0; i < cnt; i++) { - ha->tgt.atio_ring_index++; - if (ha->tgt.atio_ring_index == ha->tgt.atio_q_length) { - ha->tgt.atio_ring_index = 0; - ha->tgt.atio_ring_ptr = ha->tgt.atio_ring; - } else - ha->tgt.atio_ring_ptr++; - - pkt->u.raw.signature = ATIO_PROCESSED; - pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr; - } - wmb(); - } - - /* Adjust ring index */ - WRT_REG_DWORD(®->atio_q_out, ha->tgt.atio_ring_index); -} - -void -qlt_24xx_config_rings(struct scsi_qla_host *vha, device_reg_t __iomem *reg) -{ - struct qla_hw_data *ha = vha->hw; - -/* FIXME: atio_q in/out for ha->mqenable=1..? */ - if (ha->mqenable) { -#if 0 - WRT_REG_DWORD(®->isp25mq.atio_q_in, 0); - WRT_REG_DWORD(®->isp25mq.atio_q_out, 0); - RD_REG_DWORD(®->isp25mq.atio_q_out); -#endif - } else { - /* Setup APTIO registers for target mode */ - WRT_REG_DWORD(®->isp24.atio_q_in, 0); - WRT_REG_DWORD(®->isp24.atio_q_out, 0); - RD_REG_DWORD(®->isp24.atio_q_out); - } -} - -void -qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv) -{ - struct qla_hw_data *ha = vha->hw; - - if (qla_tgt_mode_enabled(vha)) { - if (!ha->tgt.saved_set) { - /* We save only once */ - ha->tgt.saved_exchange_count = nv->exchange_count; - ha->tgt.saved_firmware_options_1 = - nv->firmware_options_1; - ha->tgt.saved_firmware_options_2 = - nv->firmware_options_2; - ha->tgt.saved_firmware_options_3 = - nv->firmware_options_3; - ha->tgt.saved_set = 1; - } - - nv->exchange_count = __constant_cpu_to_le16(0xFFFF); - - /* Enable target mode */ - nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_4); - - /* Disable ini mode, if requested */ - if (!qla_ini_mode_enabled(vha)) - nv->firmware_options_1 |= __constant_cpu_to_le32(BIT_5); - - /* Disable Full Login after LIP */ - nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_13); - /* Enable initial LIP */ - nv->firmware_options_1 &= __constant_cpu_to_le32(~BIT_9); - /* Enable FC tapes support */ - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12); - /* Disable Full Login after LIP */ - nv->host_p &= __constant_cpu_to_le32(~BIT_10); - /* Enable target PRLI control */ - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_14); - } else { - if (ha->tgt.saved_set) { - nv->exchange_count = ha->tgt.saved_exchange_count; - nv->firmware_options_1 = - ha->tgt.saved_firmware_options_1; - nv->firmware_options_2 = - ha->tgt.saved_firmware_options_2; - nv->firmware_options_3 = - ha->tgt.saved_firmware_options_3; - } - return; - } - - /* out-of-order frames reassembly */ - nv->firmware_options_3 |= BIT_6|BIT_9; - - if (ha->tgt.enable_class_2) { - if (vha->flags.init_done) - fc_host_supported_classes(vha->host) = - FC_COS_CLASS2 | FC_COS_CLASS3; - - nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_8); - } else { - if (vha->flags.init_done) - fc_host_supported_classes(vha->host) = FC_COS_CLASS3; - - nv->firmware_options_2 &= ~__constant_cpu_to_le32(BIT_8); - } -} - -void -qlt_24xx_config_nvram_stage2(struct scsi_qla_host *vha, - struct init_cb_24xx *icb) -{ - struct qla_hw_data *ha = vha->hw; - - if (ha->tgt.node_name_set) { - memcpy(icb->node_name, ha->tgt.tgt_node_name, WWN_SIZE); - icb->firmware_options_1 |= __constant_cpu_to_le32(BIT_14); - } -} - -int -qlt_24xx_process_response_error(struct scsi_qla_host *vha, - struct sts_entry_24xx *pkt) -{ - switch (pkt->entry_type) { - case ABTS_RECV_24XX: - case ABTS_RESP_24XX: - case CTIO_TYPE7: - case NOTIFY_ACK_TYPE: - return 1; - default: - return 0; - } -} - -void -qlt_modify_vp_config(struct scsi_qla_host *vha, - struct vp_config_entry_24xx *vpmod) -{ - if (qla_tgt_mode_enabled(vha)) - vpmod->options_idx1 &= ~BIT_5; - /* Disable ini mode, if requested */ - if (!qla_ini_mode_enabled(vha)) - vpmod->options_idx1 &= ~BIT_4; -} - -void -qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) -{ - if (!QLA_TGT_MODE_ENABLED()) - return; - - mutex_init(&ha->tgt.tgt_mutex); - mutex_init(&ha->tgt.tgt_host_action_mutex); - qlt_clear_mode(base_vha); -} - -int -qlt_mem_alloc(struct qla_hw_data *ha) -{ - if (!QLA_TGT_MODE_ENABLED()) - return 0; - - ha->tgt.tgt_vp_map = kzalloc(sizeof(struct qla_tgt_vp_map) * - MAX_MULTI_ID_FABRIC, GFP_KERNEL); - if (!ha->tgt.tgt_vp_map) - return -ENOMEM; - - ha->tgt.atio_ring = dma_alloc_coherent(&ha->pdev->dev, - (ha->tgt.atio_q_length + 1) * sizeof(struct atio_from_isp), - &ha->tgt.atio_dma, GFP_KERNEL); - if (!ha->tgt.atio_ring) { - kfree(ha->tgt.tgt_vp_map); - return -ENOMEM; - } - return 0; -} - -void -qlt_mem_free(struct qla_hw_data *ha) -{ - if (!QLA_TGT_MODE_ENABLED()) - return; - - if (ha->tgt.atio_ring) { - dma_free_coherent(&ha->pdev->dev, (ha->tgt.atio_q_length + 1) * - sizeof(struct atio_from_isp), ha->tgt.atio_ring, - ha->tgt.atio_dma); - } - kfree(ha->tgt.tgt_vp_map); -} - -/* vport_slock to be held by the caller */ -void -qlt_update_vp_map(struct scsi_qla_host *vha, int cmd) -{ - if (!QLA_TGT_MODE_ENABLED()) - return; - - switch (cmd) { - case SET_VP_IDX: - vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = vha; - break; - case SET_AL_PA: - vha->hw->tgt.tgt_vp_map[vha->d_id.b.al_pa].idx = vha->vp_idx; - break; - case RESET_VP_IDX: - vha->hw->tgt.tgt_vp_map[vha->vp_idx].vha = NULL; - break; - case RESET_AL_PA: - vha->hw->tgt.tgt_vp_map[vha->d_id.b.al_pa].idx = 0; - break; - } -} - -static int __init qlt_parse_ini_mode(void) -{ - if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_EXCLUSIVE) == 0) - ql2x_ini_mode = QLA2XXX_INI_MODE_EXCLUSIVE; - else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_DISABLED) == 0) - ql2x_ini_mode = QLA2XXX_INI_MODE_DISABLED; - else if (strcasecmp(qlini_mode, QLA2XXX_INI_MODE_STR_ENABLED) == 0) - ql2x_ini_mode = QLA2XXX_INI_MODE_ENABLED; - else - return false; - - return true; -} - -int __init qlt_init(void) -{ - int ret; - - if (!qlt_parse_ini_mode()) { - ql_log(ql_log_fatal, NULL, 0xe06b, - "qlt_parse_ini_mode() failed\n"); - return -EINVAL; - } - - if (!QLA_TGT_MODE_ENABLED()) - return 0; - - qla_tgt_cmd_cachep = kmem_cache_create("qla_tgt_cmd_cachep", - sizeof(struct qla_tgt_cmd), __alignof__(struct qla_tgt_cmd), 0, - NULL); - if (!qla_tgt_cmd_cachep) { - ql_log(ql_log_fatal, NULL, 0xe06c, - "kmem_cache_create for qla_tgt_cmd_cachep failed\n"); - return -ENOMEM; - } - - qla_tgt_mgmt_cmd_cachep = kmem_cache_create("qla_tgt_mgmt_cmd_cachep", - sizeof(struct qla_tgt_mgmt_cmd), __alignof__(struct - qla_tgt_mgmt_cmd), 0, NULL); - if (!qla_tgt_mgmt_cmd_cachep) { - ql_log(ql_log_fatal, NULL, 0xe06d, - "kmem_cache_create for qla_tgt_mgmt_cmd_cachep failed\n"); - ret = -ENOMEM; - goto out; - } - - qla_tgt_mgmt_cmd_mempool = mempool_create(25, mempool_alloc_slab, - mempool_free_slab, qla_tgt_mgmt_cmd_cachep); - if (!qla_tgt_mgmt_cmd_mempool) { - ql_log(ql_log_fatal, NULL, 0xe06e, - "mempool_create for qla_tgt_mgmt_cmd_mempool failed\n"); - ret = -ENOMEM; - goto out_mgmt_cmd_cachep; - } - - qla_tgt_wq = alloc_workqueue("qla_tgt_wq", 0, 0); - if (!qla_tgt_wq) { - ql_log(ql_log_fatal, NULL, 0xe06f, - "alloc_workqueue for qla_tgt_wq failed\n"); - ret = -ENOMEM; - goto out_cmd_mempool; - } - /* - * Return 1 to signal that initiator-mode is being disabled - */ - return (ql2x_ini_mode == QLA2XXX_INI_MODE_DISABLED) ? 1 : 0; - -out_cmd_mempool: - mempool_destroy(qla_tgt_mgmt_cmd_mempool); -out_mgmt_cmd_cachep: - kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep); -out: - kmem_cache_destroy(qla_tgt_cmd_cachep); - return ret; -} - -void qlt_exit(void) -{ - if (!QLA_TGT_MODE_ENABLED()) - return; - - destroy_workqueue(qla_tgt_wq); - mempool_destroy(qla_tgt_mgmt_cmd_mempool); - kmem_cache_destroy(qla_tgt_mgmt_cmd_cachep); - kmem_cache_destroy(qla_tgt_cmd_cachep); -} diff --git a/trunk/drivers/scsi/qla2xxx/qla_target.h b/trunk/drivers/scsi/qla2xxx/qla_target.h deleted file mode 100644 index 9f9ef1644fd9..000000000000 --- a/trunk/drivers/scsi/qla2xxx/qla_target.h +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * Copyright (C) 2004 - 2010 Vladislav Bolkhovitin - * Copyright (C) 2004 - 2005 Leonid Stoljar - * Copyright (C) 2006 Nathaniel Clark - * Copyright (C) 2007 - 2010 ID7 Ltd. - * - * Forward port and refactoring to modern qla2xxx and target/configfs - * - * Copyright (C) 2010-2011 Nicholas A. Bellinger - * - * Additional file for the target driver support. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -/* - * This is the global def file that is useful for including from the - * target portion. - */ - -#ifndef __QLA_TARGET_H -#define __QLA_TARGET_H - -#include "qla_def.h" - -/* - * Must be changed on any change in any initiator visible interfaces or - * data in the target add-on - */ -#define QLA2XXX_TARGET_MAGIC 269 - -/* - * Must be changed on any change in any target visible interfaces or - * data in the initiator - */ -#define QLA2XXX_INITIATOR_MAGIC 57222 - -#define QLA2XXX_INI_MODE_STR_EXCLUSIVE "exclusive" -#define QLA2XXX_INI_MODE_STR_DISABLED "disabled" -#define QLA2XXX_INI_MODE_STR_ENABLED "enabled" - -#define QLA2XXX_INI_MODE_EXCLUSIVE 0 -#define QLA2XXX_INI_MODE_DISABLED 1 -#define QLA2XXX_INI_MODE_ENABLED 2 - -#define QLA2XXX_COMMAND_COUNT_INIT 250 -#define QLA2XXX_IMMED_NOTIFY_COUNT_INIT 250 - -/* - * Used to mark which completion handles (for RIO Status's) are for CTIO's - * vs. regular (non-target) info. This is checked for in - * qla2x00_process_response_queue() to see if a handle coming back in a - * multi-complete should come to the tgt driver or be handled there by qla2xxx - */ -#define CTIO_COMPLETION_HANDLE_MARK BIT_29 -#if (CTIO_COMPLETION_HANDLE_MARK <= MAX_OUTSTANDING_COMMANDS) -#error "CTIO_COMPLETION_HANDLE_MARK not larger than MAX_OUTSTANDING_COMMANDS" -#endif -#define HANDLE_IS_CTIO_COMP(h) (h & CTIO_COMPLETION_HANDLE_MARK) - -/* Used to mark CTIO as intermediate */ -#define CTIO_INTERMEDIATE_HANDLE_MARK BIT_30 - -#ifndef OF_SS_MODE_0 -/* - * ISP target entries - Flags bit definitions. - */ -#define OF_SS_MODE_0 0 -#define OF_SS_MODE_1 1 -#define OF_SS_MODE_2 2 -#define OF_SS_MODE_3 3 - -#define OF_EXPL_CONF BIT_5 /* Explicit Confirmation Requested */ -#define OF_DATA_IN BIT_6 /* Data in to initiator */ - /* (data from target to initiator) */ -#define OF_DATA_OUT BIT_7 /* Data out from initiator */ - /* (data from initiator to target) */ -#define OF_NO_DATA (BIT_7 | BIT_6) -#define OF_INC_RC BIT_8 /* Increment command resource count */ -#define OF_FAST_POST BIT_9 /* Enable mailbox fast posting. */ -#define OF_CONF_REQ BIT_13 /* Confirmation Requested */ -#define OF_TERM_EXCH BIT_14 /* Terminate exchange */ -#define OF_SSTS BIT_15 /* Send SCSI status */ -#endif - -#ifndef QLA_TGT_DATASEGS_PER_CMD32 -#define QLA_TGT_DATASEGS_PER_CMD32 3 -#define QLA_TGT_DATASEGS_PER_CONT32 7 -#define QLA_TGT_MAX_SG32(ql) \ - (((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD32 + \ - QLA_TGT_DATASEGS_PER_CONT32*((ql) - 1)) : 0) - -#define QLA_TGT_DATASEGS_PER_CMD64 2 -#define QLA_TGT_DATASEGS_PER_CONT64 5 -#define QLA_TGT_MAX_SG64(ql) \ - (((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD64 + \ - QLA_TGT_DATASEGS_PER_CONT64*((ql) - 1)) : 0) -#endif - -#ifndef QLA_TGT_DATASEGS_PER_CMD_24XX -#define QLA_TGT_DATASEGS_PER_CMD_24XX 1 -#define QLA_TGT_DATASEGS_PER_CONT_24XX 5 -#define QLA_TGT_MAX_SG_24XX(ql) \ - (min(1270, ((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD_24XX + \ - QLA_TGT_DATASEGS_PER_CONT_24XX*((ql) - 1)) : 0)) -#endif -#endif - -#define GET_TARGET_ID(ha, iocb) ((HAS_EXTENDED_IDS(ha)) \ - ? le16_to_cpu((iocb)->u.isp2x.target.extended) \ - : (uint16_t)(iocb)->u.isp2x.target.id.standard) - -#ifndef IMMED_NOTIFY_TYPE -#define IMMED_NOTIFY_TYPE 0x0D /* Immediate notify entry. */ -/* - * ISP queue - immediate notify entry structure definition. - * This is sent by the ISP to the Target driver. - * This IOCB would have report of events sent by the - * initiator, that needs to be handled by the target - * driver immediately. - */ -struct imm_ntfy_from_isp { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - union { - struct { - uint32_t sys_define_2; /* System defined. */ - target_id_t target; - uint16_t lun; - uint8_t target_id; - uint8_t reserved_1; - uint16_t status_modifier; - uint16_t status; - uint16_t task_flags; - uint16_t seq_id; - uint16_t srr_rx_id; - uint32_t srr_rel_offs; - uint16_t srr_ui; -#define SRR_IU_DATA_IN 0x1 -#define SRR_IU_DATA_OUT 0x5 -#define SRR_IU_STATUS 0x7 - uint16_t srr_ox_id; - uint8_t reserved_2[28]; - } isp2x; - struct { - uint32_t reserved; - uint16_t nport_handle; - uint16_t reserved_2; - uint16_t flags; -#define NOTIFY24XX_FLAGS_GLOBAL_TPRLO BIT_1 -#define NOTIFY24XX_FLAGS_PUREX_IOCB BIT_0 - uint16_t srr_rx_id; - uint16_t status; - uint8_t status_subcode; - uint8_t reserved_3; - uint32_t exchange_address; - uint32_t srr_rel_offs; - uint16_t srr_ui; - uint16_t srr_ox_id; - uint8_t reserved_4[19]; - uint8_t vp_index; - uint32_t reserved_5; - uint8_t port_id[3]; - uint8_t reserved_6; - } isp24; - } u; - uint16_t reserved_7; - uint16_t ox_id; -} __packed; -#endif - -#ifndef NOTIFY_ACK_TYPE -#define NOTIFY_ACK_TYPE 0x0E /* Notify acknowledge entry. */ -/* - * ISP queue - notify acknowledge entry structure definition. - * This is sent to the ISP from the target driver. - */ -struct nack_to_isp { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - union { - struct { - uint32_t sys_define_2; /* System defined. */ - target_id_t target; - uint8_t target_id; - uint8_t reserved_1; - uint16_t flags; - uint16_t resp_code; - uint16_t status; - uint16_t task_flags; - uint16_t seq_id; - uint16_t srr_rx_id; - uint32_t srr_rel_offs; - uint16_t srr_ui; - uint16_t srr_flags; - uint16_t srr_reject_code; - uint8_t srr_reject_vendor_uniq; - uint8_t srr_reject_code_expl; - uint8_t reserved_2[24]; - } isp2x; - struct { - uint32_t handle; - uint16_t nport_handle; - uint16_t reserved_1; - uint16_t flags; - uint16_t srr_rx_id; - uint16_t status; - uint8_t status_subcode; - uint8_t reserved_3; - uint32_t exchange_address; - uint32_t srr_rel_offs; - uint16_t srr_ui; - uint16_t srr_flags; - uint8_t reserved_4[19]; - uint8_t vp_index; - uint8_t srr_reject_vendor_uniq; - uint8_t srr_reject_code_expl; - uint8_t srr_reject_code; - uint8_t reserved_5[5]; - } isp24; - } u; - uint8_t reserved[2]; - uint16_t ox_id; -} __packed; -#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0 -#define NOTIFY_ACK_SRR_FLAGS_REJECT 1 - -#define NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM 0x9 - -#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL 0 -#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_UNABLE_TO_SUPPLY_DATA 0x2a - -#define NOTIFY_ACK_SUCCESS 0x01 -#endif - -#ifndef ACCEPT_TGT_IO_TYPE -#define ACCEPT_TGT_IO_TYPE 0x16 /* Accept target I/O entry. */ -#endif - -#ifndef CONTINUE_TGT_IO_TYPE -#define CONTINUE_TGT_IO_TYPE 0x17 -/* - * ISP queue - Continue Target I/O (CTIO) entry for status mode 0 structure. - * This structure is sent to the ISP 2xxx from target driver. - */ -struct ctio_to_2xxx { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System defined handle */ - target_id_t target; - uint16_t rx_id; - uint16_t flags; - uint16_t status; - uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */ - uint16_t dseg_count; /* Data segment count. */ - uint32_t relative_offset; - uint32_t residual; - uint16_t reserved_1[3]; - uint16_t scsi_status; - uint32_t transfer_length; - uint32_t dseg_0_address; /* Data segment 0 address. */ - uint32_t dseg_0_length; /* Data segment 0 length. */ - uint32_t dseg_1_address; /* Data segment 1 address. */ - uint32_t dseg_1_length; /* Data segment 1 length. */ - uint32_t dseg_2_address; /* Data segment 2 address. */ - uint32_t dseg_2_length; /* Data segment 2 length. */ -} __packed; -#define ATIO_PATH_INVALID 0x07 -#define ATIO_CANT_PROV_CAP 0x16 -#define ATIO_CDB_VALID 0x3D - -#define ATIO_EXEC_READ BIT_1 -#define ATIO_EXEC_WRITE BIT_0 -#endif - -#ifndef CTIO_A64_TYPE -#define CTIO_A64_TYPE 0x1F -#define CTIO_SUCCESS 0x01 -#define CTIO_ABORTED 0x02 -#define CTIO_INVALID_RX_ID 0x08 -#define CTIO_TIMEOUT 0x0B -#define CTIO_LIP_RESET 0x0E -#define CTIO_TARGET_RESET 0x17 -#define CTIO_PORT_UNAVAILABLE 0x28 -#define CTIO_PORT_LOGGED_OUT 0x29 -#define CTIO_PORT_CONF_CHANGED 0x2A -#define CTIO_SRR_RECEIVED 0x45 -#endif - -#ifndef CTIO_RET_TYPE -#define CTIO_RET_TYPE 0x17 /* CTIO return entry */ -#define ATIO_TYPE7 0x06 /* Accept target I/O entry for 24xx */ - -struct fcp_hdr { - uint8_t r_ctl; - uint8_t d_id[3]; - uint8_t cs_ctl; - uint8_t s_id[3]; - uint8_t type; - uint8_t f_ctl[3]; - uint8_t seq_id; - uint8_t df_ctl; - uint16_t seq_cnt; - uint16_t ox_id; - uint16_t rx_id; - uint32_t parameter; -} __packed; - -struct fcp_hdr_le { - uint8_t d_id[3]; - uint8_t r_ctl; - uint8_t s_id[3]; - uint8_t cs_ctl; - uint8_t f_ctl[3]; - uint8_t type; - uint16_t seq_cnt; - uint8_t df_ctl; - uint8_t seq_id; - uint16_t rx_id; - uint16_t ox_id; - uint32_t parameter; -} __packed; - -#define F_CTL_EXCH_CONTEXT_RESP BIT_23 -#define F_CTL_SEQ_CONTEXT_RESIP BIT_22 -#define F_CTL_LAST_SEQ BIT_20 -#define F_CTL_END_SEQ BIT_19 -#define F_CTL_SEQ_INITIATIVE BIT_16 - -#define R_CTL_BASIC_LINK_SERV 0x80 -#define R_CTL_B_ACC 0x4 -#define R_CTL_B_RJT 0x5 - -struct atio7_fcp_cmnd { - uint64_t lun; - uint8_t cmnd_ref; - uint8_t task_attr:3; - uint8_t reserved:5; - uint8_t task_mgmt_flags; -#define FCP_CMND_TASK_MGMT_CLEAR_ACA 6 -#define FCP_CMND_TASK_MGMT_TARGET_RESET 5 -#define FCP_CMND_TASK_MGMT_LU_RESET 4 -#define FCP_CMND_TASK_MGMT_CLEAR_TASK_SET 2 -#define FCP_CMND_TASK_MGMT_ABORT_TASK_SET 1 - uint8_t wrdata:1; - uint8_t rddata:1; - uint8_t add_cdb_len:6; - uint8_t cdb[16]; - /* - * add_cdb is optional and can absent from struct atio7_fcp_cmnd. Size 4 - * only to make sizeof(struct atio7_fcp_cmnd) be as expected by - * BUILD_BUG_ON in qlt_init(). - */ - uint8_t add_cdb[4]; - /* uint32_t data_length; */ -} __packed; - -/* - * ISP queue - Accept Target I/O (ATIO) type entry IOCB structure. - * This is sent from the ISP to the target driver. - */ -struct atio_from_isp { - union { - struct { - uint16_t entry_hdr; - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t sys_define_2; /* System defined. */ - target_id_t target; - uint16_t rx_id; - uint16_t flags; - uint16_t status; - uint8_t command_ref; - uint8_t task_codes; - uint8_t task_flags; - uint8_t execution_codes; - uint8_t cdb[MAX_CMDSZ]; - uint32_t data_length; - uint16_t lun; - uint8_t initiator_port_name[WWN_SIZE]; /* on qla23xx */ - uint16_t reserved_32[6]; - uint16_t ox_id; - } isp2x; - struct { - uint16_t entry_hdr; - uint8_t fcp_cmnd_len_low; - uint8_t fcp_cmnd_len_high:4; - uint8_t attr:4; - uint32_t exchange_addr; -#define ATIO_EXCHANGE_ADDRESS_UNKNOWN 0xFFFFFFFF - struct fcp_hdr fcp_hdr; - struct atio7_fcp_cmnd fcp_cmnd; - } isp24; - struct { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t data[58]; - uint32_t signature; -#define ATIO_PROCESSED 0xDEADDEAD /* Signature */ - } raw; - } u; -} __packed; - -#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */ - -/* - * ISP queue - Continue Target I/O (ATIO) type 7 entry (for 24xx) structure. - * This structure is sent to the ISP 24xx from the target driver. - */ - -struct ctio7_to_24xx { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System defined handle */ - uint16_t nport_handle; -#define CTIO7_NHANDLE_UNRECOGNIZED 0xFFFF - uint16_t timeout; - uint16_t dseg_count; /* Data segment count. */ - uint8_t vp_index; - uint8_t add_flags; - uint8_t initiator_id[3]; - uint8_t reserved; - uint32_t exchange_addr; - union { - struct { - uint16_t reserved1; - uint16_t flags; - uint32_t residual; - uint16_t ox_id; - uint16_t scsi_status; - uint32_t relative_offset; - uint32_t reserved2; - uint32_t transfer_length; - uint32_t reserved3; - /* Data segment 0 address. */ - uint32_t dseg_0_address[2]; - /* Data segment 0 length. */ - uint32_t dseg_0_length; - } status0; - struct { - uint16_t sense_length; - uint16_t flags; - uint32_t residual; - uint16_t ox_id; - uint16_t scsi_status; - uint16_t response_len; - uint16_t reserved; - uint8_t sense_data[24]; - } status1; - } u; -} __packed; - -/* - * ISP queue - CTIO type 7 from ISP 24xx to target driver - * returned entry structure. - */ -struct ctio7_from_24xx { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System defined handle */ - uint16_t status; - uint16_t timeout; - uint16_t dseg_count; /* Data segment count. */ - uint8_t vp_index; - uint8_t reserved1[5]; - uint32_t exchange_address; - uint16_t reserved2; - uint16_t flags; - uint32_t residual; - uint16_t ox_id; - uint16_t reserved3; - uint32_t relative_offset; - uint8_t reserved4[24]; -} __packed; - -/* CTIO7 flags values */ -#define CTIO7_FLAGS_SEND_STATUS BIT_15 -#define CTIO7_FLAGS_TERMINATE BIT_14 -#define CTIO7_FLAGS_CONFORM_REQ BIT_13 -#define CTIO7_FLAGS_DONT_RET_CTIO BIT_8 -#define CTIO7_FLAGS_STATUS_MODE_0 0 -#define CTIO7_FLAGS_STATUS_MODE_1 BIT_6 -#define CTIO7_FLAGS_EXPLICIT_CONFORM BIT_5 -#define CTIO7_FLAGS_CONFIRM_SATISF BIT_4 -#define CTIO7_FLAGS_DSD_PTR BIT_2 -#define CTIO7_FLAGS_DATA_IN BIT_1 -#define CTIO7_FLAGS_DATA_OUT BIT_0 - -#define ELS_PLOGI 0x3 -#define ELS_FLOGI 0x4 -#define ELS_LOGO 0x5 -#define ELS_PRLI 0x20 -#define ELS_PRLO 0x21 -#define ELS_TPRLO 0x24 -#define ELS_PDISC 0x50 -#define ELS_ADISC 0x52 - -/* - * ISP queue - ABTS received/response entries structure definition for 24xx. - */ -#define ABTS_RECV_24XX 0x54 /* ABTS received (for 24xx) */ -#define ABTS_RESP_24XX 0x55 /* ABTS responce (for 24xx) */ - -/* - * ISP queue - ABTS received IOCB entry structure definition for 24xx. - * The ABTS BLS received from the wire is sent to the - * target driver by the ISP 24xx. - * The IOCB is placed on the response queue. - */ -struct abts_recv_from_24xx { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint8_t reserved_1[6]; - uint16_t nport_handle; - uint8_t reserved_2[2]; - uint8_t vp_index; - uint8_t reserved_3:4; - uint8_t sof_type:4; - uint32_t exchange_address; - struct fcp_hdr_le fcp_hdr_le; - uint8_t reserved_4[16]; - uint32_t exchange_addr_to_abort; -} __packed; - -#define ABTS_PARAM_ABORT_SEQ BIT_0 - -struct ba_acc_le { - uint16_t reserved; - uint8_t seq_id_last; - uint8_t seq_id_valid; -#define SEQ_ID_VALID 0x80 -#define SEQ_ID_INVALID 0x00 - uint16_t rx_id; - uint16_t ox_id; - uint16_t high_seq_cnt; - uint16_t low_seq_cnt; -} __packed; - -struct ba_rjt_le { - uint8_t vendor_uniq; - uint8_t reason_expl; - uint8_t reason_code; -#define BA_RJT_REASON_CODE_INVALID_COMMAND 0x1 -#define BA_RJT_REASON_CODE_UNABLE_TO_PERFORM 0x9 - uint8_t reserved; -} __packed; - -/* - * ISP queue - ABTS Response IOCB entry structure definition for 24xx. - * The ABTS response to the ABTS received is sent by the - * target driver to the ISP 24xx. - * The IOCB is placed on the request queue. - */ -struct abts_resp_to_24xx { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; - uint16_t reserved_1; - uint16_t nport_handle; - uint16_t control_flags; -#define ABTS_CONTR_FLG_TERM_EXCHG BIT_0 - uint8_t vp_index; - uint8_t reserved_3:4; - uint8_t sof_type:4; - uint32_t exchange_address; - struct fcp_hdr_le fcp_hdr_le; - union { - struct ba_acc_le ba_acct; - struct ba_rjt_le ba_rjt; - } __packed payload; - uint32_t reserved_4; - uint32_t exchange_addr_to_abort; -} __packed; - -/* - * ISP queue - ABTS Response IOCB from ISP24xx Firmware entry structure. - * The ABTS response with completion status to the ABTS response - * (sent by the target driver to the ISP 24xx) is sent by the - * ISP24xx firmware to the target driver. - * The IOCB is placed on the response queue. - */ -struct abts_resp_from_24xx_fw { - uint8_t entry_type; /* Entry type. */ - uint8_t entry_count; /* Entry count. */ - uint8_t sys_define; /* System defined. */ - uint8_t entry_status; /* Entry Status. */ - uint32_t handle; - uint16_t compl_status; -#define ABTS_RESP_COMPL_SUCCESS 0 -#define ABTS_RESP_COMPL_SUBCODE_ERROR 0x31 - uint16_t nport_handle; - uint16_t reserved_1; - uint8_t reserved_2; - uint8_t reserved_3:4; - uint8_t sof_type:4; - uint32_t exchange_address; - struct fcp_hdr_le fcp_hdr_le; - uint8_t reserved_4[8]; - uint32_t error_subcode1; -#define ABTS_RESP_SUBCODE_ERR_ABORTED_EXCH_NOT_TERM 0x1E - uint32_t error_subcode2; - uint32_t exchange_addr_to_abort; -} __packed; - -/********************************************************************\ - * Type Definitions used by initiator & target halves -\********************************************************************/ - -struct qla_tgt_mgmt_cmd; -struct qla_tgt_sess; - -/* - * This structure provides a template of function calls that the - * target driver (from within qla_target.c) can issue to the - * target module (tcm_qla2xxx). - */ -struct qla_tgt_func_tmpl { - - int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *, - unsigned char *, uint32_t, int, int, int); - int (*handle_data)(struct qla_tgt_cmd *); - int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_t, - uint32_t); - void (*free_cmd)(struct qla_tgt_cmd *); - void (*free_mcmd)(struct qla_tgt_mgmt_cmd *); - void (*free_session)(struct qla_tgt_sess *); - - int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *, - void *, uint8_t *, uint16_t); - struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *, - const uint16_t); - struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, - const uint8_t *); - void (*clear_nacl_from_fcport_map)(struct qla_tgt_sess *); - void (*put_sess)(struct qla_tgt_sess *); - void (*shutdown_sess)(struct qla_tgt_sess *); -}; - -int qla2x00_wait_for_hba_online(struct scsi_qla_host *); - -#include - -#define QLA_TGT_TIMEOUT 10 /* in seconds */ - -#define QLA_TGT_MAX_HW_PENDING_TIME 60 /* in seconds */ - -/* Immediate notify status constants */ -#define IMM_NTFY_LIP_RESET 0x000E -#define IMM_NTFY_LIP_LINK_REINIT 0x000F -#define IMM_NTFY_IOCB_OVERFLOW 0x0016 -#define IMM_NTFY_ABORT_TASK 0x0020 -#define IMM_NTFY_PORT_LOGOUT 0x0029 -#define IMM_NTFY_PORT_CONFIG 0x002A -#define IMM_NTFY_GLBL_TPRLO 0x002D -#define IMM_NTFY_GLBL_LOGO 0x002E -#define IMM_NTFY_RESOURCE 0x0034 -#define IMM_NTFY_MSG_RX 0x0036 -#define IMM_NTFY_SRR 0x0045 -#define IMM_NTFY_ELS 0x0046 - -/* Immediate notify task flags */ -#define IMM_NTFY_TASK_MGMT_SHIFT 8 - -#define QLA_TGT_CLEAR_ACA 0x40 -#define QLA_TGT_TARGET_RESET 0x20 -#define QLA_TGT_LUN_RESET 0x10 -#define QLA_TGT_CLEAR_TS 0x04 -#define QLA_TGT_ABORT_TS 0x02 -#define QLA_TGT_ABORT_ALL_SESS 0xFFFF -#define QLA_TGT_ABORT_ALL 0xFFFE -#define QLA_TGT_NEXUS_LOSS_SESS 0xFFFD -#define QLA_TGT_NEXUS_LOSS 0xFFFC - -/* Notify Acknowledge flags */ -#define NOTIFY_ACK_RES_COUNT BIT_8 -#define NOTIFY_ACK_CLEAR_LIP_RESET BIT_5 -#define NOTIFY_ACK_TM_RESP_CODE_VALID BIT_4 - -/* Command's states */ -#define QLA_TGT_STATE_NEW 0 /* New command + target processing */ -#define QLA_TGT_STATE_NEED_DATA 1 /* target needs data to continue */ -#define QLA_TGT_STATE_DATA_IN 2 /* Data arrived + target processing */ -#define QLA_TGT_STATE_PROCESSED 3 /* target done processing */ -#define QLA_TGT_STATE_ABORTED 4 /* Command aborted */ - -/* Special handles */ -#define QLA_TGT_NULL_HANDLE 0 -#define QLA_TGT_SKIP_HANDLE (0xFFFFFFFF & ~CTIO_COMPLETION_HANDLE_MARK) - -/* ATIO task_codes field */ -#define ATIO_SIMPLE_QUEUE 0 -#define ATIO_HEAD_OF_QUEUE 1 -#define ATIO_ORDERED_QUEUE 2 -#define ATIO_ACA_QUEUE 4 -#define ATIO_UNTAGGED 5 - -/* TM failed response codes, see FCP (9.4.11 FCP_RSP_INFO) */ -#define FC_TM_SUCCESS 0 -#define FC_TM_BAD_FCP_DATA 1 -#define FC_TM_BAD_CMD 2 -#define FC_TM_FCP_DATA_MISMATCH 3 -#define FC_TM_REJECT 4 -#define FC_TM_FAILED 5 - -/* - * Error code of qlt_pre_xmit_response() meaning that cmd's exchange was - * terminated, so no more actions is needed and success should be returned - * to target. - */ -#define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717 - -#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G) -#define pci_dma_lo32(a) (a & 0xffffffff) -#define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff) -#else -#define pci_dma_lo32(a) (a & 0xffffffff) -#define pci_dma_hi32(a) 0 -#endif - -#define QLA_TGT_SENSE_VALID(sense) ((sense != NULL) && \ - (((const uint8_t *)(sense))[0] & 0x70) == 0x70) - -struct qla_port_24xx_data { - uint8_t port_name[WWN_SIZE]; - uint16_t loop_id; - uint16_t reserved; -}; - -struct qla_tgt { - struct scsi_qla_host *vha; - struct qla_hw_data *ha; - - /* - * To sync between IRQ handlers and qlt_target_release(). Needed, - * because req_pkt() can drop/reaquire HW lock inside. Protected by - * HW lock. - */ - int irq_cmd_count; - - int datasegs_per_cmd, datasegs_per_cont, sg_tablesize; - - /* Target's flags, serialized by pha->hardware_lock */ - unsigned int tgt_enable_64bit_addr:1; /* 64-bits PCI addr enabled */ - unsigned int link_reinit_iocb_pending:1; - - /* - * Protected by tgt_mutex AND hardware_lock for writing and tgt_mutex - * OR hardware_lock for reading. - */ - int tgt_stop; /* the target mode driver is being stopped */ - int tgt_stopped; /* the target mode driver has been stopped */ - - /* Count of sessions refering qla_tgt. Protected by hardware_lock. */ - int sess_count; - - /* Protected by hardware_lock. Addition also protected by tgt_mutex. */ - struct list_head sess_list; - - /* Protected by hardware_lock */ - struct list_head del_sess_list; - struct delayed_work sess_del_work; - - spinlock_t sess_work_lock; - struct list_head sess_works_list; - struct work_struct sess_work; - - struct imm_ntfy_from_isp link_reinit_iocb; - wait_queue_head_t waitQ; - int notify_ack_expected; - int abts_resp_expected; - int modify_lun_expected; - - int ctio_srr_id; - int imm_srr_id; - spinlock_t srr_lock; - struct list_head srr_ctio_list; - struct list_head srr_imm_list; - struct work_struct srr_work; - - atomic_t tgt_global_resets_count; - - struct list_head tgt_list_entry; -}; - -/* - * Equivilant to IT Nexus (Initiator-Target) - */ -struct qla_tgt_sess { - uint16_t loop_id; - port_id_t s_id; - - unsigned int conf_compl_supported:1; - unsigned int deleted:1; - unsigned int local:1; - unsigned int tearing_down:1; - - struct se_session *se_sess; - struct scsi_qla_host *vha; - struct qla_tgt *tgt; - - struct list_head sess_list_entry; - unsigned long expires; - struct list_head del_list_entry; - - uint8_t port_name[WWN_SIZE]; - struct work_struct free_work; -}; - -struct qla_tgt_cmd { - struct qla_tgt_sess *sess; - int state; - struct se_cmd se_cmd; - struct work_struct free_work; - struct work_struct work; - /* Sense buffer that will be mapped into outgoing status */ - unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER]; - - /* to save extra sess dereferences */ - unsigned int conf_compl_supported:1; - unsigned int sg_mapped:1; - unsigned int free_sg:1; - unsigned int aborted:1; /* Needed in case of SRR */ - unsigned int write_data_transferred:1; - - struct scatterlist *sg; /* cmd data buffer SG vector */ - int sg_cnt; /* SG segments count */ - int bufflen; /* cmd buffer length */ - int offset; - uint32_t tag; - uint32_t unpacked_lun; - enum dma_data_direction dma_data_direction; - - uint16_t loop_id; /* to save extra sess dereferences */ - struct qla_tgt *tgt; /* to save extra sess dereferences */ - struct scsi_qla_host *vha; - struct list_head cmd_list; - - struct atio_from_isp atio; -}; - -struct qla_tgt_sess_work_param { - struct list_head sess_works_list_entry; - -#define QLA_TGT_SESS_WORK_ABORT 1 -#define QLA_TGT_SESS_WORK_TM 2 - int type; - - union { - struct abts_recv_from_24xx abts; - struct imm_ntfy_from_isp tm_iocb; - struct atio_from_isp tm_iocb2; - }; -}; - -struct qla_tgt_mgmt_cmd { - uint8_t tmr_func; - uint8_t fc_tm_rsp; - struct qla_tgt_sess *sess; - struct se_cmd se_cmd; - struct work_struct free_work; - unsigned int flags; -#define QLA24XX_MGMT_SEND_NACK 1 - union { - struct atio_from_isp atio; - struct imm_ntfy_from_isp imm_ntfy; - struct abts_recv_from_24xx abts; - } __packed orig_iocb; -}; - -struct qla_tgt_prm { - struct qla_tgt_cmd *cmd; - struct qla_tgt *tgt; - void *pkt; - struct scatterlist *sg; /* cmd data buffer SG vector */ - int seg_cnt; - int req_cnt; - uint16_t rq_result; - uint16_t scsi_status; - unsigned char *sense_buffer; - int sense_buffer_len; - int residual; - int add_status_pkt; -}; - -struct qla_tgt_srr_imm { - struct list_head srr_list_entry; - int srr_id; - struct imm_ntfy_from_isp imm_ntfy; -}; - -struct qla_tgt_srr_ctio { - struct list_head srr_list_entry; - int srr_id; - struct qla_tgt_cmd *cmd; -}; - -#define QLA_TGT_XMIT_DATA 1 -#define QLA_TGT_XMIT_STATUS 2 -#define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA) - - -extern struct qla_tgt_data qla_target; -/* - * Internal function prototypes - */ -void qlt_disable_vha(struct scsi_qla_host *); - -/* - * Function prototypes for qla_target.c logic used by qla2xxx LLD code. - */ -extern int qlt_add_target(struct qla_hw_data *, struct scsi_qla_host *); -extern int qlt_remove_target(struct qla_hw_data *, struct scsi_qla_host *); -extern int qlt_lport_register(struct qla_tgt_func_tmpl *, u64, - int (*callback)(struct scsi_qla_host *), void *); -extern void qlt_lport_deregister(struct scsi_qla_host *); -extern void qlt_unreg_sess(struct qla_tgt_sess *); -extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); -extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *); -extern void qlt_set_mode(struct scsi_qla_host *ha); -extern void qlt_clear_mode(struct scsi_qla_host *ha); -extern int __init qlt_init(void); -extern void qlt_exit(void); -extern void qlt_update_vp_map(struct scsi_qla_host *, int); - -/* - * This macro is used during early initializations when host->active_mode - * is not set. Right now, ha value is ignored. - */ -#define QLA_TGT_MODE_ENABLED() (ql2x_ini_mode != QLA2XXX_INI_MODE_ENABLED) - -static inline bool qla_tgt_mode_enabled(struct scsi_qla_host *ha) -{ - return ha->host->active_mode & MODE_TARGET; -} - -static inline bool qla_ini_mode_enabled(struct scsi_qla_host *ha) -{ - return ha->host->active_mode & MODE_INITIATOR; -} - -static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha) -{ - if (ha->host->active_mode & MODE_INITIATOR) - ha->host->active_mode &= ~MODE_INITIATOR; - else - ha->host->active_mode |= MODE_INITIATOR; -} - -/* - * Exported symbols from qla_target.c LLD logic used by qla2xxx code.. - */ -extern void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *, - struct atio_from_isp *); -extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); -extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); -extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); -extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); -extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); -extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); -extern void qlt_ctio_completion(struct scsi_qla_host *, uint32_t); -extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *); -extern void qlt_enable_vha(struct scsi_qla_host *); -extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *); -extern void qlt_rff_id(struct scsi_qla_host *, struct ct_sns_req *); -extern void qlt_init_atio_q_entries(struct scsi_qla_host *); -extern void qlt_24xx_process_atio_queue(struct scsi_qla_host *); -extern void qlt_24xx_config_rings(struct scsi_qla_host *, - device_reg_t __iomem *); -extern void qlt_24xx_config_nvram_stage1(struct scsi_qla_host *, - struct nvram_24xx *); -extern void qlt_24xx_config_nvram_stage2(struct scsi_qla_host *, - struct init_cb_24xx *); -extern int qlt_24xx_process_response_error(struct scsi_qla_host *, - struct sts_entry_24xx *); -extern void qlt_modify_vp_config(struct scsi_qla_host *, - struct vp_config_entry_24xx *); -extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *); -extern int qlt_mem_alloc(struct qla_hw_data *); -extern void qlt_mem_free(struct qla_hw_data *); -extern void qlt_stop_phase1(struct qla_tgt *); -extern void qlt_stop_phase2(struct qla_tgt *); - -#endif /* __QLA_TARGET_H */ diff --git a/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.c deleted file mode 100644 index 6e64314dbbb3..000000000000 --- a/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ /dev/null @@ -1,1919 +0,0 @@ -/******************************************************************************* - * This file contains tcm implementation using v4 configfs fabric infrastructure - * for QLogic target mode HBAs - * - * ?? Copyright 2010-2011 RisingTide Systems LLC. - * - * Licensed to the Linux Foundation under the General Public License (GPL) - * version 2. - * - * Author: Nicholas A. Bellinger - * - * tcm_qla2xxx_parse_wwn() and tcm_qla2xxx_format_wwn() contains code from - * the TCM_FC / Open-FCoE.org fabric module. - * - * Copyright (c) 2010 Cisco Systems, Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - ****************************************************************************/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qla_def.h" -#include "qla_target.h" -#include "tcm_qla2xxx.h" - -struct workqueue_struct *tcm_qla2xxx_free_wq; -struct workqueue_struct *tcm_qla2xxx_cmd_wq; - -static int tcm_qla2xxx_check_true(struct se_portal_group *se_tpg) -{ - return 1; -} - -static int tcm_qla2xxx_check_false(struct se_portal_group *se_tpg) -{ - return 0; -} - -/* - * Parse WWN. - * If strict, we require lower-case hex and colon separators to be sure - * the name is the same as what would be generated by ft_format_wwn() - * so the name and wwn are mapped one-to-one. - */ -static ssize_t tcm_qla2xxx_parse_wwn(const char *name, u64 *wwn, int strict) -{ - const char *cp; - char c; - u32 nibble; - u32 byte = 0; - u32 pos = 0; - u32 err; - - *wwn = 0; - for (cp = name; cp < &name[TCM_QLA2XXX_NAMELEN - 1]; cp++) { - c = *cp; - if (c == '\n' && cp[1] == '\0') - continue; - if (strict && pos++ == 2 && byte++ < 7) { - pos = 0; - if (c == ':') - continue; - err = 1; - goto fail; - } - if (c == '\0') { - err = 2; - if (strict && byte != 8) - goto fail; - return cp - name; - } - err = 3; - if (isdigit(c)) - nibble = c - '0'; - else if (isxdigit(c) && (islower(c) || !strict)) - nibble = tolower(c) - 'a' + 10; - else - goto fail; - *wwn = (*wwn << 4) | nibble; - } - err = 4; -fail: - pr_debug("err %u len %zu pos %u byte %u\n", - err, cp - name, pos, byte); - return -1; -} - -static ssize_t tcm_qla2xxx_format_wwn(char *buf, size_t len, u64 wwn) -{ - u8 b[8]; - - put_unaligned_be64(wwn, b); - return snprintf(buf, len, - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", - b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); -} - -static char *tcm_qla2xxx_get_fabric_name(void) -{ - return "qla2xxx"; -} - -/* - * From drivers/scsi/scsi_transport_fc.c:fc_parse_wwn - */ -static int tcm_qla2xxx_npiv_extract_wwn(const char *ns, u64 *nm) -{ - unsigned int i, j; - u8 wwn[8]; - - memset(wwn, 0, sizeof(wwn)); - - /* Validate and store the new name */ - for (i = 0, j = 0; i < 16; i++) { - int value; - - value = hex_to_bin(*ns++); - if (value >= 0) - j = (j << 4) | value; - else - return -EINVAL; - - if (i % 2) { - wwn[i/2] = j & 0xff; - j = 0; - } - } - - *nm = wwn_to_u64(wwn); - return 0; -} - -/* - * This parsing logic follows drivers/scsi/scsi_transport_fc.c: - * store_fc_host_vport_create() - */ -static int tcm_qla2xxx_npiv_parse_wwn( - const char *name, - size_t count, - u64 *wwpn, - u64 *wwnn) -{ - unsigned int cnt = count; - int rc; - - *wwpn = 0; - *wwnn = 0; - - /* count may include a LF at end of string */ - if (name[cnt-1] == '\n') - cnt--; - - /* validate we have enough characters for WWPN */ - if ((cnt != (16+1+16)) || (name[16] != ':')) - return -EINVAL; - - rc = tcm_qla2xxx_npiv_extract_wwn(&name[0], wwpn); - if (rc != 0) - return rc; - - rc = tcm_qla2xxx_npiv_extract_wwn(&name[17], wwnn); - if (rc != 0) - return rc; - - return 0; -} - -static ssize_t tcm_qla2xxx_npiv_format_wwn(char *buf, size_t len, - u64 wwpn, u64 wwnn) -{ - u8 b[8], b2[8]; - - put_unaligned_be64(wwpn, b); - put_unaligned_be64(wwnn, b2); - return snprintf(buf, len, - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x," - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", - b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], - b2[0], b2[1], b2[2], b2[3], b2[4], b2[5], b2[6], b2[7]); -} - -static char *tcm_qla2xxx_npiv_get_fabric_name(void) -{ - return "qla2xxx_npiv"; -} - -static u8 tcm_qla2xxx_get_fabric_proto_ident(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - struct tcm_qla2xxx_lport *lport = tpg->lport; - u8 proto_id; - - switch (lport->lport_proto_id) { - case SCSI_PROTOCOL_FCP: - default: - proto_id = fc_get_fabric_proto_ident(se_tpg); - break; - } - - return proto_id; -} - -static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - struct tcm_qla2xxx_lport *lport = tpg->lport; - - return &lport->lport_name[0]; -} - -static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - struct tcm_qla2xxx_lport *lport = tpg->lport; - - return &lport->lport_npiv_name[0]; -} - -static u16 tcm_qla2xxx_get_tag(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - return tpg->lport_tpgt; -} - -static u32 tcm_qla2xxx_get_default_depth(struct se_portal_group *se_tpg) -{ - return 1; -} - -static u32 tcm_qla2xxx_get_pr_transport_id( - struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl, - struct t10_pr_registration *pr_reg, - int *format_code, - unsigned char *buf) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - struct tcm_qla2xxx_lport *lport = tpg->lport; - int ret = 0; - - switch (lport->lport_proto_id) { - case SCSI_PROTOCOL_FCP: - default: - ret = fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg, - format_code, buf); - break; - } - - return ret; -} - -static u32 tcm_qla2xxx_get_pr_transport_id_len( - struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl, - struct t10_pr_registration *pr_reg, - int *format_code) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - struct tcm_qla2xxx_lport *lport = tpg->lport; - int ret = 0; - - switch (lport->lport_proto_id) { - case SCSI_PROTOCOL_FCP: - default: - ret = fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, - format_code); - break; - } - - return ret; -} - -static char *tcm_qla2xxx_parse_pr_out_transport_id( - struct se_portal_group *se_tpg, - const char *buf, - u32 *out_tid_len, - char **port_nexus_ptr) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - struct tcm_qla2xxx_lport *lport = tpg->lport; - char *tid = NULL; - - switch (lport->lport_proto_id) { - case SCSI_PROTOCOL_FCP: - default: - tid = fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, - port_nexus_ptr); - break; - } - - return tid; -} - -static int tcm_qla2xxx_check_demo_mode(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - - return QLA_TPG_ATTRIB(tpg)->generate_node_acls; -} - -static int tcm_qla2xxx_check_demo_mode_cache(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - - return QLA_TPG_ATTRIB(tpg)->cache_dynamic_acls; -} - -static int tcm_qla2xxx_check_demo_write_protect(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - - return QLA_TPG_ATTRIB(tpg)->demo_mode_write_protect; -} - -static int tcm_qla2xxx_check_prod_write_protect(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - - return QLA_TPG_ATTRIB(tpg)->prod_mode_write_protect; -} - -static struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl( - struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_nacl *nacl; - - nacl = kzalloc(sizeof(struct tcm_qla2xxx_nacl), GFP_KERNEL); - if (!nacl) { - pr_err("Unable to alocate struct tcm_qla2xxx_nacl\n"); - return NULL; - } - - return &nacl->se_node_acl; -} - -static void tcm_qla2xxx_release_fabric_acl( - struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl) -{ - struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, - struct tcm_qla2xxx_nacl, se_node_acl); - kfree(nacl); -} - -static u32 tcm_qla2xxx_tpg_get_inst_index(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - - return tpg->lport_tpgt; -} - -static void tcm_qla2xxx_complete_mcmd(struct work_struct *work) -{ - struct qla_tgt_mgmt_cmd *mcmd = container_of(work, - struct qla_tgt_mgmt_cmd, free_work); - - transport_generic_free_cmd(&mcmd->se_cmd, 0); -} - -/* - * Called from qla_target_template->free_mcmd(), and will call - * tcm_qla2xxx_release_cmd() via normal struct target_core_fabric_ops - * release callback. qla_hw_data->hardware_lock is expected to be held - */ -static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) -{ - INIT_WORK(&mcmd->free_work, tcm_qla2xxx_complete_mcmd); - queue_work(tcm_qla2xxx_free_wq, &mcmd->free_work); -} - -static void tcm_qla2xxx_complete_free(struct work_struct *work) -{ - struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); - - transport_generic_free_cmd(&cmd->se_cmd, 0); -} - -/* - * Called from qla_target_template->free_cmd(), and will call - * tcm_qla2xxx_release_cmd via normal struct target_core_fabric_ops - * release callback. qla_hw_data->hardware_lock is expected to be held - */ -static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd) -{ - INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free); - queue_work(tcm_qla2xxx_free_wq, &cmd->work); -} - -/* - * Called from struct target_core_fabric_ops->check_stop_free() context - */ -static int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) -{ - return target_put_sess_cmd(se_cmd->se_sess, se_cmd); -} - -/* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying - * fabric descriptor @se_cmd command to release - */ -static void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd) -{ - struct qla_tgt_cmd *cmd; - - if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) { - struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd, - struct qla_tgt_mgmt_cmd, se_cmd); - qlt_free_mcmd(mcmd); - return; - } - - cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); - qlt_free_cmd(cmd); -} - -static int tcm_qla2xxx_shutdown_session(struct se_session *se_sess) -{ - struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr; - struct scsi_qla_host *vha; - unsigned long flags; - - BUG_ON(!sess); - vha = sess->vha; - - spin_lock_irqsave(&vha->hw->hardware_lock, flags); - sess->tearing_down = 1; - target_splice_sess_cmd_list(se_sess); - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); - - return 1; -} - -static void tcm_qla2xxx_close_session(struct se_session *se_sess) -{ - struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr; - struct scsi_qla_host *vha; - unsigned long flags; - - BUG_ON(!sess); - vha = sess->vha; - - spin_lock_irqsave(&vha->hw->hardware_lock, flags); - qlt_unreg_sess(sess); - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); -} - -static u32 tcm_qla2xxx_sess_get_index(struct se_session *se_sess) -{ - return 0; -} - -/* - * The LIO target core uses DMA_TO_DEVICE to mean that data is going - * to the target (eg handling a WRITE) and DMA_FROM_DEVICE to mean - * that data is coming from the target (eg handling a READ). However, - * this is just the opposite of what we have to tell the DMA mapping - * layer -- eg when handling a READ, the HBA will have to DMA the data - * out of memory so it can send it to the initiator, which means we - * need to use DMA_TO_DEVICE when we map the data. - */ -static enum dma_data_direction tcm_qla2xxx_mapping_dir(struct se_cmd *se_cmd) -{ - if (se_cmd->se_cmd_flags & SCF_BIDI) - return DMA_BIDIRECTIONAL; - - switch (se_cmd->data_direction) { - case DMA_TO_DEVICE: - return DMA_FROM_DEVICE; - case DMA_FROM_DEVICE: - return DMA_TO_DEVICE; - case DMA_NONE: - default: - return DMA_NONE; - } -} - -static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) -{ - struct qla_tgt_cmd *cmd = container_of(se_cmd, - struct qla_tgt_cmd, se_cmd); - - cmd->bufflen = se_cmd->data_length; - cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd); - - cmd->sg_cnt = se_cmd->t_data_nents; - cmd->sg = se_cmd->t_data_sg; - - /* - * qla_target.c:qlt_rdy_to_xfer() will call pci_map_sg() to setup - * the SGL mappings into PCIe memory for incoming FCP WRITE data. - */ - return qlt_rdy_to_xfer(cmd); -} - -static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd) -{ - unsigned long flags; - /* - * Check for WRITE_PENDING status to determine if we need to wait for - * CTIO aborts to be posted via hardware in tcm_qla2xxx_handle_data(). - */ - spin_lock_irqsave(&se_cmd->t_state_lock, flags); - if (se_cmd->t_state == TRANSPORT_WRITE_PENDING || - se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); - wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, - 3000); - return 0; - } - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); - - return 0; -} - -static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl) -{ - return; -} - -static u32 tcm_qla2xxx_get_task_tag(struct se_cmd *se_cmd) -{ - struct qla_tgt_cmd *cmd = container_of(se_cmd, - struct qla_tgt_cmd, se_cmd); - - return cmd->tag; -} - -static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd) -{ - return 0; -} - -/* - * Called from process context in qla_target.c:qlt_do_work() code - */ -static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, - unsigned char *cdb, uint32_t data_length, int fcp_task_attr, - int data_dir, int bidi) -{ - struct se_cmd *se_cmd = &cmd->se_cmd; - struct se_session *se_sess; - struct qla_tgt_sess *sess; - int flags = TARGET_SCF_ACK_KREF; - - if (bidi) - flags |= TARGET_SCF_BIDI_OP; - - sess = cmd->sess; - if (!sess) { - pr_err("Unable to locate struct qla_tgt_sess from qla_tgt_cmd\n"); - return -EINVAL; - } - - se_sess = sess->se_sess; - if (!se_sess) { - pr_err("Unable to locate active struct se_session\n"); - return -EINVAL; - } - - target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0], - cmd->unpacked_lun, data_length, fcp_task_attr, - data_dir, flags); - return 0; -} - -static void tcm_qla2xxx_do_rsp(struct work_struct *work) -{ - struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); - /* - * Dispatch ->queue_status from workqueue process context - */ - transport_generic_request_failure(&cmd->se_cmd); -} - -/* - * Called from qla_target.c:qlt_do_ctio_completion() - */ -static int tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd) -{ - struct se_cmd *se_cmd = &cmd->se_cmd; - unsigned long flags; - /* - * Ensure that the complete FCP WRITE payload has been received. - * Otherwise return an exception via CHECK_CONDITION status. - */ - if (!cmd->write_data_transferred) { - /* - * Check if se_cmd has already been aborted via LUN_RESET, and - * waiting upon completion in tcm_qla2xxx_write_pending_status() - */ - spin_lock_irqsave(&se_cmd->t_state_lock, flags); - if (se_cmd->transport_state & CMD_T_ABORTED) { - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); - complete(&se_cmd->t_transport_stop_comp); - return 0; - } - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); - - se_cmd->scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD; - INIT_WORK(&cmd->work, tcm_qla2xxx_do_rsp); - queue_work(tcm_qla2xxx_free_wq, &cmd->work); - return 0; - } - /* - * We now tell TCM to queue this WRITE CDB with TRANSPORT_PROCESS_WRITE - * status to the backstore processing thread. - */ - return transport_generic_handle_data(&cmd->se_cmd); -} - -/* - * Called from qla_target.c:qlt_issue_task_mgmt() - */ -static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, uint32_t lun, - uint8_t tmr_func, uint32_t tag) -{ - struct qla_tgt_sess *sess = mcmd->sess; - struct se_cmd *se_cmd = &mcmd->se_cmd; - - return target_submit_tmr(se_cmd, sess->se_sess, NULL, lun, mcmd, - tmr_func, GFP_ATOMIC, tag, TARGET_SCF_ACK_KREF); -} - -static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) -{ - struct qla_tgt_cmd *cmd = container_of(se_cmd, - struct qla_tgt_cmd, se_cmd); - - cmd->bufflen = se_cmd->data_length; - cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd); - cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); - - cmd->sg_cnt = se_cmd->t_data_nents; - cmd->sg = se_cmd->t_data_sg; - cmd->offset = 0; - - /* - * Now queue completed DATA_IN the qla2xxx LLD and response ring - */ - return qlt_xmit_response(cmd, QLA_TGT_XMIT_DATA|QLA_TGT_XMIT_STATUS, - se_cmd->scsi_status); -} - -static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd) -{ - struct qla_tgt_cmd *cmd = container_of(se_cmd, - struct qla_tgt_cmd, se_cmd); - int xmit_type = QLA_TGT_XMIT_STATUS; - - cmd->bufflen = se_cmd->data_length; - cmd->sg = NULL; - cmd->sg_cnt = 0; - cmd->offset = 0; - cmd->dma_data_direction = tcm_qla2xxx_mapping_dir(se_cmd); - cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); - - if (se_cmd->data_direction == DMA_FROM_DEVICE) { - /* - * For FCP_READ with CHECK_CONDITION status, clear cmd->bufflen - * for qla_tgt_xmit_response LLD code - */ - se_cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; - se_cmd->residual_count = se_cmd->data_length; - - cmd->bufflen = 0; - } - /* - * Now queue status response to qla2xxx LLD code and response ring - */ - return qlt_xmit_response(cmd, xmit_type, se_cmd->scsi_status); -} - -static int tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) -{ - struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; - struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd, - struct qla_tgt_mgmt_cmd, se_cmd); - - pr_debug("queue_tm_rsp: mcmd: %p func: 0x%02x response: 0x%02x\n", - mcmd, se_tmr->function, se_tmr->response); - /* - * Do translation between TCM TM response codes and - * QLA2xxx FC TM response codes. - */ - switch (se_tmr->response) { - case TMR_FUNCTION_COMPLETE: - mcmd->fc_tm_rsp = FC_TM_SUCCESS; - break; - case TMR_TASK_DOES_NOT_EXIST: - mcmd->fc_tm_rsp = FC_TM_BAD_CMD; - break; - case TMR_FUNCTION_REJECTED: - mcmd->fc_tm_rsp = FC_TM_REJECT; - break; - case TMR_LUN_DOES_NOT_EXIST: - default: - mcmd->fc_tm_rsp = FC_TM_FAILED; - break; - } - /* - * Queue the TM response to QLA2xxx LLD to build a - * CTIO response packet. - */ - qlt_xmit_tm_rsp(mcmd); - - return 0; -} - -static u16 tcm_qla2xxx_get_fabric_sense_len(void) -{ - return 0; -} - -static u16 tcm_qla2xxx_set_fabric_sense_len(struct se_cmd *se_cmd, - u32 sense_length) -{ - return 0; -} - -/* Local pointer to allocated TCM configfs fabric module */ -struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs; -struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs; - -static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, - struct tcm_qla2xxx_nacl *, struct qla_tgt_sess *); -/* - * Expected to be called with struct qla_hw_data->hardware_lock held - */ -static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess) -{ - struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; - struct se_portal_group *se_tpg = se_nacl->se_tpg; - struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; - struct tcm_qla2xxx_lport *lport = container_of(se_wwn, - struct tcm_qla2xxx_lport, lport_wwn); - struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, - struct tcm_qla2xxx_nacl, se_node_acl); - void *node; - - pr_debug("fc_rport domain: port_id 0x%06x\n", nacl->nport_id); - - node = btree_remove32(&lport->lport_fcport_map, nacl->nport_id); - WARN_ON(node && (node != se_nacl)); - - pr_debug("Removed from fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%06x\n", - se_nacl, nacl->nport_wwnn, nacl->nport_id); - /* - * Now clear the se_nacl and session pointers from our HW lport lookup - * table mapping for this initiator's fabric S_ID and LOOP_ID entries. - * - * This is done ahead of callbacks into tcm_qla2xxx_free_session() -> - * target_wait_for_sess_cmds() before the session waits for outstanding - * I/O to complete, to avoid a race between session shutdown execution - * and incoming ATIOs or TMRs picking up a stale se_node_act reference. - */ - tcm_qla2xxx_clear_sess_lookup(lport, nacl, sess); -} - -static void tcm_qla2xxx_release_session(struct kref *kref) -{ - struct se_session *se_sess = container_of(kref, - struct se_session, sess_kref); - - qlt_unreg_sess(se_sess->fabric_sess_ptr); -} - -static void tcm_qla2xxx_put_session(struct se_session *se_sess) -{ - struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr; - struct qla_hw_data *ha = sess->vha->hw; - unsigned long flags; - - spin_lock_irqsave(&ha->hardware_lock, flags); - kref_put(&se_sess->sess_kref, tcm_qla2xxx_release_session); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - -static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) -{ - tcm_qla2xxx_put_session(sess->se_sess); -} - -static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess) -{ - tcm_qla2xxx_shutdown_session(sess->se_sess); -} - -static struct se_node_acl *tcm_qla2xxx_make_nodeacl( - struct se_portal_group *se_tpg, - struct config_group *group, - const char *name) -{ - struct se_node_acl *se_nacl, *se_nacl_new; - struct tcm_qla2xxx_nacl *nacl; - u64 wwnn; - u32 qla2xxx_nexus_depth; - - if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0) - return ERR_PTR(-EINVAL); - - se_nacl_new = tcm_qla2xxx_alloc_fabric_acl(se_tpg); - if (!se_nacl_new) - return ERR_PTR(-ENOMEM); -/* #warning FIXME: Hardcoded qla2xxx_nexus depth in tcm_qla2xxx_make_nodeacl */ - qla2xxx_nexus_depth = 1; - - /* - * se_nacl_new may be released by core_tpg_add_initiator_node_acl() - * when converting a NodeACL from demo mode -> explict - */ - se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new, - name, qla2xxx_nexus_depth); - if (IS_ERR(se_nacl)) { - tcm_qla2xxx_release_fabric_acl(se_tpg, se_nacl_new); - return se_nacl; - } - /* - * Locate our struct tcm_qla2xxx_nacl and set the FC Nport WWPN - */ - nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); - nacl->nport_wwnn = wwnn; - tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn); - - return se_nacl; -} - -static void tcm_qla2xxx_drop_nodeacl(struct se_node_acl *se_acl) -{ - struct se_portal_group *se_tpg = se_acl->se_tpg; - struct tcm_qla2xxx_nacl *nacl = container_of(se_acl, - struct tcm_qla2xxx_nacl, se_node_acl); - - core_tpg_del_initiator_node_acl(se_tpg, se_acl, 1); - kfree(nacl); -} - -/* Start items for tcm_qla2xxx_tpg_attrib_cit */ - -#define DEF_QLA_TPG_ATTRIB(name) \ - \ -static ssize_t tcm_qla2xxx_tpg_attrib_show_##name( \ - struct se_portal_group *se_tpg, \ - char *page) \ -{ \ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \ - struct tcm_qla2xxx_tpg, se_tpg); \ - \ - return sprintf(page, "%u\n", QLA_TPG_ATTRIB(tpg)->name); \ -} \ - \ -static ssize_t tcm_qla2xxx_tpg_attrib_store_##name( \ - struct se_portal_group *se_tpg, \ - const char *page, \ - size_t count) \ -{ \ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \ - struct tcm_qla2xxx_tpg, se_tpg); \ - unsigned long val; \ - int ret; \ - \ - ret = kstrtoul(page, 0, &val); \ - if (ret < 0) { \ - pr_err("kstrtoul() failed with" \ - " ret: %d\n", ret); \ - return -EINVAL; \ - } \ - ret = tcm_qla2xxx_set_attrib_##name(tpg, val); \ - \ - return (!ret) ? count : -EINVAL; \ -} - -#define DEF_QLA_TPG_ATTR_BOOL(_name) \ - \ -static int tcm_qla2xxx_set_attrib_##_name( \ - struct tcm_qla2xxx_tpg *tpg, \ - unsigned long val) \ -{ \ - struct tcm_qla2xxx_tpg_attrib *a = &tpg->tpg_attrib; \ - \ - if ((val != 0) && (val != 1)) { \ - pr_err("Illegal boolean value %lu\n", val); \ - return -EINVAL; \ - } \ - \ - a->_name = val; \ - return 0; \ -} - -#define QLA_TPG_ATTR(_name, _mode) \ - TF_TPG_ATTRIB_ATTR(tcm_qla2xxx, _name, _mode); - -/* - * Define tcm_qla2xxx_tpg_attrib_s_generate_node_acls - */ -DEF_QLA_TPG_ATTR_BOOL(generate_node_acls); -DEF_QLA_TPG_ATTRIB(generate_node_acls); -QLA_TPG_ATTR(generate_node_acls, S_IRUGO | S_IWUSR); - -/* - Define tcm_qla2xxx_attrib_s_cache_dynamic_acls - */ -DEF_QLA_TPG_ATTR_BOOL(cache_dynamic_acls); -DEF_QLA_TPG_ATTRIB(cache_dynamic_acls); -QLA_TPG_ATTR(cache_dynamic_acls, S_IRUGO | S_IWUSR); - -/* - * Define tcm_qla2xxx_tpg_attrib_s_demo_mode_write_protect - */ -DEF_QLA_TPG_ATTR_BOOL(demo_mode_write_protect); -DEF_QLA_TPG_ATTRIB(demo_mode_write_protect); -QLA_TPG_ATTR(demo_mode_write_protect, S_IRUGO | S_IWUSR); - -/* - * Define tcm_qla2xxx_tpg_attrib_s_prod_mode_write_protect - */ -DEF_QLA_TPG_ATTR_BOOL(prod_mode_write_protect); -DEF_QLA_TPG_ATTRIB(prod_mode_write_protect); -QLA_TPG_ATTR(prod_mode_write_protect, S_IRUGO | S_IWUSR); - -static struct configfs_attribute *tcm_qla2xxx_tpg_attrib_attrs[] = { - &tcm_qla2xxx_tpg_attrib_generate_node_acls.attr, - &tcm_qla2xxx_tpg_attrib_cache_dynamic_acls.attr, - &tcm_qla2xxx_tpg_attrib_demo_mode_write_protect.attr, - &tcm_qla2xxx_tpg_attrib_prod_mode_write_protect.attr, - NULL, -}; - -/* End items for tcm_qla2xxx_tpg_attrib_cit */ - -static ssize_t tcm_qla2xxx_tpg_show_enable( - struct se_portal_group *se_tpg, - char *page) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - - return snprintf(page, PAGE_SIZE, "%d\n", - atomic_read(&tpg->lport_tpg_enabled)); -} - -static ssize_t tcm_qla2xxx_tpg_store_enable( - struct se_portal_group *se_tpg, - const char *page, - size_t count) -{ - struct se_wwn *se_wwn = se_tpg->se_tpg_wwn; - struct tcm_qla2xxx_lport *lport = container_of(se_wwn, - struct tcm_qla2xxx_lport, lport_wwn); - struct scsi_qla_host *vha = lport->qla_vha; - struct qla_hw_data *ha = vha->hw; - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - unsigned long op; - int rc; - - rc = kstrtoul(page, 0, &op); - if (rc < 0) { - pr_err("kstrtoul() returned %d\n", rc); - return -EINVAL; - } - if ((op != 1) && (op != 0)) { - pr_err("Illegal value for tpg_enable: %lu\n", op); - return -EINVAL; - } - - if (op) { - atomic_set(&tpg->lport_tpg_enabled, 1); - qlt_enable_vha(vha); - } else { - if (!ha->tgt.qla_tgt) { - pr_err("truct qla_hw_data *ha->tgt.qla_tgt is NULL\n"); - return -ENODEV; - } - atomic_set(&tpg->lport_tpg_enabled, 0); - qlt_stop_phase1(ha->tgt.qla_tgt); - } - - return count; -} - -TF_TPG_BASE_ATTR(tcm_qla2xxx, enable, S_IRUGO | S_IWUSR); - -static struct configfs_attribute *tcm_qla2xxx_tpg_attrs[] = { - &tcm_qla2xxx_tpg_enable.attr, - NULL, -}; - -static struct se_portal_group *tcm_qla2xxx_make_tpg( - struct se_wwn *wwn, - struct config_group *group, - const char *name) -{ - struct tcm_qla2xxx_lport *lport = container_of(wwn, - struct tcm_qla2xxx_lport, lport_wwn); - struct tcm_qla2xxx_tpg *tpg; - unsigned long tpgt; - int ret; - - if (strstr(name, "tpgt_") != name) - return ERR_PTR(-EINVAL); - if (kstrtoul(name + 5, 10, &tpgt) || tpgt > USHRT_MAX) - return ERR_PTR(-EINVAL); - - if (!lport->qla_npiv_vp && (tpgt != 1)) { - pr_err("In non NPIV mode, a single TPG=1 is used for HW port mappings\n"); - return ERR_PTR(-ENOSYS); - } - - tpg = kzalloc(sizeof(struct tcm_qla2xxx_tpg), GFP_KERNEL); - if (!tpg) { - pr_err("Unable to allocate struct tcm_qla2xxx_tpg\n"); - return ERR_PTR(-ENOMEM); - } - tpg->lport = lport; - tpg->lport_tpgt = tpgt; - /* - * By default allow READ-ONLY TPG demo-mode access w/ cached dynamic - * NodeACLs - */ - QLA_TPG_ATTRIB(tpg)->generate_node_acls = 1; - QLA_TPG_ATTRIB(tpg)->demo_mode_write_protect = 1; - QLA_TPG_ATTRIB(tpg)->cache_dynamic_acls = 1; - - ret = core_tpg_register(&tcm_qla2xxx_fabric_configfs->tf_ops, wwn, - &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); - if (ret < 0) { - kfree(tpg); - return NULL; - } - /* - * Setup local TPG=1 pointer for non NPIV mode. - */ - if (lport->qla_npiv_vp == NULL) - lport->tpg_1 = tpg; - - return &tpg->se_tpg; -} - -static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg) -{ - struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, - struct tcm_qla2xxx_tpg, se_tpg); - struct tcm_qla2xxx_lport *lport = tpg->lport; - struct scsi_qla_host *vha = lport->qla_vha; - struct qla_hw_data *ha = vha->hw; - /* - * Call into qla2x_target.c LLD logic to shutdown the active - * FC Nexuses and disable target mode operation for this qla_hw_data - */ - if (ha->tgt.qla_tgt && !ha->tgt.qla_tgt->tgt_stop) - qlt_stop_phase1(ha->tgt.qla_tgt); - - core_tpg_deregister(se_tpg); - /* - * Clear local TPG=1 pointer for non NPIV mode. - */ - if (lport->qla_npiv_vp == NULL) - lport->tpg_1 = NULL; - - kfree(tpg); -} - -static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg( - struct se_wwn *wwn, - struct config_group *group, - const char *name) -{ - struct tcm_qla2xxx_lport *lport = container_of(wwn, - struct tcm_qla2xxx_lport, lport_wwn); - struct tcm_qla2xxx_tpg *tpg; - unsigned long tpgt; - int ret; - - if (strstr(name, "tpgt_") != name) - return ERR_PTR(-EINVAL); - if (kstrtoul(name + 5, 10, &tpgt) || tpgt > USHRT_MAX) - return ERR_PTR(-EINVAL); - - tpg = kzalloc(sizeof(struct tcm_qla2xxx_tpg), GFP_KERNEL); - if (!tpg) { - pr_err("Unable to allocate struct tcm_qla2xxx_tpg\n"); - return ERR_PTR(-ENOMEM); - } - tpg->lport = lport; - tpg->lport_tpgt = tpgt; - - ret = core_tpg_register(&tcm_qla2xxx_npiv_fabric_configfs->tf_ops, wwn, - &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); - if (ret < 0) { - kfree(tpg); - return NULL; - } - return &tpg->se_tpg; -} - -/* - * Expected to be called with struct qla_hw_data->hardware_lock held - */ -static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( - scsi_qla_host_t *vha, - const uint8_t *s_id) -{ - struct qla_hw_data *ha = vha->hw; - struct tcm_qla2xxx_lport *lport; - struct se_node_acl *se_nacl; - struct tcm_qla2xxx_nacl *nacl; - u32 key; - - lport = ha->tgt.target_lport_ptr; - if (!lport) { - pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); - dump_stack(); - return NULL; - } - - key = (((unsigned long)s_id[0] << 16) | - ((unsigned long)s_id[1] << 8) | - (unsigned long)s_id[2]); - pr_debug("find_sess_by_s_id: 0x%06x\n", key); - - se_nacl = btree_lookup32(&lport->lport_fcport_map, key); - if (!se_nacl) { - pr_debug("Unable to locate s_id: 0x%06x\n", key); - return NULL; - } - pr_debug("find_sess_by_s_id: located se_nacl: %p, initiatorname: %s\n", - se_nacl, se_nacl->initiatorname); - - nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); - if (!nacl->qla_tgt_sess) { - pr_err("Unable to locate struct qla_tgt_sess\n"); - return NULL; - } - - return nacl->qla_tgt_sess; -} - -/* - * Expected to be called with struct qla_hw_data->hardware_lock held - */ -static void tcm_qla2xxx_set_sess_by_s_id( - struct tcm_qla2xxx_lport *lport, - struct se_node_acl *new_se_nacl, - struct tcm_qla2xxx_nacl *nacl, - struct se_session *se_sess, - struct qla_tgt_sess *qla_tgt_sess, - uint8_t *s_id) -{ - u32 key; - void *slot; - int rc; - - key = (((unsigned long)s_id[0] << 16) | - ((unsigned long)s_id[1] << 8) | - (unsigned long)s_id[2]); - pr_debug("set_sess_by_s_id: %06x\n", key); - - slot = btree_lookup32(&lport->lport_fcport_map, key); - if (!slot) { - if (new_se_nacl) { - pr_debug("Setting up new fc_port entry to new_se_nacl\n"); - nacl->nport_id = key; - rc = btree_insert32(&lport->lport_fcport_map, key, - new_se_nacl, GFP_ATOMIC); - if (rc) - printk(KERN_ERR "Unable to insert s_id into fcport_map: %06x\n", - (int)key); - } else { - pr_debug("Wiping nonexisting fc_port entry\n"); - } - - qla_tgt_sess->se_sess = se_sess; - nacl->qla_tgt_sess = qla_tgt_sess; - return; - } - - if (nacl->qla_tgt_sess) { - if (new_se_nacl == NULL) { - pr_debug("Clearing existing nacl->qla_tgt_sess and fc_port entry\n"); - btree_remove32(&lport->lport_fcport_map, key); - nacl->qla_tgt_sess = NULL; - return; - } - pr_debug("Replacing existing nacl->qla_tgt_sess and fc_port entry\n"); - btree_update32(&lport->lport_fcport_map, key, new_se_nacl); - qla_tgt_sess->se_sess = se_sess; - nacl->qla_tgt_sess = qla_tgt_sess; - return; - } - - if (new_se_nacl == NULL) { - pr_debug("Clearing existing fc_port entry\n"); - btree_remove32(&lport->lport_fcport_map, key); - return; - } - - pr_debug("Replacing existing fc_port entry w/o active nacl->qla_tgt_sess\n"); - btree_update32(&lport->lport_fcport_map, key, new_se_nacl); - qla_tgt_sess->se_sess = se_sess; - nacl->qla_tgt_sess = qla_tgt_sess; - - pr_debug("Setup nacl->qla_tgt_sess %p by s_id for se_nacl: %p, initiatorname: %s\n", - nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname); -} - -/* - * Expected to be called with struct qla_hw_data->hardware_lock held - */ -static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_loop_id( - scsi_qla_host_t *vha, - const uint16_t loop_id) -{ - struct qla_hw_data *ha = vha->hw; - struct tcm_qla2xxx_lport *lport; - struct se_node_acl *se_nacl; - struct tcm_qla2xxx_nacl *nacl; - struct tcm_qla2xxx_fc_loopid *fc_loopid; - - lport = ha->tgt.target_lport_ptr; - if (!lport) { - pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); - dump_stack(); - return NULL; - } - - pr_debug("find_sess_by_loop_id: Using loop_id: 0x%04x\n", loop_id); - - fc_loopid = lport->lport_loopid_map + loop_id; - se_nacl = fc_loopid->se_nacl; - if (!se_nacl) { - pr_debug("Unable to locate se_nacl by loop_id: 0x%04x\n", - loop_id); - return NULL; - } - - nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); - - if (!nacl->qla_tgt_sess) { - pr_err("Unable to locate struct qla_tgt_sess\n"); - return NULL; - } - - return nacl->qla_tgt_sess; -} - -/* - * Expected to be called with struct qla_hw_data->hardware_lock held - */ -static void tcm_qla2xxx_set_sess_by_loop_id( - struct tcm_qla2xxx_lport *lport, - struct se_node_acl *new_se_nacl, - struct tcm_qla2xxx_nacl *nacl, - struct se_session *se_sess, - struct qla_tgt_sess *qla_tgt_sess, - uint16_t loop_id) -{ - struct se_node_acl *saved_nacl; - struct tcm_qla2xxx_fc_loopid *fc_loopid; - - pr_debug("set_sess_by_loop_id: Using loop_id: 0x%04x\n", loop_id); - - fc_loopid = &((struct tcm_qla2xxx_fc_loopid *) - lport->lport_loopid_map)[loop_id]; - - saved_nacl = fc_loopid->se_nacl; - if (!saved_nacl) { - pr_debug("Setting up new fc_loopid->se_nacl to new_se_nacl\n"); - fc_loopid->se_nacl = new_se_nacl; - if (qla_tgt_sess->se_sess != se_sess) - qla_tgt_sess->se_sess = se_sess; - if (nacl->qla_tgt_sess != qla_tgt_sess) - nacl->qla_tgt_sess = qla_tgt_sess; - return; - } - - if (nacl->qla_tgt_sess) { - if (new_se_nacl == NULL) { - pr_debug("Clearing nacl->qla_tgt_sess and fc_loopid->se_nacl\n"); - fc_loopid->se_nacl = NULL; - nacl->qla_tgt_sess = NULL; - return; - } - - pr_debug("Replacing existing nacl->qla_tgt_sess and fc_loopid->se_nacl\n"); - fc_loopid->se_nacl = new_se_nacl; - if (qla_tgt_sess->se_sess != se_sess) - qla_tgt_sess->se_sess = se_sess; - if (nacl->qla_tgt_sess != qla_tgt_sess) - nacl->qla_tgt_sess = qla_tgt_sess; - return; - } - - if (new_se_nacl == NULL) { - pr_debug("Clearing fc_loopid->se_nacl\n"); - fc_loopid->se_nacl = NULL; - return; - } - - pr_debug("Replacing existing fc_loopid->se_nacl w/o active nacl->qla_tgt_sess\n"); - fc_loopid->se_nacl = new_se_nacl; - if (qla_tgt_sess->se_sess != se_sess) - qla_tgt_sess->se_sess = se_sess; - if (nacl->qla_tgt_sess != qla_tgt_sess) - nacl->qla_tgt_sess = qla_tgt_sess; - - pr_debug("Setup nacl->qla_tgt_sess %p by loop_id for se_nacl: %p, initiatorname: %s\n", - nacl->qla_tgt_sess, new_se_nacl, new_se_nacl->initiatorname); -} - -/* - * Should always be called with qla_hw_data->hardware_lock held. - */ -static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *lport, - struct tcm_qla2xxx_nacl *nacl, struct qla_tgt_sess *sess) -{ - struct se_session *se_sess = sess->se_sess; - unsigned char be_sid[3]; - - be_sid[0] = sess->s_id.b.domain; - be_sid[1] = sess->s_id.b.area; - be_sid[2] = sess->s_id.b.al_pa; - - tcm_qla2xxx_set_sess_by_s_id(lport, NULL, nacl, se_sess, - sess, be_sid); - tcm_qla2xxx_set_sess_by_loop_id(lport, NULL, nacl, se_sess, - sess, sess->loop_id); -} - -static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) -{ - struct qla_tgt *tgt = sess->tgt; - struct qla_hw_data *ha = tgt->ha; - struct se_session *se_sess; - struct se_node_acl *se_nacl; - struct tcm_qla2xxx_lport *lport; - struct tcm_qla2xxx_nacl *nacl; - - BUG_ON(in_interrupt()); - - se_sess = sess->se_sess; - if (!se_sess) { - pr_err("struct qla_tgt_sess->se_sess is NULL\n"); - dump_stack(); - return; - } - se_nacl = se_sess->se_node_acl; - nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); - - lport = ha->tgt.target_lport_ptr; - if (!lport) { - pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); - dump_stack(); - return; - } - target_wait_for_sess_cmds(se_sess, 0); - - transport_deregister_session_configfs(sess->se_sess); - transport_deregister_session(sess->se_sess); -} - -/* - * Called via qlt_create_sess():ha->qla2x_tmpl->check_initiator_node_acl() - * to locate struct se_node_acl - */ -static int tcm_qla2xxx_check_initiator_node_acl( - scsi_qla_host_t *vha, - unsigned char *fc_wwpn, - void *qla_tgt_sess, - uint8_t *s_id, - uint16_t loop_id) -{ - struct qla_hw_data *ha = vha->hw; - struct tcm_qla2xxx_lport *lport; - struct tcm_qla2xxx_tpg *tpg; - struct tcm_qla2xxx_nacl *nacl; - struct se_portal_group *se_tpg; - struct se_node_acl *se_nacl; - struct se_session *se_sess; - struct qla_tgt_sess *sess = qla_tgt_sess; - unsigned char port_name[36]; - unsigned long flags; - - lport = ha->tgt.target_lport_ptr; - if (!lport) { - pr_err("Unable to locate struct tcm_qla2xxx_lport\n"); - dump_stack(); - return -EINVAL; - } - /* - * Locate the TPG=1 reference.. - */ - tpg = lport->tpg_1; - if (!tpg) { - pr_err("Unable to lcoate struct tcm_qla2xxx_lport->tpg_1\n"); - return -EINVAL; - } - se_tpg = &tpg->se_tpg; - - se_sess = transport_init_session(); - if (IS_ERR(se_sess)) { - pr_err("Unable to initialize struct se_session\n"); - return PTR_ERR(se_sess); - } - /* - * Format the FCP Initiator port_name into colon seperated values to - * match the format by tcm_qla2xxx explict ConfigFS NodeACLs. - */ - memset(&port_name, 0, 36); - snprintf(port_name, 36, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - fc_wwpn[0], fc_wwpn[1], fc_wwpn[2], fc_wwpn[3], fc_wwpn[4], - fc_wwpn[5], fc_wwpn[6], fc_wwpn[7]); - /* - * Locate our struct se_node_acl either from an explict NodeACL created - * via ConfigFS, or via running in TPG demo mode. - */ - se_sess->se_node_acl = core_tpg_check_initiator_node_acl(se_tpg, - port_name); - if (!se_sess->se_node_acl) { - transport_free_session(se_sess); - return -EINVAL; - } - se_nacl = se_sess->se_node_acl; - nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); - /* - * And now setup the new se_nacl and session pointers into our HW lport - * mappings for fabric S_ID and LOOP_ID. - */ - spin_lock_irqsave(&ha->hardware_lock, flags); - tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess, - qla_tgt_sess, s_id); - tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, se_sess, - qla_tgt_sess, loop_id); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - /* - * Finally register the new FC Nexus with TCM - */ - __transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); - - return 0; -} - -/* - * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path. - */ -static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { - .handle_cmd = tcm_qla2xxx_handle_cmd, - .handle_data = tcm_qla2xxx_handle_data, - .handle_tmr = tcm_qla2xxx_handle_tmr, - .free_cmd = tcm_qla2xxx_free_cmd, - .free_mcmd = tcm_qla2xxx_free_mcmd, - .free_session = tcm_qla2xxx_free_session, - .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl, - .find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id, - .find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id, - .clear_nacl_from_fcport_map = tcm_qla2xxx_clear_nacl_from_fcport_map, - .put_sess = tcm_qla2xxx_put_sess, - .shutdown_sess = tcm_qla2xxx_shutdown_sess, -}; - -static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport) -{ - int rc; - - rc = btree_init32(&lport->lport_fcport_map); - if (rc) { - pr_err("Unable to initialize lport->lport_fcport_map btree\n"); - return rc; - } - - lport->lport_loopid_map = vmalloc(sizeof(struct tcm_qla2xxx_fc_loopid) * - 65536); - if (!lport->lport_loopid_map) { - pr_err("Unable to allocate lport->lport_loopid_map of %zu bytes\n", - sizeof(struct tcm_qla2xxx_fc_loopid) * 65536); - btree_destroy32(&lport->lport_fcport_map); - return -ENOMEM; - } - memset(lport->lport_loopid_map, 0, sizeof(struct tcm_qla2xxx_fc_loopid) - * 65536); - pr_debug("qla2xxx: Allocated lport_loopid_map of %zu bytes\n", - sizeof(struct tcm_qla2xxx_fc_loopid) * 65536); - return 0; -} - -static int tcm_qla2xxx_lport_register_cb(struct scsi_qla_host *vha) -{ - struct qla_hw_data *ha = vha->hw; - struct tcm_qla2xxx_lport *lport; - /* - * Setup local pointer to vha, NPIV VP pointer (if present) and - * vha->tcm_lport pointer - */ - lport = (struct tcm_qla2xxx_lport *)ha->tgt.target_lport_ptr; - lport->qla_vha = vha; - - return 0; -} - -static struct se_wwn *tcm_qla2xxx_make_lport( - struct target_fabric_configfs *tf, - struct config_group *group, - const char *name) -{ - struct tcm_qla2xxx_lport *lport; - u64 wwpn; - int ret = -ENODEV; - - if (tcm_qla2xxx_parse_wwn(name, &wwpn, 1) < 0) - return ERR_PTR(-EINVAL); - - lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); - if (!lport) { - pr_err("Unable to allocate struct tcm_qla2xxx_lport\n"); - return ERR_PTR(-ENOMEM); - } - lport->lport_wwpn = wwpn; - tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN, - wwpn); - - ret = tcm_qla2xxx_init_lport(lport); - if (ret != 0) - goto out; - - ret = qlt_lport_register(&tcm_qla2xxx_template, wwpn, - tcm_qla2xxx_lport_register_cb, lport); - if (ret != 0) - goto out_lport; - - return &lport->lport_wwn; -out_lport: - vfree(lport->lport_loopid_map); - btree_destroy32(&lport->lport_fcport_map); -out: - kfree(lport); - return ERR_PTR(ret); -} - -static void tcm_qla2xxx_drop_lport(struct se_wwn *wwn) -{ - struct tcm_qla2xxx_lport *lport = container_of(wwn, - struct tcm_qla2xxx_lport, lport_wwn); - struct scsi_qla_host *vha = lport->qla_vha; - struct qla_hw_data *ha = vha->hw; - struct se_node_acl *node; - u32 key = 0; - - /* - * Call into qla2x_target.c LLD logic to complete the - * shutdown of struct qla_tgt after the call to - * qlt_stop_phase1() from tcm_qla2xxx_drop_tpg() above.. - */ - if (ha->tgt.qla_tgt && !ha->tgt.qla_tgt->tgt_stopped) - qlt_stop_phase2(ha->tgt.qla_tgt); - - qlt_lport_deregister(vha); - - vfree(lport->lport_loopid_map); - btree_for_each_safe32(&lport->lport_fcport_map, key, node) - btree_remove32(&lport->lport_fcport_map, key); - btree_destroy32(&lport->lport_fcport_map); - kfree(lport); -} - -static struct se_wwn *tcm_qla2xxx_npiv_make_lport( - struct target_fabric_configfs *tf, - struct config_group *group, - const char *name) -{ - struct tcm_qla2xxx_lport *lport; - u64 npiv_wwpn, npiv_wwnn; - int ret; - - if (tcm_qla2xxx_npiv_parse_wwn(name, strlen(name)+1, - &npiv_wwpn, &npiv_wwnn) < 0) - return ERR_PTR(-EINVAL); - - lport = kzalloc(sizeof(struct tcm_qla2xxx_lport), GFP_KERNEL); - if (!lport) { - pr_err("Unable to allocate struct tcm_qla2xxx_lport for NPIV\n"); - return ERR_PTR(-ENOMEM); - } - lport->lport_npiv_wwpn = npiv_wwpn; - lport->lport_npiv_wwnn = npiv_wwnn; - tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0], - TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); - -/* FIXME: tcm_qla2xxx_npiv_make_lport */ - ret = -ENOSYS; - if (ret != 0) - goto out; - - return &lport->lport_wwn; -out: - kfree(lport); - return ERR_PTR(ret); -} - -static void tcm_qla2xxx_npiv_drop_lport(struct se_wwn *wwn) -{ - struct tcm_qla2xxx_lport *lport = container_of(wwn, - struct tcm_qla2xxx_lport, lport_wwn); - struct scsi_qla_host *vha = lport->qla_vha; - struct Scsi_Host *sh = vha->host; - /* - * Notify libfc that we want to release the lport->npiv_vport - */ - fc_vport_terminate(lport->npiv_vport); - - scsi_host_put(sh); - kfree(lport); -} - - -static ssize_t tcm_qla2xxx_wwn_show_attr_version( - struct target_fabric_configfs *tf, - char *page) -{ - return sprintf(page, - "TCM QLOGIC QLA2XXX NPIV capable fabric module %s on %s/%s on " - UTS_RELEASE"\n", TCM_QLA2XXX_VERSION, utsname()->sysname, - utsname()->machine); -} - -TF_WWN_ATTR_RO(tcm_qla2xxx, version); - -static struct configfs_attribute *tcm_qla2xxx_wwn_attrs[] = { - &tcm_qla2xxx_wwn_version.attr, - NULL, -}; - -static struct target_core_fabric_ops tcm_qla2xxx_ops = { - .get_fabric_name = tcm_qla2xxx_get_fabric_name, - .get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident, - .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, - .tpg_get_tag = tcm_qla2xxx_get_tag, - .tpg_get_default_depth = tcm_qla2xxx_get_default_depth, - .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, - .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, - .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, - .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, - .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, - .tpg_check_demo_mode_write_protect = - tcm_qla2xxx_check_demo_write_protect, - .tpg_check_prod_mode_write_protect = - tcm_qla2xxx_check_prod_write_protect, - .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_true, - .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, - .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, - .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, - .new_cmd_map = NULL, - .check_stop_free = tcm_qla2xxx_check_stop_free, - .release_cmd = tcm_qla2xxx_release_cmd, - .put_session = tcm_qla2xxx_put_session, - .shutdown_session = tcm_qla2xxx_shutdown_session, - .close_session = tcm_qla2xxx_close_session, - .sess_get_index = tcm_qla2xxx_sess_get_index, - .sess_get_initiator_sid = NULL, - .write_pending = tcm_qla2xxx_write_pending, - .write_pending_status = tcm_qla2xxx_write_pending_status, - .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, - .get_task_tag = tcm_qla2xxx_get_task_tag, - .get_cmd_state = tcm_qla2xxx_get_cmd_state, - .queue_data_in = tcm_qla2xxx_queue_data_in, - .queue_status = tcm_qla2xxx_queue_status, - .queue_tm_rsp = tcm_qla2xxx_queue_tm_rsp, - .get_fabric_sense_len = tcm_qla2xxx_get_fabric_sense_len, - .set_fabric_sense_len = tcm_qla2xxx_set_fabric_sense_len, - /* - * Setup function pointers for generic logic in - * target_core_fabric_configfs.c - */ - .fabric_make_wwn = tcm_qla2xxx_make_lport, - .fabric_drop_wwn = tcm_qla2xxx_drop_lport, - .fabric_make_tpg = tcm_qla2xxx_make_tpg, - .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, - .fabric_post_link = NULL, - .fabric_pre_unlink = NULL, - .fabric_make_np = NULL, - .fabric_drop_np = NULL, - .fabric_make_nodeacl = tcm_qla2xxx_make_nodeacl, - .fabric_drop_nodeacl = tcm_qla2xxx_drop_nodeacl, -}; - -static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { - .get_fabric_name = tcm_qla2xxx_npiv_get_fabric_name, - .get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident, - .tpg_get_wwn = tcm_qla2xxx_npiv_get_fabric_wwn, - .tpg_get_tag = tcm_qla2xxx_get_tag, - .tpg_get_default_depth = tcm_qla2xxx_get_default_depth, - .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, - .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, - .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, - .tpg_check_demo_mode = tcm_qla2xxx_check_false, - .tpg_check_demo_mode_cache = tcm_qla2xxx_check_true, - .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_true, - .tpg_check_prod_mode_write_protect = tcm_qla2xxx_check_false, - .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_true, - .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, - .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, - .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, - .release_cmd = tcm_qla2xxx_release_cmd, - .put_session = tcm_qla2xxx_put_session, - .shutdown_session = tcm_qla2xxx_shutdown_session, - .close_session = tcm_qla2xxx_close_session, - .sess_get_index = tcm_qla2xxx_sess_get_index, - .sess_get_initiator_sid = NULL, - .write_pending = tcm_qla2xxx_write_pending, - .write_pending_status = tcm_qla2xxx_write_pending_status, - .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, - .get_task_tag = tcm_qla2xxx_get_task_tag, - .get_cmd_state = tcm_qla2xxx_get_cmd_state, - .queue_data_in = tcm_qla2xxx_queue_data_in, - .queue_status = tcm_qla2xxx_queue_status, - .queue_tm_rsp = tcm_qla2xxx_queue_tm_rsp, - .get_fabric_sense_len = tcm_qla2xxx_get_fabric_sense_len, - .set_fabric_sense_len = tcm_qla2xxx_set_fabric_sense_len, - /* - * Setup function pointers for generic logic in - * target_core_fabric_configfs.c - */ - .fabric_make_wwn = tcm_qla2xxx_npiv_make_lport, - .fabric_drop_wwn = tcm_qla2xxx_npiv_drop_lport, - .fabric_make_tpg = tcm_qla2xxx_npiv_make_tpg, - .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, - .fabric_post_link = NULL, - .fabric_pre_unlink = NULL, - .fabric_make_np = NULL, - .fabric_drop_np = NULL, - .fabric_make_nodeacl = tcm_qla2xxx_make_nodeacl, - .fabric_drop_nodeacl = tcm_qla2xxx_drop_nodeacl, -}; - -static int tcm_qla2xxx_register_configfs(void) -{ - struct target_fabric_configfs *fabric, *npiv_fabric; - int ret; - - pr_debug("TCM QLOGIC QLA2XXX fabric module %s on %s/%s on " - UTS_RELEASE"\n", TCM_QLA2XXX_VERSION, utsname()->sysname, - utsname()->machine); - /* - * Register the top level struct config_item_type with TCM core - */ - fabric = target_fabric_configfs_init(THIS_MODULE, "qla2xxx"); - if (IS_ERR(fabric)) { - pr_err("target_fabric_configfs_init() failed\n"); - return PTR_ERR(fabric); - } - /* - * Setup fabric->tf_ops from our local tcm_qla2xxx_ops - */ - fabric->tf_ops = tcm_qla2xxx_ops; - /* - * Setup default attribute lists for various fabric->tf_cit_tmpl - */ - TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; - TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = tcm_qla2xxx_tpg_attrs; - TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = - tcm_qla2xxx_tpg_attrib_attrs; - TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL; - TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL; - /* - * Register the fabric for use within TCM - */ - ret = target_fabric_configfs_register(fabric); - if (ret < 0) { - pr_err("target_fabric_configfs_register() failed for TCM_QLA2XXX\n"); - return ret; - } - /* - * Setup our local pointer to *fabric - */ - tcm_qla2xxx_fabric_configfs = fabric; - pr_debug("TCM_QLA2XXX[0] - Set fabric -> tcm_qla2xxx_fabric_configfs\n"); - - /* - * Register the top level struct config_item_type for NPIV with TCM core - */ - npiv_fabric = target_fabric_configfs_init(THIS_MODULE, "qla2xxx_npiv"); - if (IS_ERR(npiv_fabric)) { - pr_err("target_fabric_configfs_init() failed\n"); - ret = PTR_ERR(npiv_fabric); - goto out_fabric; - } - /* - * Setup fabric->tf_ops from our local tcm_qla2xxx_npiv_ops - */ - npiv_fabric->tf_ops = tcm_qla2xxx_npiv_ops; - /* - * Setup default attribute lists for various npiv_fabric->tf_cit_tmpl - */ - TF_CIT_TMPL(npiv_fabric)->tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs; - TF_CIT_TMPL(npiv_fabric)->tfc_tpg_base_cit.ct_attrs = NULL; - TF_CIT_TMPL(npiv_fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL; - TF_CIT_TMPL(npiv_fabric)->tfc_tpg_param_cit.ct_attrs = NULL; - TF_CIT_TMPL(npiv_fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL; - TF_CIT_TMPL(npiv_fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL; - TF_CIT_TMPL(npiv_fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; - TF_CIT_TMPL(npiv_fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL; - TF_CIT_TMPL(npiv_fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL; - /* - * Register the npiv_fabric for use within TCM - */ - ret = target_fabric_configfs_register(npiv_fabric); - if (ret < 0) { - pr_err("target_fabric_configfs_register() failed for TCM_QLA2XXX\n"); - goto out_fabric; - } - /* - * Setup our local pointer to *npiv_fabric - */ - tcm_qla2xxx_npiv_fabric_configfs = npiv_fabric; - pr_debug("TCM_QLA2XXX[0] - Set fabric -> tcm_qla2xxx_npiv_fabric_configfs\n"); - - tcm_qla2xxx_free_wq = alloc_workqueue("tcm_qla2xxx_free", - WQ_MEM_RECLAIM, 0); - if (!tcm_qla2xxx_free_wq) { - ret = -ENOMEM; - goto out_fabric_npiv; - } - - tcm_qla2xxx_cmd_wq = alloc_workqueue("tcm_qla2xxx_cmd", 0, 0); - if (!tcm_qla2xxx_cmd_wq) { - ret = -ENOMEM; - goto out_free_wq; - } - - return 0; - -out_free_wq: - destroy_workqueue(tcm_qla2xxx_free_wq); -out_fabric_npiv: - target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs); -out_fabric: - target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs); - return ret; -} - -static void tcm_qla2xxx_deregister_configfs(void) -{ - destroy_workqueue(tcm_qla2xxx_cmd_wq); - destroy_workqueue(tcm_qla2xxx_free_wq); - - target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs); - tcm_qla2xxx_fabric_configfs = NULL; - pr_debug("TCM_QLA2XXX[0] - Cleared tcm_qla2xxx_fabric_configfs\n"); - - target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs); - tcm_qla2xxx_npiv_fabric_configfs = NULL; - pr_debug("TCM_QLA2XXX[0] - Cleared tcm_qla2xxx_npiv_fabric_configfs\n"); -} - -static int __init tcm_qla2xxx_init(void) -{ - int ret; - - ret = tcm_qla2xxx_register_configfs(); - if (ret < 0) - return ret; - - return 0; -} - -static void __exit tcm_qla2xxx_exit(void) -{ - tcm_qla2xxx_deregister_configfs(); -} - -MODULE_DESCRIPTION("TCM QLA2XXX series NPIV enabled fabric driver"); -MODULE_LICENSE("GPL"); -module_init(tcm_qla2xxx_init); -module_exit(tcm_qla2xxx_exit); diff --git a/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.h deleted file mode 100644 index 825498103352..000000000000 --- a/trunk/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include - -#define TCM_QLA2XXX_VERSION "v0.1" -/* length of ASCII WWPNs including pad */ -#define TCM_QLA2XXX_NAMELEN 32 -/* lenth of ASCII NPIV 'WWPN+WWNN' including pad */ -#define TCM_QLA2XXX_NPIV_NAMELEN 66 - -#include "qla_target.h" - -struct tcm_qla2xxx_nacl { - /* From libfc struct fc_rport->port_id */ - u32 nport_id; - /* Binary World Wide unique Node Name for remote FC Initiator Nport */ - u64 nport_wwnn; - /* ASCII formatted WWPN for FC Initiator Nport */ - char nport_name[TCM_QLA2XXX_NAMELEN]; - /* Pointer to qla_tgt_sess */ - struct qla_tgt_sess *qla_tgt_sess; - /* Pointer to TCM FC nexus */ - struct se_session *nport_nexus; - /* Returned by tcm_qla2xxx_make_nodeacl() */ - struct se_node_acl se_node_acl; -}; - -struct tcm_qla2xxx_tpg_attrib { - int generate_node_acls; - int cache_dynamic_acls; - int demo_mode_write_protect; - int prod_mode_write_protect; -}; - -struct tcm_qla2xxx_tpg { - /* FC lport target portal group tag for TCM */ - u16 lport_tpgt; - /* Atomic bit to determine TPG active status */ - atomic_t lport_tpg_enabled; - /* Pointer back to tcm_qla2xxx_lport */ - struct tcm_qla2xxx_lport *lport; - /* Used by tcm_qla2xxx_tpg_attrib_cit */ - struct tcm_qla2xxx_tpg_attrib tpg_attrib; - /* Returned by tcm_qla2xxx_make_tpg() */ - struct se_portal_group se_tpg; -}; - -#define QLA_TPG_ATTRIB(tpg) (&(tpg)->tpg_attrib) - -struct tcm_qla2xxx_fc_loopid { - struct se_node_acl *se_nacl; -}; - -struct tcm_qla2xxx_lport { - /* SCSI protocol the lport is providing */ - u8 lport_proto_id; - /* Binary World Wide unique Port Name for FC Target Lport */ - u64 lport_wwpn; - /* Binary World Wide unique Port Name for FC NPIV Target Lport */ - u64 lport_npiv_wwpn; - /* Binary World Wide unique Node Name for FC NPIV Target Lport */ - u64 lport_npiv_wwnn; - /* ASCII formatted WWPN for FC Target Lport */ - char lport_name[TCM_QLA2XXX_NAMELEN]; - /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */ - char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN]; - /* map for fc_port pointers in 24-bit FC Port ID space */ - struct btree_head32 lport_fcport_map; - /* vmalloc-ed memory for fc_port pointers for 16-bit FC loop ID */ - struct tcm_qla2xxx_fc_loopid *lport_loopid_map; - /* Pointer to struct scsi_qla_host from qla2xxx LLD */ - struct scsi_qla_host *qla_vha; - /* Pointer to struct scsi_qla_host for NPIV VP from qla2xxx LLD */ - struct scsi_qla_host *qla_npiv_vp; - /* Pointer to struct qla_tgt pointer */ - struct qla_tgt lport_qla_tgt; - /* Pointer to struct fc_vport for NPIV vport from libfc */ - struct fc_vport *npiv_vport; - /* Pointer to TPG=1 for non NPIV mode */ - struct tcm_qla2xxx_tpg *tpg_1; - /* Returned by tcm_qla2xxx_make_lport() */ - struct se_wwn lport_wwn; -}; diff --git a/trunk/drivers/scsi/qla4xxx/ql4_attr.c b/trunk/drivers/scsi/qla4xxx/ql4_attr.c index c681b2a355e1..0b0a7d42137d 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_attr.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_attr.c @@ -9,140 +9,6 @@ #include "ql4_glbl.h" #include "ql4_dbg.h" -static ssize_t -qla4_8xxx_sysfs_read_fw_dump(struct file *filep, struct kobject *kobj, - struct bin_attribute *ba, char *buf, loff_t off, - size_t count) -{ - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, - struct device, kobj))); - - if (!is_qla8022(ha)) - return -EINVAL; - - if (!test_bit(AF_82XX_DUMP_READING, &ha->flags)) - return 0; - - return memory_read_from_buffer(buf, count, &off, ha->fw_dump, - ha->fw_dump_size); -} - -static ssize_t -qla4_8xxx_sysfs_write_fw_dump(struct file *filep, struct kobject *kobj, - struct bin_attribute *ba, char *buf, loff_t off, - size_t count) -{ - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, - struct device, kobj))); - uint32_t dev_state; - long reading; - int ret = 0; - - if (!is_qla8022(ha)) - return -EINVAL; - - if (off != 0) - return ret; - - buf[1] = 0; - ret = kstrtol(buf, 10, &reading); - if (ret) { - ql4_printk(KERN_ERR, ha, "%s: Invalid input. Return err %d\n", - __func__, ret); - return ret; - } - - switch (reading) { - case 0: - /* clear dump collection flags */ - if (test_and_clear_bit(AF_82XX_DUMP_READING, &ha->flags)) { - clear_bit(AF_82XX_FW_DUMPED, &ha->flags); - /* Reload minidump template */ - qla4xxx_alloc_fw_dump(ha); - DEBUG2(ql4_printk(KERN_INFO, ha, - "Firmware template reloaded\n")); - } - break; - case 1: - /* Set flag to read dump */ - if (test_bit(AF_82XX_FW_DUMPED, &ha->flags) && - !test_bit(AF_82XX_DUMP_READING, &ha->flags)) { - set_bit(AF_82XX_DUMP_READING, &ha->flags); - DEBUG2(ql4_printk(KERN_INFO, ha, - "Raw firmware dump ready for read on (%ld).\n", - ha->host_no)); - } - break; - case 2: - /* Reset HBA */ - qla4_8xxx_idc_lock(ha); - dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); - if (dev_state == QLA82XX_DEV_READY) { - ql4_printk(KERN_INFO, ha, - "%s: Setting Need reset, reset_owner is 0x%x.\n", - __func__, ha->func_num); - qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, - QLA82XX_DEV_NEED_RESET); - set_bit(AF_82XX_RST_OWNER, &ha->flags); - } else - ql4_printk(KERN_INFO, ha, - "%s: Reset not performed as device state is 0x%x\n", - __func__, dev_state); - - qla4_8xxx_idc_unlock(ha); - break; - default: - /* do nothing */ - break; - } - - return count; -} - -static struct bin_attribute sysfs_fw_dump_attr = { - .attr = { - .name = "fw_dump", - .mode = S_IRUSR | S_IWUSR, - }, - .size = 0, - .read = qla4_8xxx_sysfs_read_fw_dump, - .write = qla4_8xxx_sysfs_write_fw_dump, -}; - -static struct sysfs_entry { - char *name; - struct bin_attribute *attr; -} bin_file_entries[] = { - { "fw_dump", &sysfs_fw_dump_attr }, - { NULL }, -}; - -void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha) -{ - struct Scsi_Host *host = ha->host; - struct sysfs_entry *iter; - int ret; - - for (iter = bin_file_entries; iter->name; iter++) { - ret = sysfs_create_bin_file(&host->shost_gendev.kobj, - iter->attr); - if (ret) - ql4_printk(KERN_ERR, ha, - "Unable to create sysfs %s binary attribute (%d).\n", - iter->name, ret); - } -} - -void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha) -{ - struct Scsi_Host *host = ha->host; - struct sysfs_entry *iter; - - for (iter = bin_file_entries; iter->name; iter++) - sysfs_remove_bin_file(&host->shost_gendev.kobj, - iter->attr); -} - /* Scsi_Host attributes. */ static ssize_t qla4xxx_fw_version_show(struct device *dev, diff --git a/trunk/drivers/scsi/qla4xxx/ql4_def.h b/trunk/drivers/scsi/qla4xxx/ql4_def.h index 96a5616a8fda..7f2492e88be7 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_def.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_def.h @@ -398,16 +398,6 @@ struct isp_operations { int (*get_sys_info) (struct scsi_qla_host *); }; -struct ql4_mdump_size_table { - uint32_t size; - uint32_t size_cmask_02; - uint32_t size_cmask_04; - uint32_t size_cmask_08; - uint32_t size_cmask_10; - uint32_t size_cmask_FF; - uint32_t version; -}; - /*qla4xxx ipaddress configuration details */ struct ipaddress_config { uint16_t ipv4_options; @@ -495,10 +485,6 @@ struct scsi_qla_host { #define AF_EEH_BUSY 20 /* 0x00100000 */ #define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ #define AF_BUILD_DDB_LIST 22 /* 0x00400000 */ -#define AF_82XX_FW_DUMPED 24 /* 0x01000000 */ -#define AF_82XX_RST_OWNER 25 /* 0x02000000 */ -#define AF_82XX_DUMP_READING 26 /* 0x04000000 */ - unsigned long dpc_flags; #define DPC_RESET_HA 1 /* 0x00000002 */ @@ -676,11 +662,6 @@ struct scsi_qla_host { uint32_t nx_dev_init_timeout; uint32_t nx_reset_timeout; - void *fw_dump; - uint32_t fw_dump_size; - uint32_t fw_dump_capture_mask; - void *fw_dump_tmplt_hdr; - uint32_t fw_dump_tmplt_size; struct completion mbx_intr_comp; @@ -955,7 +936,4 @@ static inline int ql4xxx_reset_active(struct scsi_qla_host *ha) #define PROCESS_ALL_AENS 0 #define FLUSH_DDB_CHANGED_AENS 1 -/* Defines for udev events */ -#define QL4_UEVENT_CODE_FW_DUMP 0 - #endif /*_QLA4XXX_H */ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_fw.h b/trunk/drivers/scsi/qla4xxx/ql4_fw.h index 7240948fb929..210cd1d64475 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_fw.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_fw.h @@ -385,11 +385,6 @@ struct qla_flt_region { #define MBOX_CMD_GET_IP_ADDR_STATE 0x0091 #define MBOX_CMD_SEND_IPV6_ROUTER_SOL 0x0092 #define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093 -#define MBOX_CMD_MINIDUMP 0x0129 - -/* Minidump subcommand */ -#define MINIDUMP_GET_SIZE_SUBCOMMAND 0x00 -#define MINIDUMP_GET_TMPLT_SUBCOMMAND 0x01 /* Mailbox 1 */ #define FW_STATE_READY 0x0000 @@ -1195,27 +1190,4 @@ struct ql_iscsi_stats { uint8_t reserved2[264]; /* 0x0308 - 0x040F */ }; -#define QLA82XX_DBG_STATE_ARRAY_LEN 16 -#define QLA82XX_DBG_CAP_SIZE_ARRAY_LEN 8 -#define QLA82XX_DBG_RSVD_ARRAY_LEN 8 - -struct qla4_8xxx_minidump_template_hdr { - uint32_t entry_type; - uint32_t first_entry_offset; - uint32_t size_of_template; - uint32_t capture_debug_level; - uint32_t num_of_entries; - uint32_t version; - uint32_t driver_timestamp; - uint32_t checksum; - - uint32_t driver_capture_mask; - uint32_t driver_info_word2; - uint32_t driver_info_word3; - uint32_t driver_info_word4; - - uint32_t saved_state_array[QLA82XX_DBG_STATE_ARRAY_LEN]; - uint32_t capture_size_array[QLA82XX_DBG_CAP_SIZE_ARRAY_LEN]; -}; - #endif /* _QLA4X_FW_H */ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_glbl.h b/trunk/drivers/scsi/qla4xxx/ql4_glbl.h index 20b49d019043..910536667cf5 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_glbl.h @@ -196,18 +196,10 @@ int qla4xxx_bsg_request(struct bsg_job *bsg_job); int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job); void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry); -int qla4xxx_get_minidump_template(struct scsi_qla_host *ha, - dma_addr_t phys_addr); -int qla4xxx_req_template_size(struct scsi_qla_host *ha); -void qla4_8xxx_alloc_sysfs_attr(struct scsi_qla_host *ha); -void qla4_8xxx_free_sysfs_attr(struct scsi_qla_host *ha); -void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha); extern int ql4xextended_error_logging; extern int ql4xdontresethba; extern int ql4xenablemsix; -extern int ql4xmdcapmask; -extern int ql4xenablemd; extern struct device_attribute *qla4xxx_host_attrs[]; #endif /* _QLA4x_GBL_H */ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_init.c b/trunk/drivers/scsi/qla4xxx/ql4_init.c index bf36723b84e1..90ee5d8fa731 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_init.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_init.c @@ -277,94 +277,6 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha) return ipv4_wait|ipv6_wait; } -/** - * qla4xxx_alloc_fw_dump - Allocate memory for minidump data. - * @ha: pointer to host adapter structure. - **/ -void qla4xxx_alloc_fw_dump(struct scsi_qla_host *ha) -{ - int status; - uint32_t capture_debug_level; - int hdr_entry_bit, k; - void *md_tmp; - dma_addr_t md_tmp_dma; - struct qla4_8xxx_minidump_template_hdr *md_hdr; - - if (ha->fw_dump) { - ql4_printk(KERN_WARNING, ha, - "Firmware dump previously allocated.\n"); - return; - } - - status = qla4xxx_req_template_size(ha); - if (status != QLA_SUCCESS) { - ql4_printk(KERN_INFO, ha, - "scsi%ld: Failed to get template size\n", - ha->host_no); - return; - } - - clear_bit(AF_82XX_FW_DUMPED, &ha->flags); - - /* Allocate memory for saving the template */ - md_tmp = dma_alloc_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size, - &md_tmp_dma, GFP_KERNEL); - - /* Request template */ - status = qla4xxx_get_minidump_template(ha, md_tmp_dma); - if (status != QLA_SUCCESS) { - ql4_printk(KERN_INFO, ha, - "scsi%ld: Failed to get minidump template\n", - ha->host_no); - goto alloc_cleanup; - } - - md_hdr = (struct qla4_8xxx_minidump_template_hdr *)md_tmp; - - capture_debug_level = md_hdr->capture_debug_level; - - /* Get capture mask based on module loadtime setting. */ - if (ql4xmdcapmask >= 0x3 && ql4xmdcapmask <= 0x7F) - ha->fw_dump_capture_mask = ql4xmdcapmask; - else - ha->fw_dump_capture_mask = capture_debug_level; - - md_hdr->driver_capture_mask = ha->fw_dump_capture_mask; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Minimum num of entries = %d\n", - md_hdr->num_of_entries)); - DEBUG2(ql4_printk(KERN_INFO, ha, "Dump template size = %d\n", - ha->fw_dump_tmplt_size)); - DEBUG2(ql4_printk(KERN_INFO, ha, "Selected Capture mask =0x%x\n", - ha->fw_dump_capture_mask)); - - /* Calculate fw_dump_size */ - for (hdr_entry_bit = 0x2, k = 1; (hdr_entry_bit & 0xFF); - hdr_entry_bit <<= 1, k++) { - if (hdr_entry_bit & ha->fw_dump_capture_mask) - ha->fw_dump_size += md_hdr->capture_size_array[k]; - } - - /* Total firmware dump size including command header */ - ha->fw_dump_size += ha->fw_dump_tmplt_size; - ha->fw_dump = vmalloc(ha->fw_dump_size); - if (!ha->fw_dump) - goto alloc_cleanup; - - DEBUG2(ql4_printk(KERN_INFO, ha, - "Minidump Tempalate Size = 0x%x KB\n", - ha->fw_dump_tmplt_size)); - DEBUG2(ql4_printk(KERN_INFO, ha, - "Total Minidump size = 0x%x KB\n", ha->fw_dump_size)); - - memcpy(ha->fw_dump, md_tmp, ha->fw_dump_tmplt_size); - ha->fw_dump_tmplt_hdr = ha->fw_dump; - -alloc_cleanup: - dma_free_coherent(&ha->pdev->dev, ha->fw_dump_tmplt_size, - md_tmp, md_tmp_dma); -} - static int qla4xxx_fw_ready(struct scsi_qla_host *ha) { uint32_t timeout_count; @@ -533,13 +445,9 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) "control block\n", ha->host_no, __func__)); return status; } - if (!qla4xxx_fw_ready(ha)) return status; - if (is_qla8022(ha) && !test_bit(AF_INIT_DONE, &ha->flags)) - qla4xxx_alloc_fw_dump(ha); - return qla4xxx_get_firmware_status(ha); } @@ -976,8 +884,8 @@ int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, switch (state) { case DDB_DS_SESSION_ACTIVE: case DDB_DS_DISCOVERY: - qla4xxx_update_session_conn_param(ha, ddb_entry); ddb_entry->unblock_sess(ddb_entry->sess); + qla4xxx_update_session_conn_param(ha, ddb_entry); status = QLA_SUCCESS; break; case DDB_DS_SESSION_FAILED: @@ -989,7 +897,6 @@ int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, } break; case DDB_DS_SESSION_ACTIVE: - case DDB_DS_DISCOVERY: switch (state) { case DDB_DS_SESSION_FAILED: /* diff --git a/trunk/drivers/scsi/qla4xxx/ql4_mbx.c b/trunk/drivers/scsi/qla4xxx/ql4_mbx.c index cab8f665a41f..7ac21dabbf22 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_mbx.c @@ -51,6 +51,25 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, } } + if (is_qla8022(ha)) { + if (test_bit(AF_FW_RECOVERY, &ha->flags)) { + DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " + "prematurely completing mbx cmd as firmware " + "recovery detected\n", ha->host_no, __func__)); + return status; + } + /* Do not send any mbx cmd if h/w is in failed state*/ + qla4_8xxx_idc_lock(ha); + dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); + qla4_8xxx_idc_unlock(ha); + if (dev_state == QLA82XX_DEV_FAILED) { + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: H/W is in " + "failed state, do not send any mailbox commands\n", + ha->host_no, __func__); + return status; + } + } + if ((is_aer_supported(ha)) && (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " @@ -77,25 +96,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, msleep(10); } - if (is_qla8022(ha)) { - if (test_bit(AF_FW_RECOVERY, &ha->flags)) { - DEBUG2(ql4_printk(KERN_WARNING, ha, - "scsi%ld: %s: prematurely completing mbx cmd as firmware recovery detected\n", - ha->host_no, __func__)); - goto mbox_exit; - } - /* Do not send any mbx cmd if h/w is in failed state*/ - qla4_8xxx_idc_lock(ha); - dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); - qla4_8xxx_idc_unlock(ha); - if (dev_state == QLA82XX_DEV_FAILED) { - ql4_printk(KERN_WARNING, ha, - "scsi%ld: %s: H/W is in failed state, do not send any mailbox commands\n", - ha->host_no, __func__); - goto mbox_exit; - } - } - spin_lock_irqsave(&ha->hardware_lock, flags); ha->mbox_status_count = outCount; @@ -270,79 +270,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, return status; } -/** - * qla4xxx_get_minidump_template - Get the firmware template - * @ha: Pointer to host adapter structure. - * @phys_addr: dma address for template - * - * Obtain the minidump template from firmware during initialization - * as it may not be available when minidump is desired. - **/ -int qla4xxx_get_minidump_template(struct scsi_qla_host *ha, - dma_addr_t phys_addr) -{ - uint32_t mbox_cmd[MBOX_REG_COUNT]; - uint32_t mbox_sts[MBOX_REG_COUNT]; - int status; - - memset(&mbox_cmd, 0, sizeof(mbox_cmd)); - memset(&mbox_sts, 0, sizeof(mbox_sts)); - - mbox_cmd[0] = MBOX_CMD_MINIDUMP; - mbox_cmd[1] = MINIDUMP_GET_TMPLT_SUBCOMMAND; - mbox_cmd[2] = LSDW(phys_addr); - mbox_cmd[3] = MSDW(phys_addr); - mbox_cmd[4] = ha->fw_dump_tmplt_size; - mbox_cmd[5] = 0; - - status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], - &mbox_sts[0]); - if (status != QLA_SUCCESS) { - DEBUG2(ql4_printk(KERN_INFO, ha, - "scsi%ld: %s: Cmd = %08X, mbx[0] = 0x%04x, mbx[1] = 0x%04x\n", - ha->host_no, __func__, mbox_cmd[0], - mbox_sts[0], mbox_sts[1])); - } - return status; -} - -/** - * qla4xxx_req_template_size - Get minidump template size from firmware. - * @ha: Pointer to host adapter structure. - **/ -int qla4xxx_req_template_size(struct scsi_qla_host *ha) -{ - uint32_t mbox_cmd[MBOX_REG_COUNT]; - uint32_t mbox_sts[MBOX_REG_COUNT]; - int status; - - memset(&mbox_cmd, 0, sizeof(mbox_cmd)); - memset(&mbox_sts, 0, sizeof(mbox_sts)); - - mbox_cmd[0] = MBOX_CMD_MINIDUMP; - mbox_cmd[1] = MINIDUMP_GET_SIZE_SUBCOMMAND; - - status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], - &mbox_sts[0]); - if (status == QLA_SUCCESS) { - ha->fw_dump_tmplt_size = mbox_sts[1]; - DEBUG2(ql4_printk(KERN_INFO, ha, - "%s: sts[0]=0x%04x, template size=0x%04x, size_cm_02=0x%04x, size_cm_04=0x%04x, size_cm_08=0x%04x, size_cm_10=0x%04x, size_cm_FF=0x%04x, version=0x%04x\n", - __func__, mbox_sts[0], mbox_sts[1], - mbox_sts[2], mbox_sts[3], mbox_sts[4], - mbox_sts[5], mbox_sts[6], mbox_sts[7])); - if (ha->fw_dump_tmplt_size == 0) - status = QLA_ERROR; - } else { - ql4_printk(KERN_WARNING, ha, - "%s: Error sts[0]=0x%04x, mbx[1]=0x%04x\n", - __func__, mbox_sts[0], mbox_sts[1]); - status = QLA_ERROR; - } - - return status; -} - void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) { set_bit(AF_FW_RECOVERY, &ha->flags); diff --git a/trunk/drivers/scsi/qla4xxx/ql4_nx.c b/trunk/drivers/scsi/qla4xxx/ql4_nx.c index 228b67020d2c..e1e46b6dac75 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_nx.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_nx.c @@ -7,7 +7,6 @@ #include #include #include -#include #include "ql4_def.h" #include "ql4_glbl.h" @@ -421,38 +420,6 @@ qla4_8xxx_rd_32(struct scsi_qla_host *ha, ulong off) return data; } -/* Minidump related functions */ -static int qla4_8xxx_md_rw_32(struct scsi_qla_host *ha, uint32_t off, - u32 data, uint8_t flag) -{ - uint32_t win_read, off_value, rval = QLA_SUCCESS; - - off_value = off & 0xFFFF0000; - writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); - - /* Read back value to make sure write has gone through before trying - * to use it. - */ - win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); - if (win_read != off_value) { - DEBUG2(ql4_printk(KERN_INFO, ha, - "%s: Written (0x%x) != Read (0x%x), off=0x%x\n", - __func__, off_value, win_read, off)); - return QLA_ERROR; - } - - off_value = off & 0x0000FFFF; - - if (flag) - writel(data, (void __iomem *)(off_value + CRB_INDIRECT_2M + - ha->nx_pcibase)); - else - rval = readl((void __iomem *)(off_value + CRB_INDIRECT_2M + - ha->nx_pcibase)); - - return rval; -} - #define CRB_WIN_LOCK_TIMEOUT 100000000 int qla4_8xxx_crb_win_lock(struct scsi_qla_host *ha) @@ -1285,9 +1252,9 @@ qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *ha, } if (j >= MAX_CTL_CHECK) { - printk_ratelimited(KERN_ERR - "%s: failed to read through agent\n", - __func__); + if (printk_ratelimit()) + ql4_printk(KERN_ERR, ha, + "failed to read through agent\n"); break; } @@ -1423,8 +1390,7 @@ qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha, if (j >= MAX_CTL_CHECK) { if (printk_ratelimit()) ql4_printk(KERN_ERR, ha, - "%s: failed to read through agent\n", - __func__); + "failed to write through agent\n"); ret = -1; break; } @@ -1496,8 +1462,6 @@ qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); drv_active |= (1 << (ha->func_num * 4)); - ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", - __func__, ha->host_no, drv_active); qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); } @@ -1508,8 +1472,6 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); drv_active &= ~(1 << (ha->func_num * 4)); - ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", - __func__, ha->host_no, drv_active); qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); } @@ -1535,8 +1497,6 @@ qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha) drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); drv_state |= (1 << (ha->func_num * 4)); - ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", - __func__, ha->host_no, drv_state); qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); } @@ -1547,8 +1507,6 @@ qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha) drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); drv_state &= ~(1 << (ha->func_num * 4)); - ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", - __func__, ha->host_no, drv_state); qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); } @@ -1643,629 +1601,6 @@ static void qla4_8xxx_rom_lock_recovery(struct scsi_qla_host *ha) qla4_8xxx_rom_unlock(ha); } -static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - uint32_t **d_ptr) -{ - uint32_t r_addr, r_stride, loop_cnt, i, r_value; - struct qla82xx_minidump_entry_crb *crb_hdr; - uint32_t *data_ptr = *d_ptr; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); - crb_hdr = (struct qla82xx_minidump_entry_crb *)entry_hdr; - r_addr = crb_hdr->addr; - r_stride = crb_hdr->crb_strd.addr_stride; - loop_cnt = crb_hdr->op_count; - - for (i = 0; i < loop_cnt; i++) { - r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); - *data_ptr++ = cpu_to_le32(r_addr); - *data_ptr++ = cpu_to_le32(r_value); - r_addr += r_stride; - } - *d_ptr = data_ptr; -} - -static int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - uint32_t **d_ptr) -{ - uint32_t addr, r_addr, c_addr, t_r_addr; - uint32_t i, k, loop_count, t_value, r_cnt, r_value; - unsigned long p_wait, w_time, p_mask; - uint32_t c_value_w, c_value_r; - struct qla82xx_minidump_entry_cache *cache_hdr; - int rval = QLA_ERROR; - uint32_t *data_ptr = *d_ptr; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); - cache_hdr = (struct qla82xx_minidump_entry_cache *)entry_hdr; - - loop_count = cache_hdr->op_count; - r_addr = cache_hdr->read_addr; - c_addr = cache_hdr->control_addr; - c_value_w = cache_hdr->cache_ctrl.write_value; - - t_r_addr = cache_hdr->tag_reg_addr; - t_value = cache_hdr->addr_ctrl.init_tag_value; - r_cnt = cache_hdr->read_ctrl.read_addr_cnt; - p_wait = cache_hdr->cache_ctrl.poll_wait; - p_mask = cache_hdr->cache_ctrl.poll_mask; - - for (i = 0; i < loop_count; i++) { - qla4_8xxx_md_rw_32(ha, t_r_addr, t_value, 1); - - if (c_value_w) - qla4_8xxx_md_rw_32(ha, c_addr, c_value_w, 1); - - if (p_mask) { - w_time = jiffies + p_wait; - do { - c_value_r = qla4_8xxx_md_rw_32(ha, c_addr, - 0, 0); - if ((c_value_r & p_mask) == 0) { - break; - } else if (time_after_eq(jiffies, w_time)) { - /* capturing dump failed */ - return rval; - } - } while (1); - } - - addr = r_addr; - for (k = 0; k < r_cnt; k++) { - r_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); - *data_ptr++ = cpu_to_le32(r_value); - addr += cache_hdr->read_ctrl.read_addr_stride; - } - - t_value += cache_hdr->addr_ctrl.tag_value_stride; - } - *d_ptr = data_ptr; - return QLA_SUCCESS; -} - -static int qla4_8xxx_minidump_process_control(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr) -{ - struct qla82xx_minidump_entry_crb *crb_entry; - uint32_t read_value, opcode, poll_time, addr, index, rval = QLA_SUCCESS; - uint32_t crb_addr; - unsigned long wtime; - struct qla4_8xxx_minidump_template_hdr *tmplt_hdr; - int i; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); - tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) - ha->fw_dump_tmplt_hdr; - crb_entry = (struct qla82xx_minidump_entry_crb *)entry_hdr; - - crb_addr = crb_entry->addr; - for (i = 0; i < crb_entry->op_count; i++) { - opcode = crb_entry->crb_ctrl.opcode; - if (opcode & QLA82XX_DBG_OPCODE_WR) { - qla4_8xxx_md_rw_32(ha, crb_addr, - crb_entry->value_1, 1); - opcode &= ~QLA82XX_DBG_OPCODE_WR; - } - if (opcode & QLA82XX_DBG_OPCODE_RW) { - read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); - qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); - opcode &= ~QLA82XX_DBG_OPCODE_RW; - } - if (opcode & QLA82XX_DBG_OPCODE_AND) { - read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); - read_value &= crb_entry->value_2; - opcode &= ~QLA82XX_DBG_OPCODE_AND; - if (opcode & QLA82XX_DBG_OPCODE_OR) { - read_value |= crb_entry->value_3; - opcode &= ~QLA82XX_DBG_OPCODE_OR; - } - qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); - } - if (opcode & QLA82XX_DBG_OPCODE_OR) { - read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); - read_value |= crb_entry->value_3; - qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); - opcode &= ~QLA82XX_DBG_OPCODE_OR; - } - if (opcode & QLA82XX_DBG_OPCODE_POLL) { - poll_time = crb_entry->crb_strd.poll_timeout; - wtime = jiffies + poll_time; - read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); - - do { - if ((read_value & crb_entry->value_2) == - crb_entry->value_1) - break; - else if (time_after_eq(jiffies, wtime)) { - /* capturing dump failed */ - rval = QLA_ERROR; - break; - } else - read_value = qla4_8xxx_md_rw_32(ha, - crb_addr, 0, 0); - } while (1); - opcode &= ~QLA82XX_DBG_OPCODE_POLL; - } - - if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) { - if (crb_entry->crb_strd.state_index_a) { - index = crb_entry->crb_strd.state_index_a; - addr = tmplt_hdr->saved_state_array[index]; - } else { - addr = crb_addr; - } - - read_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); - index = crb_entry->crb_ctrl.state_index_v; - tmplt_hdr->saved_state_array[index] = read_value; - opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE; - } - - if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) { - if (crb_entry->crb_strd.state_index_a) { - index = crb_entry->crb_strd.state_index_a; - addr = tmplt_hdr->saved_state_array[index]; - } else { - addr = crb_addr; - } - - if (crb_entry->crb_ctrl.state_index_v) { - index = crb_entry->crb_ctrl.state_index_v; - read_value = - tmplt_hdr->saved_state_array[index]; - } else { - read_value = crb_entry->value_1; - } - - qla4_8xxx_md_rw_32(ha, addr, read_value, 1); - opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE; - } - - if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) { - index = crb_entry->crb_ctrl.state_index_v; - read_value = tmplt_hdr->saved_state_array[index]; - read_value <<= crb_entry->crb_ctrl.shl; - read_value >>= crb_entry->crb_ctrl.shr; - if (crb_entry->value_2) - read_value &= crb_entry->value_2; - read_value |= crb_entry->value_3; - read_value += crb_entry->value_1; - tmplt_hdr->saved_state_array[index] = read_value; - opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE; - } - crb_addr += crb_entry->crb_strd.addr_stride; - } - DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__)); - return rval; -} - -static void qla4_8xxx_minidump_process_rdocm(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - uint32_t **d_ptr) -{ - uint32_t r_addr, r_stride, loop_cnt, i, r_value; - struct qla82xx_minidump_entry_rdocm *ocm_hdr; - uint32_t *data_ptr = *d_ptr; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); - ocm_hdr = (struct qla82xx_minidump_entry_rdocm *)entry_hdr; - r_addr = ocm_hdr->read_addr; - r_stride = ocm_hdr->read_addr_stride; - loop_cnt = ocm_hdr->op_count; - - DEBUG2(ql4_printk(KERN_INFO, ha, - "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n", - __func__, r_addr, r_stride, loop_cnt)); - - for (i = 0; i < loop_cnt; i++) { - r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase)); - *data_ptr++ = cpu_to_le32(r_value); - r_addr += r_stride; - } - DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%lx\n", - __func__, (loop_cnt * sizeof(uint32_t)))); - *d_ptr = data_ptr; -} - -static void qla4_8xxx_minidump_process_rdmux(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - uint32_t **d_ptr) -{ - uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value; - struct qla82xx_minidump_entry_mux *mux_hdr; - uint32_t *data_ptr = *d_ptr; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); - mux_hdr = (struct qla82xx_minidump_entry_mux *)entry_hdr; - r_addr = mux_hdr->read_addr; - s_addr = mux_hdr->select_addr; - s_stride = mux_hdr->select_value_stride; - s_value = mux_hdr->select_value; - loop_cnt = mux_hdr->op_count; - - for (i = 0; i < loop_cnt; i++) { - qla4_8xxx_md_rw_32(ha, s_addr, s_value, 1); - r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); - *data_ptr++ = cpu_to_le32(s_value); - *data_ptr++ = cpu_to_le32(r_value); - s_value += s_stride; - } - *d_ptr = data_ptr; -} - -static void qla4_8xxx_minidump_process_l1cache(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - uint32_t **d_ptr) -{ - uint32_t addr, r_addr, c_addr, t_r_addr; - uint32_t i, k, loop_count, t_value, r_cnt, r_value; - uint32_t c_value_w; - struct qla82xx_minidump_entry_cache *cache_hdr; - uint32_t *data_ptr = *d_ptr; - - cache_hdr = (struct qla82xx_minidump_entry_cache *)entry_hdr; - loop_count = cache_hdr->op_count; - r_addr = cache_hdr->read_addr; - c_addr = cache_hdr->control_addr; - c_value_w = cache_hdr->cache_ctrl.write_value; - - t_r_addr = cache_hdr->tag_reg_addr; - t_value = cache_hdr->addr_ctrl.init_tag_value; - r_cnt = cache_hdr->read_ctrl.read_addr_cnt; - - for (i = 0; i < loop_count; i++) { - qla4_8xxx_md_rw_32(ha, t_r_addr, t_value, 1); - qla4_8xxx_md_rw_32(ha, c_addr, c_value_w, 1); - addr = r_addr; - for (k = 0; k < r_cnt; k++) { - r_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); - *data_ptr++ = cpu_to_le32(r_value); - addr += cache_hdr->read_ctrl.read_addr_stride; - } - t_value += cache_hdr->addr_ctrl.tag_value_stride; - } - *d_ptr = data_ptr; -} - -static void qla4_8xxx_minidump_process_queue(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - uint32_t **d_ptr) -{ - uint32_t s_addr, r_addr; - uint32_t r_stride, r_value, r_cnt, qid = 0; - uint32_t i, k, loop_cnt; - struct qla82xx_minidump_entry_queue *q_hdr; - uint32_t *data_ptr = *d_ptr; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); - q_hdr = (struct qla82xx_minidump_entry_queue *)entry_hdr; - s_addr = q_hdr->select_addr; - r_cnt = q_hdr->rd_strd.read_addr_cnt; - r_stride = q_hdr->rd_strd.read_addr_stride; - loop_cnt = q_hdr->op_count; - - for (i = 0; i < loop_cnt; i++) { - qla4_8xxx_md_rw_32(ha, s_addr, qid, 1); - r_addr = q_hdr->read_addr; - for (k = 0; k < r_cnt; k++) { - r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); - *data_ptr++ = cpu_to_le32(r_value); - r_addr += r_stride; - } - qid += q_hdr->q_strd.queue_id_stride; - } - *d_ptr = data_ptr; -} - -#define MD_DIRECT_ROM_WINDOW 0x42110030 -#define MD_DIRECT_ROM_READ_BASE 0x42150000 - -static void qla4_8xxx_minidump_process_rdrom(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - uint32_t **d_ptr) -{ - uint32_t r_addr, r_value; - uint32_t i, loop_cnt; - struct qla82xx_minidump_entry_rdrom *rom_hdr; - uint32_t *data_ptr = *d_ptr; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); - rom_hdr = (struct qla82xx_minidump_entry_rdrom *)entry_hdr; - r_addr = rom_hdr->read_addr; - loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t); - - DEBUG2(ql4_printk(KERN_INFO, ha, - "[%s]: flash_addr: 0x%x, read_data_size: 0x%x\n", - __func__, r_addr, loop_cnt)); - - for (i = 0; i < loop_cnt; i++) { - qla4_8xxx_md_rw_32(ha, MD_DIRECT_ROM_WINDOW, - (r_addr & 0xFFFF0000), 1); - r_value = qla4_8xxx_md_rw_32(ha, - MD_DIRECT_ROM_READ_BASE + - (r_addr & 0x0000FFFF), 0, 0); - *data_ptr++ = cpu_to_le32(r_value); - r_addr += sizeof(uint32_t); - } - *d_ptr = data_ptr; -} - -#define MD_MIU_TEST_AGT_CTRL 0x41000090 -#define MD_MIU_TEST_AGT_ADDR_LO 0x41000094 -#define MD_MIU_TEST_AGT_ADDR_HI 0x41000098 - -static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - uint32_t **d_ptr) -{ - uint32_t r_addr, r_value, r_data; - uint32_t i, j, loop_cnt; - struct qla82xx_minidump_entry_rdmem *m_hdr; - unsigned long flags; - uint32_t *data_ptr = *d_ptr; - - DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); - m_hdr = (struct qla82xx_minidump_entry_rdmem *)entry_hdr; - r_addr = m_hdr->read_addr; - loop_cnt = m_hdr->read_data_size/16; - - DEBUG2(ql4_printk(KERN_INFO, ha, - "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n", - __func__, r_addr, m_hdr->read_data_size)); - - if (r_addr & 0xf) { - DEBUG2(ql4_printk(KERN_INFO, ha, - "[%s]: Read addr 0x%x not 16 bytes alligned\n", - __func__, r_addr)); - return QLA_ERROR; - } - - if (m_hdr->read_data_size % 16) { - DEBUG2(ql4_printk(KERN_INFO, ha, - "[%s]: Read data[0x%x] not multiple of 16 bytes\n", - __func__, m_hdr->read_data_size)); - return QLA_ERROR; - } - - DEBUG2(ql4_printk(KERN_INFO, ha, - "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n", - __func__, r_addr, m_hdr->read_data_size, loop_cnt)); - - write_lock_irqsave(&ha->hw_lock, flags); - for (i = 0; i < loop_cnt; i++) { - qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_LO, r_addr, 1); - r_value = 0; - qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_HI, r_value, 1); - r_value = MIU_TA_CTL_ENABLE; - qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1); - r_value = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; - qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1); - - for (j = 0; j < MAX_CTL_CHECK; j++) { - r_value = qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, - 0, 0); - if ((r_value & MIU_TA_CTL_BUSY) == 0) - break; - } - - if (j >= MAX_CTL_CHECK) { - printk_ratelimited(KERN_ERR - "%s: failed to read through agent\n", - __func__); - write_unlock_irqrestore(&ha->hw_lock, flags); - return QLA_SUCCESS; - } - - for (j = 0; j < 4; j++) { - r_data = qla4_8xxx_md_rw_32(ha, - MD_MIU_TEST_AGT_RDDATA[j], - 0, 0); - *data_ptr++ = cpu_to_le32(r_data); - } - - r_addr += 16; - } - write_unlock_irqrestore(&ha->hw_lock, flags); - - DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%x\n", - __func__, (loop_cnt * 16))); - - *d_ptr = data_ptr; - return QLA_SUCCESS; -} - -static void ql4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha, - struct qla82xx_minidump_entry_hdr *entry_hdr, - int index) -{ - entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG; - DEBUG2(ql4_printk(KERN_INFO, ha, - "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n", - ha->host_no, index, entry_hdr->entry_type, - entry_hdr->d_ctrl.entry_capture_mask)); -} - -/** - * qla82xx_collect_md_data - Retrieve firmware minidump data. - * @ha: pointer to adapter structure - **/ -static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) -{ - int num_entry_hdr = 0; - struct qla82xx_minidump_entry_hdr *entry_hdr; - struct qla4_8xxx_minidump_template_hdr *tmplt_hdr; - uint32_t *data_ptr; - uint32_t data_collected = 0; - int i, rval = QLA_ERROR; - uint64_t now; - uint32_t timestamp; - - if (!ha->fw_dump) { - ql4_printk(KERN_INFO, ha, "%s(%ld) No buffer to dump\n", - __func__, ha->host_no); - return rval; - } - - tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) - ha->fw_dump_tmplt_hdr; - data_ptr = (uint32_t *)((uint8_t *)ha->fw_dump + - ha->fw_dump_tmplt_size); - data_collected += ha->fw_dump_tmplt_size; - - num_entry_hdr = tmplt_hdr->num_of_entries; - ql4_printk(KERN_INFO, ha, "[%s]: starting data ptr: %p\n", - __func__, data_ptr); - ql4_printk(KERN_INFO, ha, - "[%s]: no of entry headers in Template: 0x%x\n", - __func__, num_entry_hdr); - ql4_printk(KERN_INFO, ha, "[%s]: Capture Mask obtained: 0x%x\n", - __func__, ha->fw_dump_capture_mask); - ql4_printk(KERN_INFO, ha, "[%s]: Total_data_size 0x%x, %d obtained\n", - __func__, ha->fw_dump_size, ha->fw_dump_size); - - /* Update current timestamp before taking dump */ - now = get_jiffies_64(); - timestamp = (u32)(jiffies_to_msecs(now) / 1000); - tmplt_hdr->driver_timestamp = timestamp; - - entry_hdr = (struct qla82xx_minidump_entry_hdr *) - (((uint8_t *)ha->fw_dump_tmplt_hdr) + - tmplt_hdr->first_entry_offset); - - /* Walk through the entry headers - validate/perform required action */ - for (i = 0; i < num_entry_hdr; i++) { - if (data_collected >= ha->fw_dump_size) { - ql4_printk(KERN_INFO, ha, - "Data collected: [0x%x], Total Dump size: [0x%x]\n", - data_collected, ha->fw_dump_size); - return rval; - } - - if (!(entry_hdr->d_ctrl.entry_capture_mask & - ha->fw_dump_capture_mask)) { - entry_hdr->d_ctrl.driver_flags |= - QLA82XX_DBG_SKIPPED_FLAG; - goto skip_nxt_entry; - } - - DEBUG2(ql4_printk(KERN_INFO, ha, - "Data collected: [0x%x], Dump size left:[0x%x]\n", - data_collected, - (ha->fw_dump_size - data_collected))); - - /* Decode the entry type and take required action to capture - * debug data - */ - switch (entry_hdr->entry_type) { - case QLA82XX_RDEND: - ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); - break; - case QLA82XX_CNTRL: - rval = qla4_8xxx_minidump_process_control(ha, - entry_hdr); - if (rval != QLA_SUCCESS) { - ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); - goto md_failed; - } - break; - case QLA82XX_RDCRB: - qla4_8xxx_minidump_process_rdcrb(ha, entry_hdr, - &data_ptr); - break; - case QLA82XX_RDMEM: - rval = qla4_8xxx_minidump_process_rdmem(ha, entry_hdr, - &data_ptr); - if (rval != QLA_SUCCESS) { - ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); - goto md_failed; - } - break; - case QLA82XX_BOARD: - case QLA82XX_RDROM: - qla4_8xxx_minidump_process_rdrom(ha, entry_hdr, - &data_ptr); - break; - case QLA82XX_L2DTG: - case QLA82XX_L2ITG: - case QLA82XX_L2DAT: - case QLA82XX_L2INS: - rval = qla4_8xxx_minidump_process_l2tag(ha, entry_hdr, - &data_ptr); - if (rval != QLA_SUCCESS) { - ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); - goto md_failed; - } - break; - case QLA82XX_L1DAT: - case QLA82XX_L1INS: - qla4_8xxx_minidump_process_l1cache(ha, entry_hdr, - &data_ptr); - break; - case QLA82XX_RDOCM: - qla4_8xxx_minidump_process_rdocm(ha, entry_hdr, - &data_ptr); - break; - case QLA82XX_RDMUX: - qla4_8xxx_minidump_process_rdmux(ha, entry_hdr, - &data_ptr); - break; - case QLA82XX_QUEUE: - qla4_8xxx_minidump_process_queue(ha, entry_hdr, - &data_ptr); - break; - case QLA82XX_RDNOP: - default: - ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); - break; - } - - data_collected = (uint8_t *)data_ptr - - ((uint8_t *)((uint8_t *)ha->fw_dump + - ha->fw_dump_tmplt_size)); -skip_nxt_entry: - /* next entry in the template */ - entry_hdr = (struct qla82xx_minidump_entry_hdr *) - (((uint8_t *)entry_hdr) + - entry_hdr->entry_size); - } - - if ((data_collected + ha->fw_dump_tmplt_size) != ha->fw_dump_size) { - ql4_printk(KERN_INFO, ha, - "Dump data mismatch: Data collected: [0x%x], total_data_size:[0x%x]\n", - data_collected, ha->fw_dump_size); - goto md_failed; - } - - DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s Last entry: 0x%x\n", - __func__, i)); -md_failed: - return rval; -} - -/** - * qla4_8xxx_uevent_emit - Send uevent when the firmware dump is ready. - * @ha: pointer to adapter structure - **/ -static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code) -{ - char event_string[40]; - char *envp[] = { event_string, NULL }; - - switch (code) { - case QL4_UEVENT_CODE_FW_DUMP: - snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld", - ha->host_no); - break; - default: - /*do nothing*/ - break; - } - - kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp); -} - /** * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw * @ha: pointer to adapter structure @@ -2324,15 +1659,6 @@ qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); qla4_8xxx_idc_unlock(ha); - if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) && - !test_and_set_bit(AF_82XX_FW_DUMPED, &ha->flags)) { - if (!qla4_8xxx_collect_md_data(ha)) { - qla4_8xxx_uevent_emit(ha, QL4_UEVENT_CODE_FW_DUMP); - } else { - ql4_printk(KERN_INFO, ha, "Unable to collect minidump\n"); - clear_bit(AF_82XX_FW_DUMPED, &ha->flags); - } - } rval = qla4_8xxx_try_start_fw(ha); qla4_8xxx_idc_lock(ha); @@ -2360,7 +1686,6 @@ static void qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) { uint32_t dev_state, drv_state, drv_active; - uint32_t active_mask = 0xFFFFFFFF; unsigned long reset_timeout; ql4_printk(KERN_INFO, ha, @@ -2372,14 +1697,7 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) qla4_8xxx_idc_lock(ha); } - if (!test_bit(AF_82XX_RST_OWNER, &ha->flags)) { - DEBUG2(ql4_printk(KERN_INFO, ha, - "%s(%ld): reset acknowledged\n", - __func__, ha->host_no)); - qla4_8xxx_set_rst_ready(ha); - } else { - active_mask = (~(1 << (ha->func_num * 4))); - } + qla4_8xxx_set_rst_ready(ha); /* wait for 10 seconds for reset ack from all functions */ reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); @@ -2391,24 +1709,12 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", __func__, ha->host_no, drv_state, drv_active); - while (drv_state != (drv_active & active_mask)) { + while (drv_state != drv_active) { if (time_after_eq(jiffies, reset_timeout)) { - ql4_printk(KERN_INFO, ha, - "%s: RESET TIMEOUT! drv_state: 0x%08x, drv_active: 0x%08x\n", - DRIVER_NAME, drv_state, drv_active); + printk("%s: RESET TIMEOUT!\n", DRIVER_NAME); break; } - /* - * When reset_owner times out, check which functions - * acked/did not ack - */ - if (test_bit(AF_82XX_RST_OWNER, &ha->flags)) { - ql4_printk(KERN_INFO, ha, - "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", - __func__, ha->host_no, drv_state, - drv_active); - } qla4_8xxx_idc_unlock(ha); msleep(1000); qla4_8xxx_idc_lock(ha); @@ -2417,18 +1723,14 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); } - /* Clear RESET OWNER as we are not going to use it any further */ - clear_bit(AF_82XX_RST_OWNER, &ha->flags); - dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); - ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", dev_state, - dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); + ql4_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state, + dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); /* Force to DEV_COLD unless someone else is starting a reset */ if (dev_state != QLA82XX_DEV_INITIALIZING) { ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); - qla4_8xxx_set_rst_ready(ha); } } @@ -2463,9 +1765,8 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) } dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); - DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", - dev_state, dev_state < MAX_STATES ? - qdev_state[dev_state] : "Unknown")); + ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, + dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); /* wait for 30 seconds for device to go ready */ dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); @@ -2474,19 +1775,15 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) while (1) { if (time_after_eq(jiffies, dev_init_timeout)) { - ql4_printk(KERN_WARNING, ha, - "%s: Device Init Failed 0x%x = %s\n", - DRIVER_NAME, - dev_state, dev_state < MAX_STATES ? - qdev_state[dev_state] : "Unknown"); + ql4_printk(KERN_WARNING, ha, "Device init failed!\n"); qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_FAILED); } dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); - ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", - dev_state, dev_state < MAX_STATES ? - qdev_state[dev_state] : "Unknown"); + ql4_printk(KERN_INFO, ha, + "2:Device state is 0x%x = %s\n", dev_state, + dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); /* NOTE: Make sure idc unlocked upon exit of switch statement */ switch (dev_state) { @@ -2887,7 +2184,6 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_NEED_RESET); - set_bit(AF_82XX_RST_OWNER, &ha->flags); } else ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); @@ -2899,10 +2195,8 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) qla4_8xxx_clear_rst_ready(ha); qla4_8xxx_idc_unlock(ha); - if (rval == QLA_SUCCESS) { - ql4_printk(KERN_INFO, ha, "Clearing AF_RECOVERY in qla4_8xxx_isp_reset\n"); + if (rval == QLA_SUCCESS) clear_bit(AF_FW_RECOVERY, &ha->flags); - } return rval; } diff --git a/trunk/drivers/scsi/qla4xxx/ql4_nx.h b/trunk/drivers/scsi/qla4xxx/ql4_nx.h index 30258479f100..dc7500e47b8b 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_nx.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_nx.h @@ -792,196 +792,4 @@ struct crb_addr_pair { #define MIU_TEST_AGT_WRDATA_UPPER_LO (0x0b0) #define MIU_TEST_AGT_WRDATA_UPPER_HI (0x0b4) -/* Minidump related */ - -/* Entry Type Defines */ -#define QLA82XX_RDNOP 0 -#define QLA82XX_RDCRB 1 -#define QLA82XX_RDMUX 2 -#define QLA82XX_QUEUE 3 -#define QLA82XX_BOARD 4 -#define QLA82XX_RDOCM 6 -#define QLA82XX_PREGS 7 -#define QLA82XX_L1DTG 8 -#define QLA82XX_L1ITG 9 -#define QLA82XX_L1DAT 11 -#define QLA82XX_L1INS 12 -#define QLA82XX_L2DTG 21 -#define QLA82XX_L2ITG 22 -#define QLA82XX_L2DAT 23 -#define QLA82XX_L2INS 24 -#define QLA82XX_RDROM 71 -#define QLA82XX_RDMEM 72 -#define QLA82XX_CNTRL 98 -#define QLA82XX_RDEND 255 - -/* Opcodes for Control Entries. - * These Flags are bit fields. - */ -#define QLA82XX_DBG_OPCODE_WR 0x01 -#define QLA82XX_DBG_OPCODE_RW 0x02 -#define QLA82XX_DBG_OPCODE_AND 0x04 -#define QLA82XX_DBG_OPCODE_OR 0x08 -#define QLA82XX_DBG_OPCODE_POLL 0x10 -#define QLA82XX_DBG_OPCODE_RDSTATE 0x20 -#define QLA82XX_DBG_OPCODE_WRSTATE 0x40 -#define QLA82XX_DBG_OPCODE_MDSTATE 0x80 - -/* Driver Flags */ -#define QLA82XX_DBG_SKIPPED_FLAG 0x80 /* driver skipped this entry */ -#define QLA82XX_DBG_SIZE_ERR_FLAG 0x40 /* Entry vs Capture size - * mismatch */ - -/* Driver_code is for driver to write some info about the entry - * currently not used. - */ -struct qla82xx_minidump_entry_hdr { - uint32_t entry_type; - uint32_t entry_size; - uint32_t entry_capture_size; - struct { - uint8_t entry_capture_mask; - uint8_t entry_code; - uint8_t driver_code; - uint8_t driver_flags; - } d_ctrl; -}; - -/* Read CRB entry header */ -struct qla82xx_minidump_entry_crb { - struct qla82xx_minidump_entry_hdr h; - uint32_t addr; - struct { - uint8_t addr_stride; - uint8_t state_index_a; - uint16_t poll_timeout; - } crb_strd; - uint32_t data_size; - uint32_t op_count; - - struct { - uint8_t opcode; - uint8_t state_index_v; - uint8_t shl; - uint8_t shr; - } crb_ctrl; - - uint32_t value_1; - uint32_t value_2; - uint32_t value_3; -}; - -struct qla82xx_minidump_entry_cache { - struct qla82xx_minidump_entry_hdr h; - uint32_t tag_reg_addr; - struct { - uint16_t tag_value_stride; - uint16_t init_tag_value; - } addr_ctrl; - uint32_t data_size; - uint32_t op_count; - uint32_t control_addr; - struct { - uint16_t write_value; - uint8_t poll_mask; - uint8_t poll_wait; - } cache_ctrl; - uint32_t read_addr; - struct { - uint8_t read_addr_stride; - uint8_t read_addr_cnt; - uint16_t rsvd_1; - } read_ctrl; -}; - -/* Read OCM */ -struct qla82xx_minidump_entry_rdocm { - struct qla82xx_minidump_entry_hdr h; - uint32_t rsvd_0; - uint32_t rsvd_1; - uint32_t data_size; - uint32_t op_count; - uint32_t rsvd_2; - uint32_t rsvd_3; - uint32_t read_addr; - uint32_t read_addr_stride; -}; - -/* Read Memory */ -struct qla82xx_minidump_entry_rdmem { - struct qla82xx_minidump_entry_hdr h; - uint32_t rsvd[6]; - uint32_t read_addr; - uint32_t read_data_size; -}; - -/* Read ROM */ -struct qla82xx_minidump_entry_rdrom { - struct qla82xx_minidump_entry_hdr h; - uint32_t rsvd[6]; - uint32_t read_addr; - uint32_t read_data_size; -}; - -/* Mux entry */ -struct qla82xx_minidump_entry_mux { - struct qla82xx_minidump_entry_hdr h; - uint32_t select_addr; - uint32_t rsvd_0; - uint32_t data_size; - uint32_t op_count; - uint32_t select_value; - uint32_t select_value_stride; - uint32_t read_addr; - uint32_t rsvd_1; -}; - -/* Queue entry */ -struct qla82xx_minidump_entry_queue { - struct qla82xx_minidump_entry_hdr h; - uint32_t select_addr; - struct { - uint16_t queue_id_stride; - uint16_t rsvd_0; - } q_strd; - uint32_t data_size; - uint32_t op_count; - uint32_t rsvd_1; - uint32_t rsvd_2; - uint32_t read_addr; - struct { - uint8_t read_addr_stride; - uint8_t read_addr_cnt; - uint16_t rsvd_3; - } rd_strd; -}; - -#define QLA82XX_MINIDUMP_OCM0_SIZE (256 * 1024) -#define QLA82XX_MINIDUMP_L1C_SIZE (256 * 1024) -#define QLA82XX_MINIDUMP_L2C_SIZE 1572864 -#define QLA82XX_MINIDUMP_COMMON_STR_SIZE 0 -#define QLA82XX_MINIDUMP_FCOE_STR_SIZE 0 -#define QLA82XX_MINIDUMP_MEM_SIZE 0 -#define QLA82XX_MAX_ENTRY_HDR 4 - -struct qla82xx_minidump { - uint32_t md_ocm0_data[QLA82XX_MINIDUMP_OCM0_SIZE]; - uint32_t md_l1c_data[QLA82XX_MINIDUMP_L1C_SIZE]; - uint32_t md_l2c_data[QLA82XX_MINIDUMP_L2C_SIZE]; - uint32_t md_cs_data[QLA82XX_MINIDUMP_COMMON_STR_SIZE]; - uint32_t md_fcoes_data[QLA82XX_MINIDUMP_FCOE_STR_SIZE]; - uint32_t md_mem_data[QLA82XX_MINIDUMP_MEM_SIZE]; -}; - -#define MBC_DIAGNOSTIC_MINIDUMP_TEMPLATE 0x129 -#define RQST_TMPLT_SIZE 0x0 -#define RQST_TMPLT 0x1 -#define MD_DIRECT_ROM_WINDOW 0x42110030 -#define MD_DIRECT_ROM_READ_BASE 0x42150000 -#define MD_MIU_TEST_AGT_CTRL 0x41000090 -#define MD_MIU_TEST_AGT_ADDR_LO 0x41000094 -#define MD_MIU_TEST_AGT_ADDR_HI 0x41000098 - -static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, - 0x410000AC, 0x410000B8, 0x410000BC }; #endif diff --git a/trunk/drivers/scsi/qla4xxx/ql4_os.c b/trunk/drivers/scsi/qla4xxx/ql4_os.c index cd15678f9ada..ee47820c30a6 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_os.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_os.c @@ -68,34 +68,12 @@ MODULE_PARM_DESC(ql4xmaxqdepth, " Maximum queue depth to report for target devices.\n" "\t\t Default: 32."); -static int ql4xqfulltracking = 1; -module_param(ql4xqfulltracking, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ql4xqfulltracking, - " Enable or disable dynamic tracking and adjustment of\n" - "\t\t scsi device queue depth.\n" - "\t\t 0 - Disable.\n" - "\t\t 1 - Enable. (Default)"); - static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; module_param(ql4xsess_recovery_tmo, int, S_IRUGO); MODULE_PARM_DESC(ql4xsess_recovery_tmo, " Target Session Recovery Timeout.\n" "\t\t Default: 120 sec."); -int ql4xmdcapmask = 0x1F; -module_param(ql4xmdcapmask, int, S_IRUGO); -MODULE_PARM_DESC(ql4xmdcapmask, - " Set the Minidump driver capture mask level.\n" - "\t\t Default is 0x1F.\n" - "\t\t Can be set to 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F"); - -int ql4xenablemd = 1; -module_param(ql4xenablemd, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ql4xenablemd, - " Set to enable minidump.\n" - "\t\t 0 - disable minidump\n" - "\t\t 1 - enable minidump (Default)"); - static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); /* * SCSI host template entry points @@ -162,8 +140,6 @@ static int qla4xxx_slave_configure(struct scsi_device *device); static void qla4xxx_slave_destroy(struct scsi_device *sdev); static umode_t ql4_attr_is_visible(int param_type, int param); static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type); -static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth, - int reason); static struct qla4_8xxx_legacy_intr_set legacy_intr[] = QLA82XX_LEGACY_INTR_CONFIG; @@ -183,7 +159,6 @@ static struct scsi_host_template qla4xxx_driver_template = { .slave_configure = qla4xxx_slave_configure, .slave_alloc = qla4xxx_slave_alloc, .slave_destroy = qla4xxx_slave_destroy, - .change_queue_depth = qla4xxx_change_queue_depth, .this_id = -1, .cmd_per_lun = 3, @@ -1580,53 +1555,19 @@ static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess) struct iscsi_session *sess; struct ddb_entry *ddb_entry; struct scsi_qla_host *ha; - unsigned long flags, wtime; - struct dev_db_entry *fw_ddb_entry = NULL; - dma_addr_t fw_ddb_entry_dma; - uint32_t ddb_state; - int ret; + unsigned long flags; DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); sess = cls_sess->dd_data; ddb_entry = sess->dd_data; ha = ddb_entry->ha; - fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), - &fw_ddb_entry_dma, GFP_KERNEL); - if (!fw_ddb_entry) { - ql4_printk(KERN_ERR, ha, - "%s: Unable to allocate dma buffer\n", __func__); - goto destroy_session; - } - - wtime = jiffies + (HZ * LOGOUT_TOV); - do { - ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, - fw_ddb_entry, fw_ddb_entry_dma, - NULL, NULL, &ddb_state, NULL, - NULL, NULL); - if (ret == QLA_ERROR) - goto destroy_session; - - if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) || - (ddb_state == DDB_DS_SESSION_FAILED)) - goto destroy_session; - - schedule_timeout_uninterruptible(HZ); - } while ((time_after(wtime, jiffies))); - -destroy_session: qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); spin_lock_irqsave(&ha->hardware_lock, flags); qla4xxx_free_ddb(ha, ddb_entry); spin_unlock_irqrestore(&ha->hardware_lock, flags); - iscsi_session_teardown(cls_sess); - - if (fw_ddb_entry) - dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), - fw_ddb_entry, fw_ddb_entry_dma); } static struct iscsi_cls_conn * @@ -2279,9 +2220,6 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues, ha->queues_dma); - if (ha->fw_dump) - vfree(ha->fw_dump); - ha->queues_len = 0; ha->queues = NULL; ha->queues_dma = 0; @@ -2291,8 +2229,6 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) ha->response_dma = 0; ha->shadow_regs = NULL; ha->shadow_regs_dma = 0; - ha->fw_dump = NULL; - ha->fw_dump_size = 0; /* Free srb pool. */ if (ha->srb_mempool) @@ -5087,8 +5023,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, set_bit(AF_INIT_DONE, &ha->flags); - qla4_8xxx_alloc_sysfs_attr(ha); - printk(KERN_INFO " QLogic iSCSI HBA Driver version: %s\n" " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n", @@ -5215,7 +5149,6 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) iscsi_boot_destroy_kset(ha->boot_kset); qla4xxx_destroy_fw_ddb_session(ha); - qla4_8xxx_free_sysfs_attr(ha); scsi_remove_host(ha->host); @@ -5284,15 +5217,6 @@ static void qla4xxx_slave_destroy(struct scsi_device *sdev) scsi_deactivate_tcq(sdev, 1); } -static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth, - int reason) -{ - if (!ql4xqfulltracking) - return -EOPNOTSUPP; - - return iscsi_change_queue_depth(sdev, qdepth, reason); -} - /** * qla4xxx_del_from_active_array - returns an active srb * @ha: Pointer to host adapter structure. diff --git a/trunk/drivers/scsi/qla4xxx/ql4_version.h b/trunk/drivers/scsi/qla4xxx/ql4_version.h index cc1cc3518b87..97b30c108e36 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_version.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k17" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k16" diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 6dfb9785d345..62ddfd31d4ce 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -1378,19 +1378,16 @@ static int scsi_lld_busy(struct request_queue *q) { struct scsi_device *sdev = q->queuedata; struct Scsi_Host *shost; + struct scsi_target *starget; if (!sdev) return 0; shost = sdev->host; + starget = scsi_target(sdev); - /* - * Ignore host/starget busy state. - * Since block layer does not have a concept of fairness across - * multiple queues, congestion of host/starget needs to be handled - * in SCSI layer. - */ - if (scsi_host_in_recovery(shost) || scsi_device_is_busy(sdev)) + if (scsi_host_in_recovery(shost) || scsi_host_is_busy(shost) || + scsi_target_is_busy(starget) || scsi_device_is_busy(sdev)) return 1; return 0; diff --git a/trunk/drivers/scsi/scsi_pm.c b/trunk/drivers/scsi/scsi_pm.c index d4201ded3b22..f661a41fa4c6 100644 --- a/trunk/drivers/scsi/scsi_pm.c +++ b/trunk/drivers/scsi/scsi_pm.c @@ -24,11 +24,8 @@ static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg) err = scsi_device_quiesce(to_scsi_device(dev)); if (err == 0) { drv = dev->driver; - if (drv && drv->suspend) { + if (drv && drv->suspend) err = drv->suspend(dev, msg); - if (err) - scsi_device_resume(to_scsi_device(dev)); - } } dev_dbg(dev, "scsi suspend: %d\n", err); return err; diff --git a/trunk/drivers/scsi/scsi_scan.c b/trunk/drivers/scsi/scsi_scan.c index 2e5fe584aad3..01b03744f1f9 100644 --- a/trunk/drivers/scsi/scsi_scan.c +++ b/trunk/drivers/scsi/scsi_scan.c @@ -147,7 +147,7 @@ int scsi_complete_async_scans(void) do { if (list_empty(&scanning_hosts)) - goto out; + return 0; /* If we can't get memory immediately, that's OK. Just * sleep a little. Even if we never get memory, the async * scans will finish eventually. @@ -179,11 +179,8 @@ int scsi_complete_async_scans(void) } done: spin_unlock(&async_scan_lock); - kfree(data); - - out: - async_synchronize_full_domain(&scsi_sd_probe_domain); + kfree(data); return 0; } diff --git a/trunk/drivers/scsi/scsi_wait_scan.c b/trunk/drivers/scsi/scsi_wait_scan.c index ae7814874618..74708fcaf82f 100644 --- a/trunk/drivers/scsi/scsi_wait_scan.c +++ b/trunk/drivers/scsi/scsi_wait_scan.c @@ -12,7 +12,7 @@ #include #include -#include "scsi_priv.h" +#include static int __init wait_scan_init(void) { diff --git a/trunk/drivers/scsi/ufs/ufshcd.c b/trunk/drivers/scsi/ufs/ufshcd.c index 6a4fd00117ca..4e010b727818 100644 --- a/trunk/drivers/scsi/ufs/ufshcd.c +++ b/trunk/drivers/scsi/ufs/ufshcd.c @@ -1836,7 +1836,7 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id) err = pci_request_regions(pdev, UFSHCD); if (err < 0) { dev_err(&pdev->dev, "request regions failed\n"); - goto out_host_put; + goto out_disable; } hba->mmio_base = pci_ioremap_bar(pdev, 0); @@ -1925,9 +1925,8 @@ ufshcd_probe(struct pci_dev *pdev, const struct pci_device_id *id) iounmap(hba->mmio_base); out_release_regions: pci_release_regions(pdev); -out_host_put: - scsi_host_put(host); out_disable: + scsi_host_put(host); pci_clear_master(pdev); pci_disable_device(pdev); out_error: diff --git a/trunk/drivers/staging/ramster/zcache-main.c b/trunk/drivers/staging/ramster/zcache-main.c index d46764b5aaba..4e7ef0e6b79c 100644 --- a/trunk/drivers/staging/ramster/zcache-main.c +++ b/trunk/drivers/staging/ramster/zcache-main.c @@ -3002,7 +3002,7 @@ static inline struct tmem_oid oswiz(unsigned type, u32 ind) return oid; } -static int zcache_frontswap_store(unsigned type, pgoff_t offset, +static int zcache_frontswap_put_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -3025,7 +3025,7 @@ static int zcache_frontswap_store(unsigned type, pgoff_t offset, /* returns 0 if the page was successfully gotten from frontswap, -1 if * was not present (should never happen!) */ -static int zcache_frontswap_load(unsigned type, pgoff_t offset, +static int zcache_frontswap_get_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -3080,8 +3080,8 @@ static void zcache_frontswap_init(unsigned ignored) } static struct frontswap_ops zcache_frontswap_ops = { - .store = zcache_frontswap_store, - .load = zcache_frontswap_load, + .put_page = zcache_frontswap_put_page, + .get_page = zcache_frontswap_get_page, .invalidate_page = zcache_frontswap_flush_page, .invalidate_area = zcache_frontswap_flush_area, .init = zcache_frontswap_init diff --git a/trunk/drivers/staging/zcache/zcache-main.c b/trunk/drivers/staging/zcache/zcache-main.c index 784c796b9848..2734dacacbaf 100644 --- a/trunk/drivers/staging/zcache/zcache-main.c +++ b/trunk/drivers/staging/zcache/zcache-main.c @@ -1835,7 +1835,7 @@ static int zcache_frontswap_poolid = -1; * Swizzling increases objects per swaptype, increasing tmem concurrency * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS * Setting SWIZ_BITS to 27 basically reconstructs the swap entry from - * frontswap_load(), but has side-effects. Hence using 8. + * frontswap_get_page(), but has side-effects. Hence using 8. */ #define SWIZ_BITS 8 #define SWIZ_MASK ((1 << SWIZ_BITS) - 1) @@ -1849,7 +1849,7 @@ static inline struct tmem_oid oswiz(unsigned type, u32 ind) return oid; } -static int zcache_frontswap_store(unsigned type, pgoff_t offset, +static int zcache_frontswap_put_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -1870,7 +1870,7 @@ static int zcache_frontswap_store(unsigned type, pgoff_t offset, /* returns 0 if the page was successfully gotten from frontswap, -1 if * was not present (should never happen!) */ -static int zcache_frontswap_load(unsigned type, pgoff_t offset, +static int zcache_frontswap_get_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -1919,8 +1919,8 @@ static void zcache_frontswap_init(unsigned ignored) } static struct frontswap_ops zcache_frontswap_ops = { - .store = zcache_frontswap_store, - .load = zcache_frontswap_load, + .put_page = zcache_frontswap_put_page, + .get_page = zcache_frontswap_get_page, .invalidate_page = zcache_frontswap_flush_page, .invalidate_area = zcache_frontswap_flush_area, .init = zcache_frontswap_init diff --git a/trunk/drivers/target/sbp/sbp_target.c b/trunk/drivers/target/sbp/sbp_target.c index 7e6136e2ce81..37c609898f84 100644 --- a/trunk/drivers/target/sbp/sbp_target.c +++ b/trunk/drivers/target/sbp/sbp_target.c @@ -587,14 +587,14 @@ static void sbp_management_request_logout( { struct sbp_tport *tport = agent->tport; struct sbp_tpg *tpg = tport->tpg; - int id; + int login_id; struct sbp_login_descriptor *login; - id = LOGOUT_ORB_LOGIN_ID(be32_to_cpu(req->orb.misc)); + login_id = LOGOUT_ORB_LOGIN_ID(be32_to_cpu(req->orb.misc)); - login = sbp_login_find_by_id(tpg, id); + login = sbp_login_find_by_id(tpg, login_id); if (!login) { - pr_warn("cannot find login: %d\n", id); + pr_warn("cannot find login: %d\n", login_id); req->status.status = cpu_to_be32( STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) | diff --git a/trunk/drivers/target/target_core_alua.c b/trunk/drivers/target/target_core_alua.c index 91799973081a..e624b836469c 100644 --- a/trunk/drivers/target/target_core_alua.c +++ b/trunk/drivers/target/target_core_alua.c @@ -374,9 +374,8 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd) out: transport_kunmap_data_sg(cmd); - if (!rc) - target_complete_cmd(cmd, GOOD); - return rc; + target_complete_cmd(cmd, GOOD); + return 0; } static inline int core_alua_state_nonoptimized( diff --git a/trunk/drivers/target/target_core_file.c b/trunk/drivers/target/target_core_file.c index 9f99d0404908..686dba189f8e 100644 --- a/trunk/drivers/target/target_core_file.c +++ b/trunk/drivers/target/target_core_file.c @@ -133,11 +133,16 @@ static struct se_device *fd_create_virtdevice( ret = PTR_ERR(dev_p); goto fail; } + + /* O_DIRECT too? */ + flags = O_RDWR | O_CREAT | O_LARGEFILE; + /* - * Use O_DSYNC by default instead of O_SYNC to forgo syncing - * of pure timestamp updates. + * If fd_buffered_io=1 has not been set explicitly (the default), + * use O_SYNC to force FILEIO writes to disk. */ - flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; + if (!(fd_dev->fbd_flags & FDBD_USE_BUFFERED_IO)) + flags |= O_SYNC; file = filp_open(dev_p, flags, 0600); if (IS_ERR(file)) { @@ -375,6 +380,23 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd) } } +static void fd_emulate_write_fua(struct se_cmd *cmd) +{ + struct se_device *dev = cmd->se_dev; + struct fd_dev *fd_dev = dev->dev_ptr; + loff_t start = cmd->t_task_lba * + dev->se_sub_dev->se_dev_attrib.block_size; + loff_t end = start + cmd->data_length; + int ret; + + pr_debug("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n", + cmd->t_task_lba, cmd->data_length); + + ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1); + if (ret != 0) + pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret); +} + static int fd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, enum dma_data_direction data_direction) { @@ -389,21 +411,19 @@ static int fd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl, ret = fd_do_readv(cmd, sgl, sgl_nents); } else { ret = fd_do_writev(cmd, sgl, sgl_nents); - /* - * Perform implict vfs_fsync_range() for fd_do_writev() ops - * for SCSI WRITEs with Forced Unit Access (FUA) set. - * Allow this to happen independent of WCE=0 setting. - */ + if (ret > 0 && + dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0 && dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 && (cmd->se_cmd_flags & SCF_FUA)) { - struct fd_dev *fd_dev = dev->dev_ptr; - loff_t start = cmd->t_task_lba * - dev->se_sub_dev->se_dev_attrib.block_size; - loff_t end = start + cmd->data_length; - - vfs_fsync_range(fd_dev->fd_file, start, end, 1); + /* + * We might need to be a bit smarter here + * and return some sense data to let the initiator + * know the FUA WRITE cache sync failed..? + */ + fd_emulate_write_fua(cmd); } + } if (ret < 0) { @@ -422,6 +442,7 @@ enum { static match_table_t tokens = { {Opt_fd_dev_name, "fd_dev_name=%s"}, {Opt_fd_dev_size, "fd_dev_size=%s"}, + {Opt_fd_buffered_io, "fd_buffered_io=%d"}, {Opt_err, NULL} }; @@ -433,7 +454,7 @@ static ssize_t fd_set_configfs_dev_params( struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; char *orig, *ptr, *arg_p, *opts; substring_t args[MAX_OPT_ARGS]; - int ret = 0, token; + int ret = 0, arg, token; opts = kstrdup(page, GFP_KERNEL); if (!opts) @@ -477,6 +498,19 @@ static ssize_t fd_set_configfs_dev_params( " bytes\n", fd_dev->fd_dev_size); fd_dev->fbd_flags |= FBDF_HAS_SIZE; break; + case Opt_fd_buffered_io: + match_int(args, &arg); + if (arg != 1) { + pr_err("bogus fd_buffered_io=%d value\n", arg); + ret = -EINVAL; + goto out; + } + + pr_debug("FILEIO: Using buffered I/O" + " operations for struct fd_dev\n"); + + fd_dev->fbd_flags |= FDBD_USE_BUFFERED_IO; + break; default: break; } @@ -508,8 +542,10 @@ static ssize_t fd_show_configfs_dev_params( ssize_t bl = 0; bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id); - bl += sprintf(b + bl, " File: %s Size: %llu Mode: O_DSYNC\n", - fd_dev->fd_dev_name, fd_dev->fd_dev_size); + bl += sprintf(b + bl, " File: %s Size: %llu Mode: %s\n", + fd_dev->fd_dev_name, fd_dev->fd_dev_size, + (fd_dev->fbd_flags & FDBD_USE_BUFFERED_IO) ? + "Buffered" : "Synchronous"); return bl; } diff --git a/trunk/drivers/target/target_core_file.h b/trunk/drivers/target/target_core_file.h index 70ce7fd7111d..fbd59ef7d8be 100644 --- a/trunk/drivers/target/target_core_file.h +++ b/trunk/drivers/target/target_core_file.h @@ -14,6 +14,7 @@ #define FBDF_HAS_PATH 0x01 #define FBDF_HAS_SIZE 0x02 +#define FDBD_USE_BUFFERED_IO 0x04 struct fd_dev { u32 fbd_flags; diff --git a/trunk/drivers/target/target_core_transport.c b/trunk/drivers/target/target_core_transport.c index 634d0f31a28c..b05fdc0c05d3 100644 --- a/trunk/drivers/target/target_core_transport.c +++ b/trunk/drivers/target/target_core_transport.c @@ -315,7 +315,7 @@ void transport_register_session( } EXPORT_SYMBOL(transport_register_session); -void target_release_session(struct kref *kref) +static void target_release_session(struct kref *kref) { struct se_session *se_sess = container_of(kref, struct se_session, sess_kref); @@ -332,12 +332,6 @@ EXPORT_SYMBOL(target_get_session); void target_put_session(struct se_session *se_sess) { - struct se_portal_group *tpg = se_sess->se_tpg; - - if (tpg->se_tpg_tfo->put_session != NULL) { - tpg->se_tpg_tfo->put_session(se_sess); - return; - } kref_put(&se_sess->sess_kref, target_release_session); } EXPORT_SYMBOL(target_put_session); diff --git a/trunk/drivers/tty/amiserial.c b/trunk/drivers/tty/amiserial.c index 6cc4358f68c1..35819e312624 100644 --- a/trunk/drivers/tty/amiserial.c +++ b/trunk/drivers/tty/amiserial.c @@ -1033,7 +1033,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, if (!retinfo) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); - tty_lock(); + tty_lock(tty); tmp.line = tty->index; tmp.port = state->port; tmp.flags = state->tport.flags; @@ -1042,7 +1042,7 @@ static int get_serial_info(struct tty_struct *tty, struct serial_state *state, tmp.close_delay = state->tport.close_delay; tmp.closing_wait = state->tport.closing_wait; tmp.custom_divisor = state->custom_divisor; - tty_unlock(); + tty_unlock(tty); if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) return -EFAULT; return 0; @@ -1059,12 +1059,12 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; - tty_lock(); + tty_lock(tty); change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) || new_serial.custom_divisor != state->custom_divisor; if (new_serial.irq || new_serial.port != state->port || new_serial.xmit_fifo_size != state->xmit_fifo_size) { - tty_unlock(); + tty_unlock(tty); return -EINVAL; } @@ -1074,7 +1074,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, (new_serial.xmit_fifo_size != state->xmit_fifo_size) || ((new_serial.flags & ~ASYNC_USR_MASK) != (port->flags & ~ASYNC_USR_MASK))) { - tty_unlock(); + tty_unlock(tty); return -EPERM; } port->flags = ((port->flags & ~ASYNC_USR_MASK) | @@ -1084,7 +1084,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, } if (new_serial.baud_base < 9600) { - tty_unlock(); + tty_unlock(tty); return -EINVAL; } @@ -1116,7 +1116,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state, } } else retval = startup(tty, state); - tty_unlock(); + tty_unlock(tty); return retval; } diff --git a/trunk/drivers/tty/cyclades.c b/trunk/drivers/tty/cyclades.c index e61cabdd69df..6984e1a2686a 100644 --- a/trunk/drivers/tty/cyclades.c +++ b/trunk/drivers/tty/cyclades.c @@ -1599,7 +1599,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(info->port.close_wait, + wait_event_interruptible_tty(tty, info->port.close_wait, !(info->port.flags & ASYNC_CLOSING)); return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; } diff --git a/trunk/drivers/tty/hvc/hvc_xen.c b/trunk/drivers/tty/hvc/hvc_xen.c index 944eaeb8e0cf..d3d91dae065c 100644 --- a/trunk/drivers/tty/hvc/hvc_xen.c +++ b/trunk/drivers/tty/hvc/hvc_xen.c @@ -214,24 +214,24 @@ static int xen_hvm_console_init(void) /* already configured */ if (info->intf != NULL) return 0; - /* - * If the toolstack (or the hypervisor) hasn't set these values, the - * default value is 0. Even though mfn = 0 and evtchn = 0 are - * theoretically correct values, in practice they never are and they - * mean that a legacy toolstack hasn't initialized the pv console correctly. - */ + r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); - if (r < 0 || v == 0) - goto err; + if (r < 0) { + kfree(info); + return -ENODEV; + } info->evtchn = v; - v = 0; - r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); - if (r < 0 || v == 0) - goto err; + hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); + if (r < 0) { + kfree(info); + return -ENODEV; + } mfn = v; info->intf = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE); - if (info->intf == NULL) - goto err; + if (info->intf == NULL) { + kfree(info); + return -ENODEV; + } info->vtermno = HVC_COOKIE; spin_lock(&xencons_lock); @@ -239,9 +239,6 @@ static int xen_hvm_console_init(void) spin_unlock(&xencons_lock); return 0; -err: - kfree(info); - return -ENODEV; } static int xen_pv_console_init(void) diff --git a/trunk/drivers/tty/n_r3964.c b/trunk/drivers/tty/n_r3964.c index 5c6c31459a2f..656ad93bbc96 100644 --- a/trunk/drivers/tty/n_r3964.c +++ b/trunk/drivers/tty/n_r3964.c @@ -1065,7 +1065,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, TRACE_L("read()"); - tty_lock(); + /* FIXME: should use a private lock */ + tty_lock(tty); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1077,7 +1078,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, goto unlock; } /* block until there is a message: */ - wait_event_interruptible_tty(pInfo->read_wait, + wait_event_interruptible_tty(tty, pInfo->read_wait, (pMsg = remove_msg(pInfo, pClient))); } @@ -1107,7 +1108,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, } ret = -EPERM; unlock: - tty_unlock(); + tty_unlock(tty); return ret; } @@ -1156,7 +1157,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, pHeader->locks = 0; pHeader->owner = NULL; - tty_lock(); + tty_lock(tty); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1175,7 +1176,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, add_tx_queue(pInfo, pHeader); trigger_transmit(pInfo); - tty_unlock(); + tty_unlock(tty); return 0; } diff --git a/trunk/drivers/tty/pty.c b/trunk/drivers/tty/pty.c index 5505ffc91da4..65c7c62c7aae 100644 --- a/trunk/drivers/tty/pty.c +++ b/trunk/drivers/tty/pty.c @@ -47,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->write_wait); tty->packet = 0; + /* Review - krefs on tty_link ?? */ if (!tty->link) return; tty->link->packet = 0; @@ -62,9 +63,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&devpts_mutex); } #endif - tty_unlock(); + tty_unlock(tty); tty_vhangup(tty->link); - tty_lock(); + tty_lock(tty); } } @@ -622,26 +623,27 @@ static int ptmx_open(struct inode *inode, struct file *filp) return retval; /* find a device that is not in use. */ - tty_lock(); + mutex_lock(&devpts_mutex); index = devpts_new_index(inode); - tty_unlock(); if (index < 0) { retval = index; goto err_file; } + mutex_unlock(&devpts_mutex); + mutex_lock(&tty_mutex); - mutex_lock(&devpts_mutex); tty = tty_init_dev(ptm_driver, index); - mutex_unlock(&devpts_mutex); - tty_lock(); - mutex_unlock(&tty_mutex); if (IS_ERR(tty)) { retval = PTR_ERR(tty); goto out; } + /* The tty returned here is locked so we can safely + drop the mutex */ + mutex_unlock(&tty_mutex); + set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty_add_file(tty, filp); @@ -654,16 +656,17 @@ static int ptmx_open(struct inode *inode, struct file *filp) if (retval) goto err_release; - tty_unlock(); + tty_unlock(tty); return 0; err_release: - tty_unlock(); + tty_unlock(tty); tty_release(inode, filp); return retval; out: + mutex_unlock(&tty_mutex); devpts_kill_index(inode, index); - tty_unlock(); err_file: + mutex_unlock(&devpts_mutex); tty_free_file(filp); return retval; } diff --git a/trunk/drivers/tty/serial/crisv10.c b/trunk/drivers/tty/serial/crisv10.c index 80b6b1b1f725..7264d4d26717 100644 --- a/trunk/drivers/tty/serial/crisv10.c +++ b/trunk/drivers/tty/serial/crisv10.c @@ -3976,7 +3976,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(info->close_wait, + wait_event_interruptible_tty(tty, info->close_wait, !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART if (info->flags & ASYNC_HUP_NOTIFY) @@ -4052,9 +4052,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready blocking: ttyS%d, count = %d\n", info->line, info->count); #endif - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); @@ -4115,7 +4115,7 @@ rs_open(struct tty_struct *tty, struct file * filp) */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(info->close_wait, + wait_event_interruptible_tty(tty, info->close_wait, !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? diff --git a/trunk/drivers/tty/serial/sh-sci.c b/trunk/drivers/tty/serial/sh-sci.c index 1bd9163bc118..4604153b7954 100644 --- a/trunk/drivers/tty/serial/sh-sci.c +++ b/trunk/drivers/tty/serial/sh-sci.c @@ -2179,16 +2179,6 @@ static int __devinit sci_init_single(struct platform_device *dev, return 0; } -static void sci_cleanup_single(struct sci_port *port) -{ - sci_free_gpios(port); - - clk_put(port->iclk); - clk_put(port->fclk); - - pm_runtime_disable(port->port.dev); -} - #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE static void serial_console_putchar(struct uart_port *port, int ch) { @@ -2370,10 +2360,14 @@ static int sci_remove(struct platform_device *dev) cpufreq_unregister_notifier(&port->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); + sci_free_gpios(port); + uart_remove_one_port(&sci_uart_driver, &port->port); - sci_cleanup_single(port); + clk_put(port->iclk); + clk_put(port->fclk); + pm_runtime_disable(&dev->dev); return 0; } @@ -2391,20 +2385,14 @@ static int __devinit sci_probe_single(struct platform_device *dev, index+1, SCI_NPORTS); dev_notice(&dev->dev, "Consider bumping " "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); - return -EINVAL; + return 0; } ret = sci_init_single(dev, sciport, index, p); if (ret) return ret; - ret = uart_add_one_port(&sci_uart_driver, &sciport->port); - if (ret) { - sci_cleanup_single(sciport); - return ret; - } - - return 0; + return uart_add_one_port(&sci_uart_driver, &sciport->port); } static int __devinit sci_probe(struct platform_device *dev) @@ -2425,22 +2413,24 @@ static int __devinit sci_probe(struct platform_device *dev) ret = sci_probe_single(dev, dev->id, p, sp); if (ret) - return ret; + goto err_unreg; sp->freq_transition.notifier_call = sci_notifier; ret = cpufreq_register_notifier(&sp->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); - if (unlikely(ret < 0)) { - sci_cleanup_single(sp); - return ret; - } + if (unlikely(ret < 0)) + goto err_unreg; #ifdef CONFIG_SH_STANDARD_BIOS sh_bios_gdb_detach(); #endif return 0; + +err_unreg: + sci_remove(dev); + return ret; } static int sci_suspend(struct device *dev) diff --git a/trunk/drivers/tty/synclink.c b/trunk/drivers/tty/synclink.c index 593d40ad0a6b..5ed0daae6564 100644 --- a/trunk/drivers/tty/synclink.c +++ b/trunk/drivers/tty/synclink.c @@ -3338,9 +3338,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, printk("%s(%d):block_til_ready blocking on %s count=%d\n", __FILE__,__LINE__, tty->driver->name, port->count ); - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); diff --git a/trunk/drivers/tty/synclink_gt.c b/trunk/drivers/tty/synclink_gt.c index aa1debf97cc7..45b43f11ca39 100644 --- a/trunk/drivers/tty/synclink_gt.c +++ b/trunk/drivers/tty/synclink_gt.c @@ -3336,9 +3336,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, } DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); diff --git a/trunk/drivers/tty/synclinkmp.c b/trunk/drivers/tty/synclinkmp.c index a3dddc12d2fe..4a1e4f07765b 100644 --- a/trunk/drivers/tty/synclinkmp.c +++ b/trunk/drivers/tty/synclinkmp.c @@ -3357,9 +3357,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, printk("%s(%d):%s block_til_ready() count=%d\n", __FILE__,__LINE__, tty->driver->name, port->count ); - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } set_current_state(TASK_RUNNING); diff --git a/trunk/drivers/tty/tty_io.c b/trunk/drivers/tty/tty_io.c index b425c79675ad..9e930c009bf2 100644 --- a/trunk/drivers/tty/tty_io.c +++ b/trunk/drivers/tty/tty_io.c @@ -185,6 +185,7 @@ void free_tty_struct(struct tty_struct *tty) put_device(tty->dev); kfree(tty->write_buf); tty_buffer_free_all(tty); + tty->magic = 0xDEADDEAD; kfree(tty); } @@ -573,7 +574,7 @@ void __tty_hangup(struct tty_struct *tty) } spin_unlock(&redirect_lock); - tty_lock(); + tty_lock(tty); /* some functions below drop BTM, so we need this bit */ set_bit(TTY_HUPPING, &tty->flags); @@ -666,7 +667,7 @@ void __tty_hangup(struct tty_struct *tty) clear_bit(TTY_HUPPING, &tty->flags); tty_ldisc_enable(tty); - tty_unlock(); + tty_unlock(tty); if (f) fput(f); @@ -1103,12 +1104,12 @@ void tty_write_message(struct tty_struct *tty, char *msg) { if (tty) { mutex_lock(&tty->atomic_write_lock); - tty_lock(); + tty_lock(tty); if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { - tty_unlock(); + tty_unlock(tty); tty->ops->write(tty, msg, strlen(msg)); } else - tty_unlock(); + tty_unlock(tty); tty_write_unlock(tty); } return; @@ -1403,6 +1404,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) } initialize_tty_struct(tty, driver, idx); + tty_lock(tty); retval = tty_driver_install_tty(driver, tty); if (retval < 0) goto err_deinit_tty; @@ -1415,9 +1417,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) retval = tty_ldisc_setup(tty, tty->link); if (retval) goto err_release_tty; + /* Return the tty locked so that it cannot vanish under the caller */ return tty; err_deinit_tty: + tty_unlock(tty); deinitialize_tty_struct(tty); free_tty_struct(tty); err_module_put: @@ -1426,6 +1430,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) /* call the tty release_tty routine to clean out this slot */ err_release_tty: + tty_unlock(tty); printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, " "clearing slot %d\n", idx); release_tty(tty, idx); @@ -1628,7 +1633,7 @@ int tty_release(struct inode *inode, struct file *filp) if (tty_paranoia_check(tty, inode, __func__)) return 0; - tty_lock(); + tty_lock(tty); check_tty_count(tty, __func__); __tty_fasync(-1, filp, 0); @@ -1637,10 +1642,11 @@ int tty_release(struct inode *inode, struct file *filp) pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER); devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; + /* Review: parallel close */ o_tty = tty->link; if (tty_release_checks(tty, o_tty, idx)) { - tty_unlock(); + tty_unlock(tty); return 0; } @@ -1652,7 +1658,7 @@ int tty_release(struct inode *inode, struct file *filp) if (tty->ops->close) tty->ops->close(tty, filp); - tty_unlock(); + tty_unlock(tty); /* * Sanity check: if tty->count is going to zero, there shouldn't be * any waiters on tty->read_wait or tty->write_wait. We test the @@ -1675,7 +1681,7 @@ int tty_release(struct inode *inode, struct file *filp) opens on /dev/tty */ mutex_lock(&tty_mutex); - tty_lock(); + tty_lock_pair(tty, o_tty); tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); @@ -1706,7 +1712,7 @@ int tty_release(struct inode *inode, struct file *filp) printk(KERN_WARNING "%s: %s: read/write wait queue active!\n", __func__, tty_name(tty, buf)); - tty_unlock(); + tty_unlock_pair(tty, o_tty); mutex_unlock(&tty_mutex); schedule(); } @@ -1769,7 +1775,7 @@ int tty_release(struct inode *inode, struct file *filp) /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) { - tty_unlock(); + tty_unlock_pair(tty, o_tty); return 0; } @@ -1782,14 +1788,16 @@ int tty_release(struct inode *inode, struct file *filp) tty_ldisc_release(tty, o_tty); /* * The release_tty function takes care of the details of clearing - * the slots and preserving the termios structure. + * the slots and preserving the termios structure. The tty_unlock_pair + * should be safe as we keep a kref while the tty is locked (so the + * unlock never unlocks a freed tty). */ release_tty(tty, idx); + tty_unlock_pair(tty, o_tty); /* Make this pty number available for reallocation */ if (devpts) devpts_kill_index(inode, idx); - tty_unlock(); return 0; } @@ -1893,6 +1901,9 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev. * tty->count should protect the rest. * ->siglock protects ->signal/->sighand + * + * Note: the tty_unlock/lock cases without a ref are only safe due to + * tty_mutex */ static int tty_open(struct inode *inode, struct file *filp) @@ -1916,8 +1927,7 @@ static int tty_open(struct inode *inode, struct file *filp) retval = 0; mutex_lock(&tty_mutex); - tty_lock(); - + /* This is protected by the tty_mutex */ tty = tty_open_current_tty(device, filp); if (IS_ERR(tty)) { retval = PTR_ERR(tty); @@ -1938,17 +1948,19 @@ static int tty_open(struct inode *inode, struct file *filp) } if (tty) { + tty_lock(tty); retval = tty_reopen(tty); - if (retval) + if (retval < 0) { + tty_unlock(tty); tty = ERR_PTR(retval); - } else + } + } else /* Returns with the tty_lock held for now */ tty = tty_init_dev(driver, index); mutex_unlock(&tty_mutex); if (driver) tty_driver_kref_put(driver); if (IS_ERR(tty)) { - tty_unlock(); retval = PTR_ERR(tty); goto err_file; } @@ -1977,7 +1989,7 @@ static int tty_open(struct inode *inode, struct file *filp) printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__, retval, tty->name); #endif - tty_unlock(); /* need to call tty_release without BTM */ + tty_unlock(tty); /* need to call tty_release without BTM */ tty_release(inode, filp); if (retval != -ERESTARTSYS) return retval; @@ -1989,17 +2001,15 @@ static int tty_open(struct inode *inode, struct file *filp) /* * Need to reset f_op in case a hangup happened. */ - tty_lock(); if (filp->f_op == &hung_up_tty_fops) filp->f_op = &tty_fops; - tty_unlock(); goto retry_open; } - tty_unlock(); + tty_unlock(tty); mutex_lock(&tty_mutex); - tty_lock(); + tty_lock(tty); spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && @@ -2007,11 +2017,10 @@ static int tty_open(struct inode *inode, struct file *filp) tty->session == NULL) __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); - tty_unlock(); + tty_unlock(tty); mutex_unlock(&tty_mutex); return 0; err_unlock: - tty_unlock(); mutex_unlock(&tty_mutex); /* after locks to avoid deadlock */ if (!IS_ERR_OR_NULL(driver)) @@ -2094,10 +2103,13 @@ static int __tty_fasync(int fd, struct file *filp, int on) static int tty_fasync(int fd, struct file *filp, int on) { + struct tty_struct *tty = file_tty(filp); int retval; - tty_lock(); + + tty_lock(tty); retval = __tty_fasync(fd, filp, on); - tty_unlock(); + tty_unlock(tty); + return retval; } @@ -2934,6 +2946,7 @@ void initialize_tty_struct(struct tty_struct *tty, tty->pgrp = NULL; tty->overrun_time = jiffies; tty_buffer_init(tty); + mutex_init(&tty->legacy_mutex); mutex_init(&tty->termios_mutex); mutex_init(&tty->ldisc_mutex); init_waitqueue_head(&tty->write_wait); diff --git a/trunk/drivers/tty/tty_ldisc.c b/trunk/drivers/tty/tty_ldisc.c index 9911eb6b34cd..ba8be396a621 100644 --- a/trunk/drivers/tty/tty_ldisc.c +++ b/trunk/drivers/tty/tty_ldisc.c @@ -568,7 +568,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); - tty_lock(); + tty_lock(tty); /* * We need to look at the tty locking here for pty/tty pairs * when both sides try to change in parallel. @@ -582,12 +582,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) */ if (tty->ldisc->ops->num == ldisc) { - tty_unlock(); + tty_unlock(tty); tty_ldisc_put(new_ldisc); return 0; } - tty_unlock(); + tty_unlock(tty); /* * Problem: What do we do if this blocks ? * We could deadlock here @@ -595,7 +595,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_wait_until_sent(tty, 0); - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); /* @@ -605,10 +605,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { mutex_unlock(&tty->ldisc_mutex); - tty_unlock(); + tty_unlock(tty); wait_event(tty_ldisc_wait, test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); } @@ -623,7 +623,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) o_ldisc = tty->ldisc; - tty_unlock(); + tty_unlock(tty); /* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit @@ -650,7 +650,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) retval = tty_ldisc_wait_idle(tty, 5 * HZ); - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); /* handle wait idle failure locked */ @@ -665,7 +665,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) clear_bit(TTY_LDISC_CHANGING, &tty->flags); mutex_unlock(&tty->ldisc_mutex); tty_ldisc_put(new_ldisc); - tty_unlock(); + tty_unlock(tty); return -EIO; } @@ -708,7 +708,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (o_work) schedule_work(&o_tty->buf.work); mutex_unlock(&tty->ldisc_mutex); - tty_unlock(); + tty_unlock(tty); return retval; } @@ -816,11 +816,11 @@ void tty_ldisc_hangup(struct tty_struct *tty) * need to wait for another function taking the BTM */ clear_bit(TTY_LDISC, &tty->flags); - tty_unlock(); + tty_unlock(tty); cancel_work_sync(&tty->buf.work); mutex_unlock(&tty->ldisc_mutex); retry: - tty_lock(); + tty_lock(tty); mutex_lock(&tty->ldisc_mutex); /* At this point we have a closed ldisc and we want to @@ -831,7 +831,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) if (atomic_read(&tty->ldisc->users) != 1) { char cur_n[TASK_COMM_LEN], tty_n[64]; long timeout = 3 * HZ; - tty_unlock(); + tty_unlock(tty); while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { timeout = MAX_SCHEDULE_TIMEOUT; @@ -894,6 +894,23 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) tty_ldisc_enable(tty); return 0; } + +static void tty_ldisc_kill(struct tty_struct *tty) +{ + mutex_lock(&tty->ldisc_mutex); + /* + * Now kill off the ldisc + */ + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + /* Force an oops if we mess this up */ + tty->ldisc = NULL; + + /* Ensure the next open requests the N_TTY ldisc */ + tty_set_termios_ldisc(tty, N_TTY); + mutex_unlock(&tty->ldisc_mutex); +} + /** * tty_ldisc_release - release line discipline * @tty: tty being shut down @@ -912,27 +929,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) * race with the set_ldisc code path. */ - tty_unlock(); + tty_unlock_pair(tty, o_tty); tty_ldisc_halt(tty); tty_ldisc_flush_works(tty); - tty_lock(); - - mutex_lock(&tty->ldisc_mutex); - /* - * Now kill off the ldisc - */ - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* Force an oops if we mess this up */ - tty->ldisc = NULL; + if (o_tty) { + tty_ldisc_halt(o_tty); + tty_ldisc_flush_works(o_tty); + } + tty_lock_pair(tty, o_tty); - /* Ensure the next open requests the N_TTY ldisc */ - tty_set_termios_ldisc(tty, N_TTY); - mutex_unlock(&tty->ldisc_mutex); - /* This will need doing differently if we need to lock */ + tty_ldisc_kill(tty); if (o_tty) - tty_ldisc_release(o_tty, NULL); + tty_ldisc_kill(o_tty); /* And the memory resources remaining (buffers, termios) will be disposed of when the kref hits zero */ diff --git a/trunk/drivers/tty/tty_mutex.c b/trunk/drivers/tty/tty_mutex.c index 9ff986c32a21..69adc80c98cd 100644 --- a/trunk/drivers/tty/tty_mutex.c +++ b/trunk/drivers/tty/tty_mutex.c @@ -4,29 +4,59 @@ #include #include -/* - * The 'big tty mutex' - * - * This mutex is taken and released by tty_lock() and tty_unlock(), - * replacing the older big kernel lock. - * It can no longer be taken recursively, and does not get - * released implicitly while sleeping. - * - * Don't use in new code. - */ -static DEFINE_MUTEX(big_tty_mutex); +/* Legacy tty mutex glue */ /* * Getting the big tty mutex. */ -void __lockfunc tty_lock(void) + +void __lockfunc tty_lock(struct tty_struct *tty) { - mutex_lock(&big_tty_mutex); + if (tty->magic != TTY_MAGIC) { + printk(KERN_ERR "L Bad %p\n", tty); + WARN_ON(1); + return; + } + tty_kref_get(tty); + mutex_lock(&tty->legacy_mutex); } EXPORT_SYMBOL(tty_lock); -void __lockfunc tty_unlock(void) +void __lockfunc tty_unlock(struct tty_struct *tty) { - mutex_unlock(&big_tty_mutex); + if (tty->magic != TTY_MAGIC) { + printk(KERN_ERR "U Bad %p\n", tty); + WARN_ON(1); + return; + } + mutex_unlock(&tty->legacy_mutex); + tty_kref_put(tty); } EXPORT_SYMBOL(tty_unlock); + +/* + * Getting the big tty mutex for a pair of ttys with lock ordering + * On a non pty/tty pair tty2 can be NULL which is just fine. + */ +void __lockfunc tty_lock_pair(struct tty_struct *tty, + struct tty_struct *tty2) +{ + if (tty < tty2) { + tty_lock(tty); + tty_lock(tty2); + } else { + if (tty2 && tty2 != tty) + tty_lock(tty2); + tty_lock(tty); + } +} +EXPORT_SYMBOL(tty_lock_pair); + +void __lockfunc tty_unlock_pair(struct tty_struct *tty, + struct tty_struct *tty2) +{ + tty_unlock(tty); + if (tty2 && tty2 != tty) + tty_unlock(tty2); +} +EXPORT_SYMBOL(tty_unlock_pair); diff --git a/trunk/drivers/tty/tty_port.c b/trunk/drivers/tty/tty_port.c index bf6e238146ae..d9cca95a5452 100644 --- a/trunk/drivers/tty/tty_port.c +++ b/trunk/drivers/tty/tty_port.c @@ -230,7 +230,7 @@ int tty_port_block_til_ready(struct tty_port *port, /* block if port is in the process of being closed */ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { - wait_event_interruptible_tty(port->close_wait, + wait_event_interruptible_tty(tty, port->close_wait, !(port->flags & ASYNC_CLOSING)); if (port->flags & ASYNC_HUP_NOTIFY) return -EAGAIN; @@ -296,9 +296,9 @@ int tty_port_block_til_ready(struct tty_port *port, retval = -ERESTARTSYS; break; } - tty_unlock(); + tty_unlock(tty); schedule(); - tty_lock(); + tty_lock(tty); } finish_wait(&port->open_wait, &wait); diff --git a/trunk/drivers/usb/class/cdc-acm.c b/trunk/drivers/usb/class/cdc-acm.c index 36a2a0b7b82c..f2a120eea9d4 100644 --- a/trunk/drivers/usb/class/cdc-acm.c +++ b/trunk/drivers/usb/class/cdc-acm.c @@ -567,14 +567,6 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) usb_autopm_put_interface(acm->control); - /* - * Unthrottle device in case the TTY was closed while throttled. - */ - spin_lock_irq(&acm->read_lock); - acm->throttled = 0; - acm->throttle_req = 0; - spin_unlock_irq(&acm->read_lock); - if (acm_submit_read_urbs(acm, GFP_KERNEL)) goto error_submit_read_urbs; diff --git a/trunk/drivers/usb/class/cdc-wdm.c b/trunk/drivers/usb/class/cdc-wdm.c index 8fd398dffced..ea8b304f0e85 100644 --- a/trunk/drivers/usb/class/cdc-wdm.c +++ b/trunk/drivers/usb/class/cdc-wdm.c @@ -55,15 +55,6 @@ static const struct usb_device_id wdm_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */ }, - { - /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR | - USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 57, /* NOTE: CDC ECM control interface! */ - }, { } }; diff --git a/trunk/drivers/usb/core/hcd-pci.c b/trunk/drivers/usb/core/hcd-pci.c index 622b4a48e732..57ed9e400c06 100644 --- a/trunk/drivers/usb/core/hcd-pci.c +++ b/trunk/drivers/usb/core/hcd-pci.c @@ -493,6 +493,15 @@ static int hcd_pci_suspend_noirq(struct device *dev) pci_save_state(pci_dev); + /* + * Some systems crash if an EHCI controller is in D3 during + * a sleep transition. We have to leave such controllers in D0. + */ + if (hcd->broken_pci_sleep) { + dev_dbg(dev, "Staying in PCI D0\n"); + return retval; + } + /* If the root hub is dead rather than suspended, disallow remote * wakeup. usb_hc_died() should ensure that both hosts are marked as * dying, so we only need to check the primary roothub. diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index 25a7422ee657..04fb834c3fa1 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -3379,7 +3379,7 @@ int usb_disable_lpm(struct usb_device *udev) return 0; udev->lpm_disable_count++; - if ((udev->u1_params.timeout == 0 && udev->u2_params.timeout == 0)) + if ((udev->u1_params.timeout == 0 && udev->u1_params.timeout == 0)) return 0; /* If LPM is enabled, attempt to disable it. */ diff --git a/trunk/drivers/usb/core/message.c b/trunk/drivers/usb/core/message.c index bdd1c6749d88..b548cf1dbc62 100644 --- a/trunk/drivers/usb/core/message.c +++ b/trunk/drivers/usb/core/message.c @@ -1838,6 +1838,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) intfc = cp->intf_cache[i]; intf->altsetting = intfc->altsetting; intf->num_altsetting = intfc->num_altsetting; + intf->intf_assoc = find_iad(dev, cp, i); kref_get(&intfc->ref); alt = usb_altnum_to_altsetting(intf, 0); @@ -1850,8 +1851,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (!alt) alt = &intf->altsetting[0]; - intf->intf_assoc = - find_iad(dev, cp, alt->desc.bInterfaceNumber); intf->cur_altsetting = alt; usb_enable_interface(dev, intf, true); intf->dev.parent = &dev->dev; diff --git a/trunk/drivers/usb/gadget/atmel_usba_udc.c b/trunk/drivers/usb/gadget/atmel_usba_udc.c index 9a9bced813ed..e23bf7984aaf 100644 --- a/trunk/drivers/usb/gadget/atmel_usba_udc.c +++ b/trunk/drivers/usb/gadget/atmel_usba_udc.c @@ -599,6 +599,12 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) spin_lock_irqsave(&ep->udc->lock, flags); + if (ep->ep.desc) { + spin_unlock_irqrestore(&ep->udc->lock, flags); + DBG(DBG_ERR, "ep%d already enabled\n", ep->index); + return -EBUSY; + } + ep->ep.desc = desc; ep->ep.maxpacket = maxpacket; diff --git a/trunk/drivers/usb/gadget/fsl_qe_udc.c b/trunk/drivers/usb/gadget/fsl_qe_udc.c index b09452d6f33a..51881f3bd07a 100644 --- a/trunk/drivers/usb/gadget/fsl_qe_udc.c +++ b/trunk/drivers/usb/gadget/fsl_qe_udc.c @@ -1596,7 +1596,7 @@ static int qe_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct qe_ep, ep); /* catch various bogus parameters */ - if (!_ep || !desc || _ep->name == ep_name[0] || + if (!_ep || !desc || ep->ep.desc || _ep->name == ep_name[0] || (desc->bDescriptorType != USB_DT_ENDPOINT)) return -EINVAL; diff --git a/trunk/drivers/usb/gadget/fsl_udc_core.c b/trunk/drivers/usb/gadget/fsl_udc_core.c index bc6f9bb9994a..28316858208b 100644 --- a/trunk/drivers/usb/gadget/fsl_udc_core.c +++ b/trunk/drivers/usb/gadget/fsl_udc_core.c @@ -567,7 +567,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct fsl_ep, ep); /* catch various bogus parameters */ - if (!_ep || !desc + if (!_ep || !desc || ep->ep.desc || (desc->bDescriptorType != USB_DT_ENDPOINT)) return -EINVAL; @@ -2575,7 +2575,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) /* for ep0: the desc defined here; * for other eps, gadget layer called ep_enable with defined desc */ - udc_controller->eps[0].ep.desc = &fsl_ep0_desc; + udc_controller->eps[0].desc = &fsl_ep0_desc; udc_controller->eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD; /* setup the udc->eps[] for non-control endpoints and link diff --git a/trunk/drivers/usb/gadget/fsl_usb2_udc.h b/trunk/drivers/usb/gadget/fsl_usb2_udc.h index f61a967f7082..5cd7b7e7ddb4 100644 --- a/trunk/drivers/usb/gadget/fsl_usb2_udc.h +++ b/trunk/drivers/usb/gadget/fsl_usb2_udc.h @@ -568,10 +568,10 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) /* * ### internal used help routines. */ -#define ep_index(EP) ((EP)->ep.desc->bEndpointAddress&0xF) +#define ep_index(EP) ((EP)->desc->bEndpointAddress&0xF) #define ep_maxpacket(EP) ((EP)->ep.maxpacket) #define ep_is_in(EP) ( (ep_index(EP) == 0) ? (EP->udc->ep0_dir == \ - USB_DIR_IN) : ((EP)->ep.desc->bEndpointAddress \ + USB_DIR_IN ):((EP)->desc->bEndpointAddress \ & USB_DIR_IN)==USB_DIR_IN) #define get_ep_by_pipe(udc, pipe) ((pipe == 1)? &udc->eps[0]: \ &udc->eps[pipe]) diff --git a/trunk/drivers/usb/gadget/goku_udc.c b/trunk/drivers/usb/gadget/goku_udc.c index 3d28fb976c78..b241e6c6a7f2 100644 --- a/trunk/drivers/usb/gadget/goku_udc.c +++ b/trunk/drivers/usb/gadget/goku_udc.c @@ -102,7 +102,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) unsigned long flags; ep = container_of(_ep, struct goku_ep, ep); - if (!_ep || !desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; dev = ep->dev; diff --git a/trunk/drivers/usb/gadget/mv_udc_core.c b/trunk/drivers/usb/gadget/mv_udc_core.c index 117a4bba1b8c..dbcd1329495e 100644 --- a/trunk/drivers/usb/gadget/mv_udc_core.c +++ b/trunk/drivers/usb/gadget/mv_udc_core.c @@ -464,7 +464,7 @@ static int mv_ep_enable(struct usb_ep *_ep, ep = container_of(_ep, struct mv_ep, ep); udc = ep->udc; - if (!_ep || !desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; diff --git a/trunk/drivers/usb/gadget/omap_udc.c b/trunk/drivers/usb/gadget/omap_udc.c index a460e8c204f4..7ba32469c5bd 100644 --- a/trunk/drivers/usb/gadget/omap_udc.c +++ b/trunk/drivers/usb/gadget/omap_udc.c @@ -153,7 +153,7 @@ static int omap_ep_enable(struct usb_ep *_ep, u16 maxp; /* catch various bogus parameters */ - if (!_ep || !desc + if (!_ep || !desc || ep->ep.desc || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress || ep->maxpacket < usb_endpoint_maxp(desc)) { diff --git a/trunk/drivers/usb/gadget/pxa25x_udc.c b/trunk/drivers/usb/gadget/pxa25x_udc.c index f7ff9e8e746a..d7c8cb3bf759 100644 --- a/trunk/drivers/usb/gadget/pxa25x_udc.c +++ b/trunk/drivers/usb/gadget/pxa25x_udc.c @@ -218,7 +218,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, struct pxa25x_udc *dev; ep = container_of (_ep, struct pxa25x_ep, ep); - if (!_ep || !desc || _ep->name == ep0name + if (!_ep || !desc || ep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress || ep->fifo_size < usb_endpoint_maxp (desc)) { diff --git a/trunk/drivers/usb/gadget/s3c-hsudc.c b/trunk/drivers/usb/gadget/s3c-hsudc.c index 236b271871a0..36c6836eeb0f 100644 --- a/trunk/drivers/usb/gadget/s3c-hsudc.c +++ b/trunk/drivers/usb/gadget/s3c-hsudc.c @@ -760,7 +760,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, u32 ecr = 0; hsep = our_ep(_ep); - if (!_ep || !desc || _ep->name == ep0name + if (!_ep || !desc || hsep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || hsep->bEndpointAddress != desc->bEndpointAddress || ep_maxpacket(hsep) < usb_endpoint_maxp(desc)) diff --git a/trunk/drivers/usb/gadget/s3c2410_udc.c b/trunk/drivers/usb/gadget/s3c2410_udc.c index f2e51f50e528..3de71d37d75e 100644 --- a/trunk/drivers/usb/gadget/s3c2410_udc.c +++ b/trunk/drivers/usb/gadget/s3c2410_udc.c @@ -1062,7 +1062,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, ep = to_s3c2410_ep(_ep); - if (!_ep || !desc + if (!_ep || !desc || ep->ep.desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT) return -EINVAL; diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index 800be38c78b4..b100f5f9f4b6 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/drivers/usb/host/ehci-hcd.c @@ -671,9 +671,7 @@ static int ehci_init(struct usb_hcd *hcd) hw = ehci->async->hw; hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); -#if defined(CONFIG_PPC_PS3) hw->hw_info1 |= cpu_to_hc32(ehci, (1 << 7)); /* I = 1 */ -#endif hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); hw->hw_qtd_next = EHCI_LIST_END(ehci); ehci->async->qh_state = QH_STATE_LINKED; diff --git a/trunk/drivers/usb/host/ehci-omap.c b/trunk/drivers/usb/host/ehci-omap.c index 17cfb8a1131c..a44294d13494 100644 --- a/trunk/drivers/usb/host/ehci-omap.c +++ b/trunk/drivers/usb/host/ehci-omap.c @@ -43,7 +43,6 @@ #include #include #include -#include /* EHCI Register Set */ #define EHCI_INSNREG04 (0xA0) @@ -56,15 +55,6 @@ #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 -/* Errata i693 */ -static struct clk *utmi_p1_fck; -static struct clk *utmi_p2_fck; -static struct clk *xclk60mhsp1_ck; -static struct clk *xclk60mhsp2_ck; -static struct clk *usbhost_p1_fck; -static struct clk *usbhost_p2_fck; -static struct clk *init_60m_fclk; - /*-------------------------------------------------------------------------*/ static const struct hc_driver ehci_omap_hc_driver; @@ -80,41 +70,6 @@ static inline u32 ehci_read(void __iomem *base, u32 reg) return __raw_readl(base + reg); } -/* Erratum i693 workaround sequence */ -static void omap_ehci_erratum_i693(struct ehci_hcd *ehci) -{ - int ret = 0; - - /* Switch to the internal 60 MHz clock */ - ret = clk_set_parent(utmi_p1_fck, init_60m_fclk); - if (ret != 0) - ehci_err(ehci, "init_60m_fclk set parent" - "failed error:%d\n", ret); - - ret = clk_set_parent(utmi_p2_fck, init_60m_fclk); - if (ret != 0) - ehci_err(ehci, "init_60m_fclk set parent" - "failed error:%d\n", ret); - - clk_enable(usbhost_p1_fck); - clk_enable(usbhost_p2_fck); - - /* Wait 1ms and switch back to the external clock */ - mdelay(1); - ret = clk_set_parent(utmi_p1_fck, xclk60mhsp1_ck); - if (ret != 0) - ehci_err(ehci, "xclk60mhsp1_ck set parent" - "failed error:%d\n", ret); - - ret = clk_set_parent(utmi_p2_fck, xclk60mhsp2_ck); - if (ret != 0) - ehci_err(ehci, "xclk60mhsp2_ck set parent" - "failed error:%d\n", ret); - - clk_disable(usbhost_p1_fck); - clk_disable(usbhost_p2_fck); -} - static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) { struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); @@ -145,50 +100,6 @@ static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) } } -static int omap_ehci_hub_control( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, - u16 wLength -) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - u32 __iomem *status_reg = &ehci->regs->port_status[ - (wIndex & 0xff) - 1]; - u32 temp; - unsigned long flags; - int retval = 0; - - spin_lock_irqsave(&ehci->lock, flags); - - if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { - temp = ehci_readl(ehci, status_reg); - if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { - retval = -EPIPE; - goto done; - } - - temp &= ~PORT_WKCONN_E; - temp |= PORT_WKDISC_E | PORT_WKOC_E; - ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); - - omap_ehci_erratum_i693(ehci); - - set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); - goto done; - } - - spin_unlock_irqrestore(&ehci->lock, flags); - - /* Handle the hub control events here */ - return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); -done: - spin_unlock_irqrestore(&ehci->lock, flags); - return retval; -} - static void disable_put_regulator( struct ehci_hcd_omap_platform_data *pdata) { @@ -353,76 +264,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) /* root ports should always stay powered */ ehci_port_power(omap_ehci, 1); - /* get clocks */ - utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); - if (IS_ERR(utmi_p1_fck)) { - ret = PTR_ERR(utmi_p1_fck); - dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); - goto err_add_hcd; - } - - xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); - if (IS_ERR(xclk60mhsp1_ck)) { - ret = PTR_ERR(xclk60mhsp1_ck); - dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); - goto err_utmi_p1_fck; - } - - utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); - if (IS_ERR(utmi_p2_fck)) { - ret = PTR_ERR(utmi_p2_fck); - dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); - goto err_xclk60mhsp1_ck; - } - - xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); - if (IS_ERR(xclk60mhsp2_ck)) { - ret = PTR_ERR(xclk60mhsp2_ck); - dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); - goto err_utmi_p2_fck; - } - - usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); - if (IS_ERR(usbhost_p1_fck)) { - ret = PTR_ERR(usbhost_p1_fck); - dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); - goto err_xclk60mhsp2_ck; - } - - usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); - if (IS_ERR(usbhost_p2_fck)) { - ret = PTR_ERR(usbhost_p2_fck); - dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); - goto err_usbhost_p1_fck; - } - - init_60m_fclk = clk_get(dev, "init_60m_fclk"); - if (IS_ERR(init_60m_fclk)) { - ret = PTR_ERR(init_60m_fclk); - dev_err(dev, "init_60m_fclk failed error:%d\n", ret); - goto err_usbhost_p2_fck; - } - return 0; -err_usbhost_p2_fck: - clk_put(usbhost_p2_fck); - -err_usbhost_p1_fck: - clk_put(usbhost_p1_fck); - -err_xclk60mhsp2_ck: - clk_put(xclk60mhsp2_ck); - -err_utmi_p2_fck: - clk_put(utmi_p2_fck); - -err_xclk60mhsp1_ck: - clk_put(xclk60mhsp1_ck); - -err_utmi_p1_fck: - clk_put(utmi_p1_fck); - err_add_hcd: disable_put_regulator(pdata); pm_runtime_put_sync(dev); @@ -451,15 +294,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) disable_put_regulator(dev->platform_data); iounmap(hcd->regs); usb_put_hcd(hcd); - - clk_put(utmi_p1_fck); - clk_put(utmi_p2_fck); - clk_put(xclk60mhsp1_ck); - clk_put(xclk60mhsp2_ck); - clk_put(usbhost_p1_fck); - clk_put(usbhost_p2_fck); - clk_put(init_60m_fclk); - pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -530,7 +364,7 @@ static const struct hc_driver ehci_omap_hc_driver = { * root hub support */ .hub_status_data = ehci_hub_status_data, - .hub_control = omap_ehci_hub_control, + .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, diff --git a/trunk/drivers/usb/host/ehci-pci.c b/trunk/drivers/usb/host/ehci-pci.c index 123481793a47..bc94d7bf072d 100644 --- a/trunk/drivers/usb/host/ehci-pci.c +++ b/trunk/drivers/usb/host/ehci-pci.c @@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd) hcd->has_tt = 1; tdi_reset(ehci); } + if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) { + /* EHCI #1 or #2 on 6 Series/C200 Series chipset */ + if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) { + ehci_info(ehci, "broken D3 during system sleep on ASUS\n"); + hcd->broken_pci_sleep = 1; + device_set_wakeup_capable(&pdev->dev, false); + } + } break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { diff --git a/trunk/drivers/usb/host/ehci-sh.c b/trunk/drivers/usb/host/ehci-sh.c index e7cb3925abf8..ca819cdd0c5e 100644 --- a/trunk/drivers/usb/host/ehci-sh.c +++ b/trunk/drivers/usb/host/ehci-sh.c @@ -126,7 +126,8 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) goto fail_create_hcd; } - pdata = pdev->dev.platform_data; + if (pdev->dev.platform_data != NULL) + pdata = pdev->dev.platform_data; /* initialize hcd */ hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev, diff --git a/trunk/drivers/usb/host/ehci-xilinx-of.c b/trunk/drivers/usb/host/ehci-xilinx-of.c index e9713d589e30..9c2cc4633894 100644 --- a/trunk/drivers/usb/host/ehci-xilinx-of.c +++ b/trunk/drivers/usb/host/ehci-xilinx-of.c @@ -270,12 +270,14 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op) * * Properly shutdown the hcd, call driver's shutdown routine. */ -static void ehci_hcd_xilinx_of_shutdown(struct platform_device *op) +static int ehci_hcd_xilinx_of_shutdown(struct platform_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); + + return 0; } diff --git a/trunk/drivers/usb/host/ohci-hub.c b/trunk/drivers/usb/host/ohci-hub.c index 2f3619eefefa..836772dfabd3 100644 --- a/trunk/drivers/usb/host/ohci-hub.c +++ b/trunk/drivers/usb/host/ohci-hub.c @@ -317,7 +317,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd) } /* Carry out the final steps of resuming the controller device */ -static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd) +static void ohci_finish_controller_resume(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); int port; diff --git a/trunk/drivers/usb/host/xhci-mem.c b/trunk/drivers/usb/host/xhci-mem.c index 77689bd64cac..ec4338eec826 100644 --- a/trunk/drivers/usb/host/xhci-mem.c +++ b/trunk/drivers/usb/host/xhci-mem.c @@ -793,9 +793,10 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, int slot_id) { + struct list_head *tt; struct list_head *tt_list_head; - struct xhci_tt_bw_info *tt_info, *next; - bool slot_found = false; + struct list_head *tt_next; + struct xhci_tt_bw_info *tt_info; /* If the device never made it past the Set Address stage, * it may not have the real_port set correctly. @@ -807,16 +808,34 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci, } tt_list_head = &(xhci->rh_bw[virt_dev->real_port - 1].tts); - list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) { - /* Multi-TT hubs will have more than one entry */ - if (tt_info->slot_id == slot_id) { - slot_found = true; - list_del(&tt_info->tt_list); - kfree(tt_info); - } else if (slot_found) { + if (list_empty(tt_list_head)) + return; + + list_for_each(tt, tt_list_head) { + tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); + if (tt_info->slot_id == slot_id) break; - } } + /* Cautionary measure in case the hub was disconnected before we + * stored the TT information. + */ + if (tt_info->slot_id != slot_id) + return; + + tt_next = tt->next; + tt_info = list_entry(tt, struct xhci_tt_bw_info, + tt_list); + /* Multi-TT hubs will have more than one entry */ + do { + list_del(tt); + kfree(tt_info); + tt = tt_next; + if (list_empty(tt_list_head)) + break; + tt_next = tt->next; + tt_info = list_entry(tt, struct xhci_tt_bw_info, + tt_list); + } while (tt_info->slot_id == slot_id); } int xhci_alloc_tt_info(struct xhci_hcd *xhci, @@ -1772,9 +1791,17 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; + struct list_head *tt_list_head; + struct list_head *tt; + struct list_head *endpoints; + struct list_head *ep, *q; + struct xhci_tt_bw_info *tt_info; + struct xhci_interval_bw_table *bwt; + struct xhci_virt_ep *virt_ep; + unsigned long flags; int size; - int i, j, num_ports; + int i; /* Free the Event Ring Segment Table and the actual Event Ring */ size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); @@ -1833,22 +1860,21 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } spin_unlock_irqrestore(&xhci->lock, flags); - num_ports = HCS_MAX_PORTS(xhci->hcs_params1); - for (i = 0; i < num_ports; i++) { - struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; - for (j = 0; j < XHCI_MAX_INTERVAL; j++) { - struct list_head *ep = &bwt->interval_bw[j].endpoints; - while (!list_empty(ep)) - list_del_init(ep->next); + bwt = &xhci->rh_bw->bw_table; + for (i = 0; i < XHCI_MAX_INTERVAL; i++) { + endpoints = &bwt->interval_bw[i].endpoints; + list_for_each_safe(ep, q, endpoints) { + virt_ep = list_entry(ep, struct xhci_virt_ep, bw_endpoint_list); + list_del(&virt_ep->bw_endpoint_list); + kfree(virt_ep); } } - for (i = 0; i < num_ports; i++) { - struct xhci_tt_bw_info *tt, *n; - list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) { - list_del(&tt->tt_list); - kfree(tt); - } + tt_list_head = &xhci->rh_bw->tts; + list_for_each_safe(tt, q, tt_list_head) { + tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); + list_del(tt); + kfree(tt_info); } xhci->num_usb2_ports = 0; diff --git a/trunk/drivers/usb/host/xhci.c b/trunk/drivers/usb/host/xhci.c index a979cd0dbe0f..afdc73ee84a6 100644 --- a/trunk/drivers/usb/host/xhci.c +++ b/trunk/drivers/usb/host/xhci.c @@ -795,8 +795,8 @@ int xhci_suspend(struct xhci_hcd *xhci) command = xhci_readl(xhci, &xhci->op_regs->command); command |= CMD_CSS; xhci_writel(xhci, command, &xhci->op_regs->command); - if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) { - xhci_warn(xhci, "WARN: xHC save state timeout\n"); + if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) { + xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } @@ -848,8 +848,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) command |= CMD_CRS; xhci_writel(xhci, command, &xhci->op_regs->command); if (handshake(xhci, &xhci->op_regs->status, - STS_RESTORE, 0, 10 * 1000)) { - xhci_warn(xhci, "WARN: xHC restore state timeout\n"); + STS_RESTORE, 0, 10*100)) { + xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } @@ -3906,7 +3906,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, default: dev_warn(&udev->dev, "%s: Can't get timeout for non-U1 or U2 state.\n", __func__); - return USB3_LPM_DISABLED; + return -EINVAL; } if (sel <= max_sel_pel && pel <= max_sel_pel) diff --git a/trunk/drivers/usb/musb/davinci.c b/trunk/drivers/usb/musb/davinci.c index 9d63ba4d10d6..768b4b55c816 100644 --- a/trunk/drivers/usb/musb/davinci.c +++ b/trunk/drivers/usb/musb/davinci.c @@ -34,7 +34,6 @@ #include #include -#include #include diff --git a/trunk/drivers/usb/musb/davinci.h b/trunk/drivers/usb/musb/davinci.h index 371baa0ee509..046c84433cad 100644 --- a/trunk/drivers/usb/musb/davinci.h +++ b/trunk/drivers/usb/musb/davinci.h @@ -15,7 +15,7 @@ */ /* Integrated highspeed/otg PHY */ -#define USBPHY_CTL_PADDR 0x01c40034 +#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) #define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */ #define USBPHY_PHYCLKGD BIT(8) #define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ @@ -27,7 +27,7 @@ #define USBPHY_OTGPDWN BIT(1) #define USBPHY_PHYPDWN BIT(0) -#define DM355_DEEPSLEEP_PADDR 0x01c40048 +#define DM355_DEEPSLEEP_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x48) #define DRVVBUS_FORCE BIT(2) #define DRVVBUS_OVERRIDE BIT(1) diff --git a/trunk/drivers/usb/musb/musb_gadget.c b/trunk/drivers/usb/musb/musb_gadget.c index 95918dacc99a..f42c29b11f71 100644 --- a/trunk/drivers/usb/musb/musb_gadget.c +++ b/trunk/drivers/usb/musb/musb_gadget.c @@ -1232,7 +1232,6 @@ static int musb_gadget_disable(struct usb_ep *ep) } musb_ep->desc = NULL; - musb_ep->end_point.desc = NULL; /* abort all pending DMA and requests */ nuke(musb_ep, -ESHUTDOWN); diff --git a/trunk/drivers/usb/serial/cp210x.c b/trunk/drivers/usb/serial/cp210x.c index 73d25cd8cba5..1b1926200ba7 100644 --- a/trunk/drivers/usb/serial/cp210x.c +++ b/trunk/drivers/usb/serial/cp210x.c @@ -82,7 +82,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ { USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */ { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ - { USB_DEVICE(0x10C4, 0x80C4) }, /* Cygnal Integrated Products, Inc., Optris infrared thermometer */ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index bc912e5a3beb..8c084ea34e26 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -737,7 +737,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) }, - { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_RTS01_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, diff --git a/trunk/drivers/usb/serial/ftdi_sio_ids.h b/trunk/drivers/usb/serial/ftdi_sio_ids.h index 5661c7e2d415..f3c7c78ede33 100644 --- a/trunk/drivers/usb/serial/ftdi_sio_ids.h +++ b/trunk/drivers/usb/serial/ftdi_sio_ids.h @@ -784,7 +784,6 @@ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ #define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */ #define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */ -#define RTSYSTEMS_RTS01_PID 0x9e57 /* USB-RTS01 Radio Cable */ /* diff --git a/trunk/drivers/usb/serial/generic.c b/trunk/drivers/usb/serial/generic.c index 9b026bf7afef..105a6d898ca4 100644 --- a/trunk/drivers/usb/serial/generic.c +++ b/trunk/drivers/usb/serial/generic.c @@ -39,6 +39,13 @@ MODULE_PARM_DESC(product, "User specified USB idProduct"); static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ +/* we want to look at all devices, as the vendor/product id can change + * depending on the command line argument */ +static const struct usb_device_id generic_serial_ids[] = { + {.driver_info = 42}, + {} +}; + /* All of the device info needed for the Generic Serial Converter */ struct usb_serial_driver usb_serial_generic_device = { .driver = { @@ -72,8 +79,7 @@ int usb_serial_generic_register(int _debug) USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT; /* register our generic driver with ourselves */ - retval = usb_serial_register_drivers(serial_drivers, - "usbserial_generic", generic_device_ids); + retval = usb_serial_register_drivers(serial_drivers, "usbserial_generic", generic_serial_ids); #endif return retval; } diff --git a/trunk/drivers/usb/serial/mct_u232.c b/trunk/drivers/usb/serial/mct_u232.c index a71fa0aa0406..d0ec1aa52719 100644 --- a/trunk/drivers/usb/serial/mct_u232.c +++ b/trunk/drivers/usb/serial/mct_u232.c @@ -309,16 +309,13 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial, MCT_U232_SET_REQUEST_TYPE, 0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE, WDR_TIMEOUT); - kfree(buf); - - dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); - - if (rc < 0) { + if (rc < 0) dev_err(&serial->dev->dev, "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); - return rc; - } - return 0; + dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); + + kfree(buf); + return rc; } /* mct_u232_set_modem_ctrl */ static int mct_u232_get_modem_stat(struct usb_serial *serial, diff --git a/trunk/drivers/usb/serial/mos7840.c b/trunk/drivers/usb/serial/mos7840.c index 57eca2448424..29160f8b5101 100644 --- a/trunk/drivers/usb/serial/mos7840.c +++ b/trunk/drivers/usb/serial/mos7840.c @@ -190,7 +190,7 @@ static int device_type; -static const struct usb_device_id id_table[] = { +static const struct usb_device_id id_table[] __devinitconst = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)}, diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index e668a2460bd4..1aae9028cd0b 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -47,7 +47,6 @@ /* Function prototypes */ static int option_probe(struct usb_serial *serial, const struct usb_device_id *id); -static void option_release(struct usb_serial *serial); static int option_send_setup(struct usb_serial_port *port); static void option_instat_callback(struct urb *urb); @@ -151,7 +150,6 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_PRODUCT_E14AC 0x14AC #define HUAWEI_PRODUCT_K3806 0x14AE #define HUAWEI_PRODUCT_K4605 0x14C6 -#define HUAWEI_PRODUCT_K5005 0x14C8 #define HUAWEI_PRODUCT_K3770 0x14C9 #define HUAWEI_PRODUCT_K3771 0x14CA #define HUAWEI_PRODUCT_K4510 0x14CB @@ -427,7 +425,7 @@ static void option_instat_callback(struct urb *urb); #define SAMSUNG_VENDOR_ID 0x04e8 #define SAMSUNG_PRODUCT_GT_B3730 0x6889 -/* YUGA products www.yuga-info.com gavin.kx@qq.com */ +/* YUGA products www.yuga-info.com*/ #define YUGA_VENDOR_ID 0x257A #define YUGA_PRODUCT_CEM600 0x1601 #define YUGA_PRODUCT_CEM610 0x1602 @@ -444,8 +442,6 @@ static void option_instat_callback(struct urb *urb); #define YUGA_PRODUCT_CEU516 0x160C #define YUGA_PRODUCT_CEU528 0x160D #define YUGA_PRODUCT_CEU526 0x160F -#define YUGA_PRODUCT_CEU881 0x161F -#define YUGA_PRODUCT_CEU882 0x162F #define YUGA_PRODUCT_CWM600 0x2601 #define YUGA_PRODUCT_CWM610 0x2602 @@ -461,26 +457,23 @@ static void option_instat_callback(struct urb *urb); #define YUGA_PRODUCT_CWU518 0x260B #define YUGA_PRODUCT_CWU516 0x260C #define YUGA_PRODUCT_CWU528 0x260D -#define YUGA_PRODUCT_CWU581 0x260E #define YUGA_PRODUCT_CWU526 0x260F -#define YUGA_PRODUCT_CWU582 0x261F -#define YUGA_PRODUCT_CWU583 0x262F - -#define YUGA_PRODUCT_CLM600 0x3601 -#define YUGA_PRODUCT_CLM610 0x3602 -#define YUGA_PRODUCT_CLM500 0x3603 -#define YUGA_PRODUCT_CLM510 0x3604 -#define YUGA_PRODUCT_CLM800 0x3605 -#define YUGA_PRODUCT_CLM900 0x3606 - -#define YUGA_PRODUCT_CLU718 0x3607 -#define YUGA_PRODUCT_CLU716 0x3608 -#define YUGA_PRODUCT_CLU728 0x3609 -#define YUGA_PRODUCT_CLU726 0x360A -#define YUGA_PRODUCT_CLU518 0x360B -#define YUGA_PRODUCT_CLU516 0x360C -#define YUGA_PRODUCT_CLU528 0x360D -#define YUGA_PRODUCT_CLU526 0x360F + +#define YUGA_PRODUCT_CLM600 0x2601 +#define YUGA_PRODUCT_CLM610 0x2602 +#define YUGA_PRODUCT_CLM500 0x2603 +#define YUGA_PRODUCT_CLM510 0x2604 +#define YUGA_PRODUCT_CLM800 0x2605 +#define YUGA_PRODUCT_CLM900 0x2606 + +#define YUGA_PRODUCT_CLU718 0x2607 +#define YUGA_PRODUCT_CLU716 0x2608 +#define YUGA_PRODUCT_CLU728 0x2609 +#define YUGA_PRODUCT_CLU726 0x260A +#define YUGA_PRODUCT_CLU518 0x260B +#define YUGA_PRODUCT_CLU516 0x260C +#define YUGA_PRODUCT_CLU528 0x260D +#define YUGA_PRODUCT_CLU526 0x260F /* Viettel products */ #define VIETTEL_VENDOR_ID 0x2262 @@ -673,11 +666,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, @@ -1221,11 +1209,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) }, { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) }, { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, - { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU881) }, - { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU882) }, - { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU581) }, - { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU582) }, - { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU583) }, { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ @@ -1262,7 +1245,7 @@ static struct usb_serial_driver option_1port_device = { .ioctl = usb_wwan_ioctl, .attach = usb_wwan_startup, .disconnect = usb_wwan_disconnect, - .release = option_release, + .release = usb_wwan_release, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, @@ -1276,6 +1259,35 @@ static struct usb_serial_driver * const serial_drivers[] = { static bool debug; +/* per port private data */ + +#define N_IN_URB 4 +#define N_OUT_URB 4 +#define IN_BUFLEN 4096 +#define OUT_BUFLEN 4096 + +struct option_port_private { + /* Input endpoints and buffer for this port */ + struct urb *in_urbs[N_IN_URB]; + u8 *in_buffer[N_IN_URB]; + /* Output endpoints and buffer for this port */ + struct urb *out_urbs[N_OUT_URB]; + u8 *out_buffer[N_OUT_URB]; + unsigned long out_busy; /* Bit vector of URBs in use */ + int opened; + struct usb_anchor delayed; + + /* Settings for the port */ + int rts_state; /* Handshaking pins (outputs) */ + int dtr_state; + int cts_state; /* Handshaking pins (inputs) */ + int dsr_state; + int dcd_state; + int ri_state; + + unsigned long tx_start_time[N_OUT_URB]; +}; + module_usb_serial_driver(serial_drivers, option_ids); static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, @@ -1344,22 +1356,12 @@ static int option_probe(struct usb_serial *serial, return 0; } -static void option_release(struct usb_serial *serial) -{ - struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); - - usb_wwan_release(serial); - - kfree(priv); -} - static void option_instat_callback(struct urb *urb) { int err; int status = urb->status; struct usb_serial_port *port = urb->context; - struct usb_wwan_port_private *portdata = - usb_get_serial_port_data(port); + struct option_port_private *portdata = usb_get_serial_port_data(port); dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); @@ -1419,7 +1421,7 @@ static int option_send_setup(struct usb_serial_port *port) struct usb_serial *serial = port->serial; struct usb_wwan_intf_private *intfdata = (struct usb_wwan_intf_private *) serial->private; - struct usb_wwan_port_private *portdata; + struct option_port_private *portdata; int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; int val = 0; diff --git a/trunk/drivers/usb/serial/qcserial.c b/trunk/drivers/usb/serial/qcserial.c index 996015c5f1ac..0d5fe59ebb9e 100644 --- a/trunk/drivers/usb/serial/qcserial.c +++ b/trunk/drivers/usb/serial/qcserial.c @@ -105,13 +105,7 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */ {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */ {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */ - {USB_DEVICE(0x1199, 0x9010)}, /* Sierra Wireless Gobi 3000 QDL */ - {USB_DEVICE(0x1199, 0x9012)}, /* Sierra Wireless Gobi 3000 QDL */ {USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ - {USB_DEVICE(0x1199, 0x9014)}, /* Sierra Wireless Gobi 3000 QDL */ - {USB_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ - {USB_DEVICE(0x1199, 0x9018)}, /* Sierra Wireless Gobi 3000 QDL */ - {USB_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */ {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */ { } /* Terminating entry */ diff --git a/trunk/drivers/usb/serial/sierra.c b/trunk/drivers/usb/serial/sierra.c index d423d36acc04..ba54a0a8235c 100644 --- a/trunk/drivers/usb/serial/sierra.c +++ b/trunk/drivers/usb/serial/sierra.c @@ -294,10 +294,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, - /* AT&T Direct IP LTE modems */ - { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), - .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist - }, { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, diff --git a/trunk/drivers/usb/serial/usb-serial.c b/trunk/drivers/usb/serial/usb-serial.c index 27483f91a4a3..6a1b609a0d94 100644 --- a/trunk/drivers/usb/serial/usb-serial.c +++ b/trunk/drivers/usb/serial/usb-serial.c @@ -659,14 +659,12 @@ static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv, static struct usb_serial_driver *search_serial_device( struct usb_interface *iface) { - const struct usb_device_id *id = NULL; + const struct usb_device_id *id; struct usb_serial_driver *drv; - struct usb_driver *driver = to_usb_driver(iface->dev.driver); /* Check if the usb id matches a known device */ list_for_each_entry(drv, &usb_serial_driver_list, driver_list) { - if (drv->usb_driver == driver) - id = get_iface_id(drv, iface); + id = get_iface_id(drv, iface); if (id) return drv; } @@ -757,7 +755,7 @@ static int usb_serial_probe(struct usb_interface *interface, if (retval) { dbg("sub driver rejected device"); - usb_serial_put(serial); + kfree(serial); module_put(type->driver.owner); return retval; } @@ -829,7 +827,7 @@ static int usb_serial_probe(struct usb_interface *interface, */ if (num_bulk_in == 0 || num_bulk_out == 0) { dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); - usb_serial_put(serial); + kfree(serial); module_put(type->driver.owner); return -ENODEV; } @@ -843,7 +841,7 @@ static int usb_serial_probe(struct usb_interface *interface, if (num_ports == 0) { dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); - usb_serial_put(serial); + kfree(serial); module_put(type->driver.owner); return -EIO; } diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index caf22bf5f822..1719886bb9be 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -1107,13 +1107,6 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, USB_SC_RBC, USB_PR_BULK, NULL, 0 ), -/* Feiya QDI U2 DISK, reported by Hans de Goede */ -UNUSUAL_DEV( 0x090c, 0x1000, 0x0000, 0xffff, - "Feiya", - "QDI U2 DISK", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_NO_READ_CAPACITY_16 ), - /* aeb */ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, "Feiya", diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 0217f7415ef5..a290be51a1f4 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -2210,7 +2210,7 @@ config FB_XILINX config FB_COBALT tristate "Cobalt server LCD frame buffer support" - depends on FB && (MIPS_COBALT || MIPS_SEAD3) + depends on FB && MIPS_COBALT config FB_SH7760 bool "SH7760/SH7763/SH7720/SH7721 LCDC support" @@ -2382,39 +2382,6 @@ config FB_BROADSHEET and could also have been called by other names when coupled with a bridge adapter. -config FB_AUO_K190X - tristate "AUO-K190X EPD controller support" - depends on FB - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - help - Provides support for epaper controllers from the K190X series - of AUO. These controllers can be used to drive epaper displays - from Sipix. - - This option enables the common support, shared by the individual - controller drivers. You will also have to enable the driver - for the controller type used in your device. - -config FB_AUO_K1900 - tristate "AUO-K1900 EPD controller support" - depends on FB && FB_AUO_K190X - help - This driver implements support for the AUO K1900 epd-controller. - This controller can drive Sipix epaper displays but can only do - serial updates, reducing the number of possible frames per second. - -config FB_AUO_K1901 - tristate "AUO-K1901 EPD controller support" - depends on FB && FB_AUO_K190X - help - This driver implements support for the AUO K1901 epd-controller. - This controller can drive Sipix epaper displays and supports - concurrent updates, making higher frames per second possible. - config FB_JZ4740 tristate "JZ4740 LCD framebuffer support" depends on FB && MACH_JZ4740 diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index ee8dafb69e36..9356add945b3 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -118,9 +118,6 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o obj-$(CONFIG_FB_MAXINE) += maxinefb.o obj-$(CONFIG_FB_METRONOME) += metronomefb.o obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o -obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o -obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o -obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o obj-$(CONFIG_FB_SH7760) += sh7760fb.o obj-$(CONFIG_FB_IMX) += imxfb.o diff --git a/trunk/drivers/video/auo_k1900fb.c b/trunk/drivers/video/auo_k1900fb.c deleted file mode 100644 index c36cf961dcb2..000000000000 --- a/trunk/drivers/video/auo_k1900fb.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * auok190xfb.c -- FB driver for AUO-K1900 controllers - * - * Copyright (C) 2011, 2012 Heiko Stuebner - * - * based on broadsheetfb.c - * - * Copyright (C) 2008, Jaya Kumar - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. - * - * This driver is written to be used with the AUO-K1900 display controller. - * - * It is intended to be architecture independent. A board specific driver - * must be used to perform all the physical IO interactions. - * - * The controller supports different update modes: - * mode0+1 16 step gray (4bit) - * mode2 4 step gray (2bit) - FIXME: add strange refresh - * mode3 2 step gray (1bit) - FIXME: add strange refresh - * mode4 handwriting mode (strange behaviour) - * mode5 automatic selection of update mode - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include