diff --git a/[refs] b/[refs] index c47a5fbb7616..178fd9f1d564 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f309532bf3e1cc1b787403d84e3039812a7dbe50 +refs/heads/master: 30dc0d0fe5d08396dbdaa2d70972149131340960 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/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/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/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/vm/slub.txt b/trunk/Documentation/vm/slub.txt index b0c6d1bbb434..6752870c4970 100644 --- a/trunk/Documentation/vm/slub.txt +++ b/trunk/Documentation/vm/slub.txt @@ -17,7 +17,7 @@ data and perform operation on the slabs. By default slabinfo only lists slabs that have data in them. See "slabinfo -h" for more options when running the command. slabinfo can be compiled with -gcc -o slabinfo tools/vm/slabinfo.c +gcc -o slabinfo tools/slub/slabinfo.c Some of the modes of operation of slabinfo require that slub debugging be enabled on the command line. F.e. no tracking information will be 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..f6db3032ddf0 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 */ } 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/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..63f327dd5198 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 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 54d49ddb9b81..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 = 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); -} - 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-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/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..5e6beb2597a8 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 | _TIF_NOTIFY_RESUME tst r1, r2 breq 2f unmask_interrupts diff --git a/trunk/arch/avr32/kernel/signal.c b/trunk/arch/avr32/kernel/signal.c index c140f9b41dce..e7595ef74f51 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,8 +315,8 @@ 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); 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< #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,7 +330,7 @@ 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)) { 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..9493f0bbf0a6 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,7 +357,8 @@ 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)) { 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/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..595bf1e5a5dc 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,7 +555,7 @@ 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 */ 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..e58992ad789e 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) diff --git a/trunk/arch/hexagon/kernel/signal.c b/trunk/arch/hexagon/kernel/signal.c index 304b0808d072..21a3018cb9bf 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) @@ -270,6 +301,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/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..64804f1f5141 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); + } } /* 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/kernel/signal.c b/trunk/arch/m68k/kernel/signal.c index 710a528b928b..973eec60cad4 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) 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..5d796e32786e 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; + + block_sigmask(ka, sig); - signal_delivered(sig, info, ka, regs, 0); + 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) 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..8a6e6d116ab0 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,7 +630,7 @@ 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) { 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..b8b6aa1a6837 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,7 +548,7 @@ 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) { diff --git a/trunk/arch/openrisc/kernel/signal.c b/trunk/arch/openrisc/kernel/signal.c index 30110297f4f9..9ae611522953 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; 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..c7fbc96472f3 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|_TIF_NOTIFY_RESUME), %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..e7a7cd3e1120 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,12 +621,18 @@ 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)) { 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/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/signal.c b/trunk/arch/powerpc/kernel/signal.c index 5c023c9cf16e..bfc3ec1382fb 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)); } 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/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..42a6e8b47f06 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,7 +484,10 @@ 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) diff --git a/trunk/arch/score/kernel/signal.c b/trunk/arch/score/kernel/signal.c index e382c52ca0d9..302838d3acf6 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); + } } /* 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/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/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/kernel/signal_32.c b/trunk/arch/sh/kernel/signal_32.c index d6b7b6154f87..9d7bfd66f189 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, diff --git a/trunk/arch/sh/kernel/signal_64.c b/trunk/arch/sh/kernel/signal_64.c index 6b5b3dfe886b..aa6428430842 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) 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..6b42e8622d12 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,13 +576,16 @@ 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); diff --git a/trunk/arch/sparc/kernel/signal_64.c b/trunk/arch/sparc/kernel/signal_64.c index 867de2f8189c..c82cf1cc3965 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) 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 7e1fef36bde6..656c486e64fa 100644 --- a/trunk/arch/tile/include/asm/thread_info.h +++ b/trunk/arch/tile/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, &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/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/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/unicore32/kernel/signal.c b/trunk/arch/unicore32/kernel/signal.c index 8adedb37720a..28782ad47b93 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, diff --git a/trunk/arch/x86/boot/compressed/eboot.c b/trunk/arch/x86/boot/compressed/eboot.c index 2c14e76bb4c7..52a4e667b258 100644 --- a/trunk/arch/x86/boot/compressed/eboot.c +++ b/trunk/arch/x86/boot/compressed/eboot.c @@ -674,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 < nr_initrds; k++) + for (k = j; k < i; k++) efi_call_phys1(fh->close, initrds[k].handle); free_initrds: efi_call_phys1(sys_table->boottime->free_pool, initrds); 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/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/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/signal.c b/trunk/arch/x86/kernel/signal.c index 21af737053aa..2e937a5ad531 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); + } } /* @@ -901,6 +934,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/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/xtensa/kernel/signal.c b/trunk/arch/xtensa/kernel/signal.c index b9f8e5850d3a..ea7e17778a75 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; 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/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/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/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/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/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 3df4efa11942..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: @@ -490,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; } @@ -510,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) @@ -519,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; @@ -532,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 @@ -560,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 45cfcea63507..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; } - return data; + 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 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); 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 85dac33e3cce..2e24022b389a 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -1848,11 +1848,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/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index 04ddc365a908..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); 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/ttm/ttm_bo.c b/trunk/drivers/gpu/drm/ttm/ttm_bo.c index b67cfcaa661f..36792bd4da77 100644 --- a/trunk/drivers/gpu/drm/ttm/ttm_bo.c +++ b/trunk/drivers/gpu/drm/ttm/ttm_bo.c @@ -1834,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/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/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/pinctrl/pinctrl-nomadik.c b/trunk/drivers/pinctrl/pinctrl-nomadik.c index b26395d16347..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 @@ -1689,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); /* @@ -1775,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/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/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/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/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/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..67feac9e6ebb 100644 --- a/trunk/drivers/tty/tty_mutex.c +++ b/trunk/drivers/tty/tty_mutex.c @@ -4,29 +4,70 @@ #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 */ + +enum { + TTY_MUTEX_NORMAL, + TTY_MUTEX_NESTED, +}; /* * Getting the big tty mutex. */ -void __lockfunc tty_lock(void) + +static void __lockfunc tty_lock_nested(struct tty_struct *tty, + unsigned int subclass) { - 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_nested(&tty->legacy_mutex, subclass); +} + +void __lockfunc tty_lock(struct tty_struct *tty) +{ + return tty_lock_nested(tty, TTY_MUTEX_NORMAL); } 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_nested(tty2, TTY_MUTEX_NESTED); + } else { + if (tty2 && tty2 != tty) + tty_lock(tty2); + tty_lock_nested(tty, TTY_MUTEX_NESTED); + } +} +EXPORT_SYMBOL(tty_lock_pair); + +void __lockfunc tty_unlock_pair(struct tty_struct *tty, + struct tty_struct *tty2) +{ + tty_unlock(tty); + if (tty2 && tty2 != tty) + tty_unlock(tty2); +} +EXPORT_SYMBOL(tty_unlock_pair); diff --git a/trunk/drivers/tty/tty_port.c b/trunk/drivers/tty/tty_port.c index 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/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