Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 6 Feb 2014 21:31:42 +0000 (13:31 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 6 Feb 2014 21:31:42 +0000 (13:31 -0800)
Pull drm fixes from Dave Airlie:
 "A few regression fixes already, one for my own stupidity, and mgag200
  typo fix, vmwgfx fixes and ttm regression fixes, and a radeon register
  checker update for older cards to handle geom shaders"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/radeon: allow geom rings to be setup on r600/r700 (v2)
  drm/mgag200,ast,cirrus: fix regression with drm_can_sleep conversion
  drm/ttm: Don't clear page metadata of imported sg pages
  drm/ttm: Fix TTM object open regression
  vmwgfx: Fix unitialized stack read in vmw_setup_otable_base
  drm/vmwgfx: Reemit context bindings when necessary v2
  drm/vmwgfx: Detect old user-space drivers and set up legacy emulation v2
  drm/vmwgfx: Emulate legacy shaders on guest-backed devices v2
  drm/vmwgfx: Fix legacy surface reference size copyback
  drm/vmwgfx: Fix SET_SHADER_CONST emulation on guest-backed devices
  drm/vmwgfx: Fix regression caused by "drm/ttm: make ttm reservation calls behave like reservation calls"
  drm/vmwgfx: Don't commit staged bindings if execbuf fails
  drm/mgag200: fix typo causing bw limits to be ignored on some chips

46 files changed:
Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt [new file with mode: 0644]
arch/ia64/include/asm/unistd.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/entry.S
arch/parisc/hpux/fs.c
arch/s390/crypto/aes_s390.c
arch/s390/crypto/des_s390.c
arch/x86/Kconfig.debug
arch/x86/include/asm/xen/page.h
arch/x86/xen/enlighten.c
arch/x86/xen/p2m.c
drivers/block/nvme-core.c
drivers/block/nvme-scsi.c
drivers/block/xen-blkback/blkback.c
drivers/irqchip/Makefile
drivers/irqchip/irq-armada-370-xp.c
drivers/irqchip/irq-zevio.c [new file with mode: 0644]
drivers/regulator/ab3100.c
drivers/regulator/core.c
drivers/regulator/s2mps11.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
fs/btrfs/check-integrity.c
fs/btrfs/disk-io.c
fs/btrfs/inode.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/exec.c
fs/namei.c
fs/nfs/nfs3acl.c
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4session.c
fs/nfs/nfs4session.h
fs/posix_acl.c
include/linux/binfmts.h
include/linux/fs.h
include/linux/nfs_xdr.h
include/linux/nvme.h
include/linux/sched.h
include/uapi/linux/nvme.h
include/xen/grant_table.h
init/main.c
kernel/auditsc.c
kernel/kmod.c
lib/Kconfig.debug

diff --git a/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt
new file mode 100644 (file)
index 0000000..aee38e7
--- /dev/null
@@ -0,0 +1,18 @@
+TI-NSPIRE interrupt controller
+
+Required properties:
+- compatible: Compatible property value should be "lsi,zevio-intc".
+
+- reg: Physical base address of the controller and length of memory mapped
+       region.
+
+- interrupt-controller : Identifies the node as an interrupt controller
+
+Example:
+
+interrupt-controller {
+       compatible = "lsi,zevio-intc";
+       interrupt-controller;
+       reg = <0xDC000000 0x1000>;
+       #interrupt-cells = <1>;
+};
index afd45e0..ae763d8 100644 (file)
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls                    312 /* length of syscall table */
+#define NR_syscalls                    314 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
index 34fd6fe..715e85f 100644 (file)
 #define __NR_process_vm_writev         1333
 #define __NR_accept4                   1334
 #define __NR_finit_module              1335
+#define __NR_sched_setattr             1336
+#define __NR_sched_getattr             1337
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
index ddea607..fa8d61a 100644 (file)
@@ -1773,6 +1773,8 @@ sys_call_table:
        data8 sys_process_vm_writev
        data8 sys_accept4
        data8 sys_finit_module                  // 1335
+       data8 sys_sched_setattr
+       data8 sys_sched_getattr
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
index 88d0962..2bedafe 100644 (file)
 
 int hpux_execve(struct pt_regs *regs)
 {
-       int error;
-       struct filename *filename;
-
-       filename = getname((const char __user *) regs->gr[26]);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-
-       error = do_execve(filename->name,
+       return  do_execve(getname((const char __user *) regs->gr[26]),
                          (const char __user *const __user *) regs->gr[25],
                          (const char __user *const __user *) regs->gr[24]);
-
-       putname(filename);
-
-out:
-       return error;
 }
 
 struct hpux_dirent {
index b3feabd..cf3c008 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/spinlock.h>
 #include "crypt_s390.h"
 
 #define AES_KEYLEN_128         1
@@ -32,6 +33,7 @@
 #define AES_KEYLEN_256         4
 
 static u8 *ctrblk;
+static DEFINE_SPINLOCK(ctrblk_lock);
 static char keylen_flag;
 
 struct s390_aes_ctx {
@@ -758,43 +760,67 @@ static int ctr_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
        return aes_set_key(tfm, in_key, key_len);
 }
 
+static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
+{
+       unsigned int i, n;
+
+       /* only use complete blocks, max. PAGE_SIZE */
+       n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(AES_BLOCK_SIZE - 1);
+       for (i = AES_BLOCK_SIZE; i < n; i += AES_BLOCK_SIZE) {
+               memcpy(ctrptr + i, ctrptr + i - AES_BLOCK_SIZE,
+                      AES_BLOCK_SIZE);
+               crypto_inc(ctrptr + i, AES_BLOCK_SIZE);
+       }
+       return n;
+}
+
 static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
                         struct s390_aes_ctx *sctx, struct blkcipher_walk *walk)
 {
        int ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE);
-       unsigned int i, n, nbytes;
-       u8 buf[AES_BLOCK_SIZE];
-       u8 *out, *in;
+       unsigned int n, nbytes;
+       u8 buf[AES_BLOCK_SIZE], ctrbuf[AES_BLOCK_SIZE];
+       u8 *out, *in, *ctrptr = ctrbuf;
 
        if (!walk->nbytes)
                return ret;
 
-       memcpy(ctrblk, walk->iv, AES_BLOCK_SIZE);
+       if (spin_trylock(&ctrblk_lock))
+               ctrptr = ctrblk;
+
+       memcpy(ctrptr, walk->iv, AES_BLOCK_SIZE);
        while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
                while (nbytes >= AES_BLOCK_SIZE) {
-                       /* only use complete blocks, max. PAGE_SIZE */
-                       n = (nbytes > PAGE_SIZE) ? PAGE_SIZE :
-                                                nbytes & ~(AES_BLOCK_SIZE - 1);
-                       for (i = AES_BLOCK_SIZE; i < n; i += AES_BLOCK_SIZE) {
-                               memcpy(ctrblk + i, ctrblk + i - AES_BLOCK_SIZE,
-                                      AES_BLOCK_SIZE);
-                               crypto_inc(ctrblk + i, AES_BLOCK_SIZE);
-                       }
-                       ret = crypt_s390_kmctr(func, sctx->key, out, in, n, ctrblk);
-                       if (ret < 0 || ret != n)
+                       if (ctrptr == ctrblk)
+                               n = __ctrblk_init(ctrptr, nbytes);
+                       else
+                               n = AES_BLOCK_SIZE;
+                       ret = crypt_s390_kmctr(func, sctx->key, out, in,
+                                              n, ctrptr);
+                       if (ret < 0 || ret != n) {
+                               if (ctrptr == ctrblk)
+                                       spin_unlock(&ctrblk_lock);
                                return -EIO;
+                       }
                        if (n > AES_BLOCK_SIZE)
-                               memcpy(ctrblk, ctrblk + n - AES_BLOCK_SIZE,
+                               memcpy(ctrptr, ctrptr + n - AES_BLOCK_SIZE,
                                       AES_BLOCK_SIZE);
-                       crypto_inc(ctrblk, AES_BLOCK_SIZE);
+                       crypto_inc(ctrptr, AES_BLOCK_SIZE);
                        out += n;
                        in += n;
                        nbytes -= n;
                }
                ret = blkcipher_walk_done(desc, walk, nbytes);
        }
+       if (ctrptr == ctrblk) {
+               if (nbytes)
+                       memcpy(ctrbuf, ctrptr, AES_BLOCK_SIZE);
+               else
+                       memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE);
+               spin_unlock(&ctrblk_lock);
+       }
        /*
         * final block may be < AES_BLOCK_SIZE, copy only nbytes
         */
@@ -802,14 +828,15 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
                ret = crypt_s390_kmctr(func, sctx->key, buf, in,
-                                      AES_BLOCK_SIZE, ctrblk);
+                                      AES_BLOCK_SIZE, ctrbuf);
                if (ret < 0 || ret != AES_BLOCK_SIZE)
                        return -EIO;
                memcpy(out, buf, nbytes);
-               crypto_inc(ctrblk, AES_BLOCK_SIZE);
+               crypto_inc(ctrbuf, AES_BLOCK_SIZE);
                ret = blkcipher_walk_done(desc, walk, 0);
+               memcpy(walk->iv, ctrbuf, AES_BLOCK_SIZE);
        }
-       memcpy(walk->iv, ctrblk, AES_BLOCK_SIZE);
+
        return ret;
 }
 
index 200f2a1..0a5aac8 100644 (file)
@@ -25,6 +25,7 @@
 #define DES3_KEY_SIZE  (3 * DES_KEY_SIZE)
 
 static u8 *ctrblk;
+static DEFINE_SPINLOCK(ctrblk_lock);
 
 struct s390_des_ctx {
        u8 iv[DES_BLOCK_SIZE];
@@ -105,29 +106,35 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
 }
 
 static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
-                           u8 *iv, struct blkcipher_walk *walk)
+                           struct blkcipher_walk *walk)
 {
+       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        int ret = blkcipher_walk_virt(desc, walk);
        unsigned int nbytes = walk->nbytes;
+       struct {
+               u8 iv[DES_BLOCK_SIZE];
+               u8 key[DES3_KEY_SIZE];
+       } param;
 
        if (!nbytes)
                goto out;
 
-       memcpy(iv, walk->iv, DES_BLOCK_SIZE);
+       memcpy(param.iv, walk->iv, DES_BLOCK_SIZE);
+       memcpy(param.key, ctx->key, DES3_KEY_SIZE);
        do {
                /* only use complete blocks */
                unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
                u8 *out = walk->dst.virt.addr;
                u8 *in = walk->src.virt.addr;
 
-               ret = crypt_s390_kmc(func, iv, out, in, n);
+               ret = crypt_s390_kmc(func, &param, out, in, n);
                if (ret < 0 || ret != n)
                        return -EIO;
 
                nbytes &= DES_BLOCK_SIZE - 1;
                ret = blkcipher_walk_done(desc, walk, nbytes);
        } while ((nbytes = walk->nbytes));
-       memcpy(walk->iv, iv, DES_BLOCK_SIZE);
+       memcpy(walk->iv, param.iv, DES_BLOCK_SIZE);
 
 out:
        return ret;
@@ -179,22 +186,20 @@ static int cbc_des_encrypt(struct blkcipher_desc *desc,
                           struct scatterlist *dst, struct scatterlist *src,
                           unsigned int nbytes)
 {
-       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        struct blkcipher_walk walk;
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, ctx->iv, &walk);
+       return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, &walk);
 }
 
 static int cbc_des_decrypt(struct blkcipher_desc *desc,
                           struct scatterlist *dst, struct scatterlist *src,
                           unsigned int nbytes)
 {
-       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        struct blkcipher_walk walk;
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, ctx->iv, &walk);
+       return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, &walk);
 }
 
 static struct crypto_alg cbc_des_alg = {
@@ -327,22 +332,20 @@ static int cbc_des3_encrypt(struct blkcipher_desc *desc,
                            struct scatterlist *dst, struct scatterlist *src,
                            unsigned int nbytes)
 {
-       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        struct blkcipher_walk walk;
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, ctx->iv, &walk);
+       return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, &walk);
 }
 
 static int cbc_des3_decrypt(struct blkcipher_desc *desc,
                            struct scatterlist *dst, struct scatterlist *src,
                            unsigned int nbytes)
 {
-       struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
        struct blkcipher_walk walk;
 
        blkcipher_walk_init(&walk, dst, src, nbytes);
-       return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, ctx->iv, &walk);
+       return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, &walk);
 }
 
 static struct crypto_alg cbc_des3_alg = {
@@ -366,54 +369,80 @@ static struct crypto_alg cbc_des3_alg = {
        }
 };
 
+static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
+{
+       unsigned int i, n;
+
+       /* align to block size, max. PAGE_SIZE */
+       n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1);
+       for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
+               memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+               crypto_inc(ctrptr + i, DES_BLOCK_SIZE);
+       }
+       return n;
+}
+
 static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
-                           struct s390_des_ctx *ctx, struct blkcipher_walk *walk)
+                           struct s390_des_ctx *ctx,
+                           struct blkcipher_walk *walk)
 {
        int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
-       unsigned int i, n, nbytes;
-       u8 buf[DES_BLOCK_SIZE];
-       u8 *out, *in;
+       unsigned int n, nbytes;
+       u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE];
+       u8 *out, *in, *ctrptr = ctrbuf;
+
+       if (!walk->nbytes)
+               return ret;
 
-       memcpy(ctrblk, walk->iv, DES_BLOCK_SIZE);
+       if (spin_trylock(&ctrblk_lock))
+               ctrptr = ctrblk;
+
+       memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE);
        while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
                while (nbytes >= DES_BLOCK_SIZE) {
-                       /* align to block size, max. PAGE_SIZE */
-                       n = (nbytes > PAGE_SIZE) ? PAGE_SIZE :
-                               nbytes & ~(DES_BLOCK_SIZE - 1);
-                       for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
-                               memcpy(ctrblk + i, ctrblk + i - DES_BLOCK_SIZE,
-                                      DES_BLOCK_SIZE);
-                               crypto_inc(ctrblk + i, DES_BLOCK_SIZE);
-                       }
-                       ret = crypt_s390_kmctr(func, ctx->key, out, in, n, ctrblk);
-                       if (ret < 0 || ret != n)
+                       if (ctrptr == ctrblk)
+                               n = __ctrblk_init(ctrptr, nbytes);
+                       else
+                               n = DES_BLOCK_SIZE;
+                       ret = crypt_s390_kmctr(func, ctx->key, out, in,
+                                              n, ctrptr);
+                       if (ret < 0 || ret != n) {
+                               if (ctrptr == ctrblk)
+                                       spin_unlock(&ctrblk_lock);
                                return -EIO;
+                       }
                        if (n > DES_BLOCK_SIZE)
-                               memcpy(ctrblk, ctrblk + n - DES_BLOCK_SIZE,
+                               memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE,
                                       DES_BLOCK_SIZE);
-                       crypto_inc(ctrblk, DES_BLOCK_SIZE);
+                       crypto_inc(ctrptr, DES_BLOCK_SIZE);
                        out += n;
                        in += n;
                        nbytes -= n;
                }
                ret = blkcipher_walk_done(desc, walk, nbytes);
        }
-
+       if (ctrptr == ctrblk) {
+               if (nbytes)
+                       memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE);
+               else
+                       memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
+               spin_unlock(&ctrblk_lock);
+       }
        /* final block may be < DES_BLOCK_SIZE, copy only nbytes */
        if (nbytes) {
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
                ret = crypt_s390_kmctr(func, ctx->key, buf, in,
-                                      DES_BLOCK_SIZE, ctrblk);
+                                      DES_BLOCK_SIZE, ctrbuf);
                if (ret < 0 || ret != DES_BLOCK_SIZE)
                        return -EIO;
                memcpy(out, buf, nbytes);
-               crypto_inc(ctrblk, DES_BLOCK_SIZE);
+               crypto_inc(ctrbuf, DES_BLOCK_SIZE);
                ret = blkcipher_walk_done(desc, walk, 0);
+               memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE);
        }
-       memcpy(walk->iv, ctrblk, DES_BLOCK_SIZE);
        return ret;
 }
 
index 0f3621e..321a52c 100644 (file)
@@ -184,6 +184,7 @@ config HAVE_MMIOTRACE_SUPPORT
 config X86_DECODER_SELFTEST
        bool "x86 instruction decoder selftest"
        depends on DEBUG_KERNEL && KPROBES
+       depends on !COMPILE_TEST
        ---help---
         Perform x86 instruction decoder selftests at build time.
         This option is useful for checking the sanity of x86 instruction
index 787e1bb..3e276eb 100644 (file)
@@ -52,8 +52,7 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s,
 extern int m2p_add_override(unsigned long mfn, struct page *page,
                            struct gnttab_map_grant_ref *kmap_op);
 extern int m2p_remove_override(struct page *page,
-                              struct gnttab_map_grant_ref *kmap_op,
-                              unsigned long mfn);
+                               struct gnttab_map_grant_ref *kmap_op);
 extern struct page *m2p_find_override(unsigned long mfn);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
@@ -122,7 +121,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
                pfn = m2p_find_override_pfn(mfn, ~0);
        }
 
-       /*
+       /* 
         * pfn is ~0 if there are no entries in the m2p for mfn or if the
         * entry doesn't map back to the mfn and m2p_override doesn't have a
         * valid entry for it.
index a4d7b64..201d09a 100644 (file)
@@ -1473,6 +1473,18 @@ static void xen_pvh_set_cr_flags(int cpu)
         * X86_CR0_TS, X86_CR0_PE, X86_CR0_ET are set by Xen for HVM guests
         * (which PVH shared codepaths), while X86_CR0_PG is for PVH. */
        write_cr0(read_cr0() | X86_CR0_MP | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM);
+
+       if (!cpu)
+               return;
+       /*
+        * For BSP, PSE PGE are set in probe_page_size_mask(), for APs
+        * set them here. For all, OSFXSR OSXMMEXCPT are set in fpu_init.
+       */
+       if (cpu_has_pse)
+               set_in_cr4(X86_CR4_PSE);
+
+       if (cpu_has_pge)
+               set_in_cr4(X86_CR4_PGE);
 }
 
 /*
index 8009acb..696c694 100644 (file)
@@ -899,6 +899,13 @@ int m2p_add_override(unsigned long mfn, struct page *page,
                                        "m2p_add_override: pfn %lx not mapped", pfn))
                        return -EINVAL;
        }
+       WARN_ON(PagePrivate(page));
+       SetPagePrivate(page);
+       set_page_private(page, mfn);
+       page->index = pfn_to_mfn(pfn);
+
+       if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
+               return -ENOMEM;
 
        if (kmap_op != NULL) {
                if (!PageHighMem(page)) {
@@ -937,16 +944,19 @@ int m2p_add_override(unsigned long mfn, struct page *page,
 }
 EXPORT_SYMBOL_GPL(m2p_add_override);
 int m2p_remove_override(struct page *page,
-                       struct gnttab_map_grant_ref *kmap_op,
-                       unsigned long mfn)
+               struct gnttab_map_grant_ref *kmap_op)
 {
        unsigned long flags;
+       unsigned long mfn;
        unsigned long pfn;
        unsigned long uninitialized_var(address);
        unsigned level;
        pte_t *ptep = NULL;
 
        pfn = page_to_pfn(page);
+       mfn = get_phys_to_machine(pfn);
+       if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT))
+               return -EINVAL;
 
        if (!PageHighMem(page)) {
                address = (unsigned long)__va(pfn << PAGE_SHIFT);
@@ -960,7 +970,10 @@ int m2p_remove_override(struct page *page,
        spin_lock_irqsave(&m2p_override_lock, flags);
        list_del(&page->lru);
        spin_unlock_irqrestore(&m2p_override_lock, flags);
+       WARN_ON(!PagePrivate(page));
+       ClearPagePrivate(page);
 
+       set_phys_to_machine(pfn, page->index);
        if (kmap_op != NULL) {
                if (!PageHighMem(page)) {
                        struct multicall_space mcs;
index 1f14ac4..51824d1 100644 (file)
@@ -46,7 +46,6 @@
 #define NVME_Q_DEPTH 1024
 #define SQ_SIZE(depth)         (depth * sizeof(struct nvme_command))
 #define CQ_SIZE(depth)         (depth * sizeof(struct nvme_completion))
-#define NVME_MINORS 64
 #define ADMIN_TIMEOUT  (60 * HZ)
 
 static int nvme_major;
@@ -58,6 +57,17 @@ module_param(use_threaded_interrupts, int, 0);
 static DEFINE_SPINLOCK(dev_list_lock);
 static LIST_HEAD(dev_list);
 static struct task_struct *nvme_thread;
+static struct workqueue_struct *nvme_workq;
+
+static void nvme_reset_failed_dev(struct work_struct *ws);
+
+struct async_cmd_info {
+       struct kthread_work work;
+       struct kthread_worker *worker;
+       u32 result;
+       int status;
+       void *ctx;
+};
 
 /*
  * An NVM Express queue.  Each device has at least two (one for admin
@@ -66,6 +76,7 @@ static struct task_struct *nvme_thread;
 struct nvme_queue {
        struct device *q_dmadev;
        struct nvme_dev *dev;
+       char irqname[24];       /* nvme4294967295-65535\0 */
        spinlock_t q_lock;
        struct nvme_command *sq_cmds;
        volatile struct nvme_completion *cqes;
@@ -80,9 +91,11 @@ struct nvme_queue {
        u16 sq_head;
        u16 sq_tail;
        u16 cq_head;
+       u16 qid;
        u8 cq_phase;
        u8 cqe_seen;
        u8 q_suspended;
+       struct async_cmd_info cmdinfo;
        unsigned long cmdid_data[];
 };
 
@@ -97,6 +110,7 @@ static inline void _nvme_check_size(void)
        BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_features) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_format_cmd) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_abort_cmd) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_command) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096);
        BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096);
@@ -111,6 +125,7 @@ struct nvme_cmd_info {
        nvme_completion_fn fn;
        void *ctx;
        unsigned long timeout;
+       int aborted;
 };
 
 static struct nvme_cmd_info *nvme_cmd_info(struct nvme_queue *nvmeq)
@@ -154,6 +169,7 @@ static int alloc_cmdid(struct nvme_queue *nvmeq, void *ctx,
        info[cmdid].fn = handler;
        info[cmdid].ctx = ctx;
        info[cmdid].timeout = jiffies + timeout;
+       info[cmdid].aborted = 0;
        return cmdid;
 }
 
@@ -172,6 +188,7 @@ static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx,
 #define CMD_CTX_COMPLETED      (0x310 + CMD_CTX_BASE)
 #define CMD_CTX_INVALID                (0x314 + CMD_CTX_BASE)
 #define CMD_CTX_FLUSH          (0x318 + CMD_CTX_BASE)
+#define CMD_CTX_ABORT          (0x31C + CMD_CTX_BASE)
 
 static void special_completion(struct nvme_dev *dev, void *ctx,
                                                struct nvme_completion *cqe)
@@ -180,6 +197,10 @@ static void special_completion(struct nvme_dev *dev, void *ctx,
                return;
        if (ctx == CMD_CTX_FLUSH)
                return;
+       if (ctx == CMD_CTX_ABORT) {
+               ++dev->abort_limit;
+               return;
+       }
        if (ctx == CMD_CTX_COMPLETED) {
                dev_warn(&dev->pci_dev->dev,
                                "completed id %d twice on queue %d\n",
@@ -196,6 +217,15 @@ static void special_completion(struct nvme_dev *dev, void *ctx,
        dev_warn(&dev->pci_dev->dev, "Unknown special completion %p\n", ctx);
 }
 
+static void async_completion(struct nvme_dev *dev, void *ctx,
+                                               struct nvme_completion *cqe)
+{
+       struct async_cmd_info *cmdinfo = ctx;
+       cmdinfo->result = le32_to_cpup(&cqe->result);
+       cmdinfo->status = le16_to_cpup(&cqe->status) >> 1;
+       queue_kthread_work(cmdinfo->worker, &cmdinfo->work);
+}
+
 /*
  * Called with local interrupts disabled and the q_lock held.  May not sleep.
  */
@@ -693,7 +723,7 @@ static int nvme_process_cq(struct nvme_queue *nvmeq)
        if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
                return 0;
 
-       writel(head, nvmeq->q_db + (1 << nvmeq->dev->db_stride));
+       writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
        nvmeq->cq_head = head;
        nvmeq->cq_phase = phase;
 
@@ -804,12 +834,34 @@ int nvme_submit_sync_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd,
        return cmdinfo.status;
 }
 
+static int nvme_submit_async_cmd(struct nvme_queue *nvmeq,
+                       struct nvme_command *cmd,
+                       struct async_cmd_info *cmdinfo, unsigned timeout)
+{
+       int cmdid;
+
+       cmdid = alloc_cmdid_killable(nvmeq, cmdinfo, async_completion, timeout);
+       if (cmdid < 0)
+               return cmdid;
+       cmdinfo->status = -EINTR;
+       cmd->common.command_id = cmdid;
+       nvme_submit_cmd(nvmeq, cmd);
+       return 0;
+}
+
 int nvme_submit_admin_cmd(struct nvme_dev *dev, struct nvme_command *cmd,
                                                                u32 *result)
 {
        return nvme_submit_sync_cmd(dev->queues[0], cmd, result, ADMIN_TIMEOUT);
 }
 
+static int nvme_submit_admin_cmd_async(struct nvme_dev *dev,
+               struct nvme_command *cmd, struct async_cmd_info *cmdinfo)
+{
+       return nvme_submit_async_cmd(dev->queues[0], cmd, cmdinfo,
+                                                               ADMIN_TIMEOUT);
+}
+
 static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
 {
        int status;
@@ -919,6 +971,56 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
        return nvme_submit_admin_cmd(dev, &c, result);
 }
 
+/**
+ * nvme_abort_cmd - Attempt aborting a command
+ * @cmdid: Command id of a timed out IO
+ * @queue: The queue with timed out IO
+ *
+ * Schedule controller reset if the command was already aborted once before and
+ * still hasn't been returned to the driver, or if this is the admin queue.
+ */
+static void nvme_abort_cmd(int cmdid, struct nvme_queue *nvmeq)
+{
+       int a_cmdid;
+       struct nvme_command cmd;
+       struct nvme_dev *dev = nvmeq->dev;
+       struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+
+       if (!nvmeq->qid || info[cmdid].aborted) {
+               if (work_busy(&dev->reset_work))
+                       return;
+               list_del_init(&dev->node);
+               dev_warn(&dev->pci_dev->dev,
+                       "I/O %d QID %d timeout, reset controller\n", cmdid,
+                                                               nvmeq->qid);
+               PREPARE_WORK(&dev->reset_work, nvme_reset_failed_dev);
+               queue_work(nvme_workq, &dev->reset_work);
+               return;
+       }
+
+       if (!dev->abort_limit)
+               return;
+
+       a_cmdid = alloc_cmdid(dev->queues[0], CMD_CTX_ABORT, special_completion,
+                                                               ADMIN_TIMEOUT);
+       if (a_cmdid < 0)
+               return;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.abort.opcode = nvme_admin_abort_cmd;
+       cmd.abort.cid = cmdid;
+       cmd.abort.sqid = cpu_to_le16(nvmeq->qid);
+       cmd.abort.command_id = a_cmdid;
+
+       --dev->abort_limit;
+       info[cmdid].aborted = 1;
+       info[cmdid].timeout = jiffies + ADMIN_TIMEOUT;
+
+       dev_warn(nvmeq->q_dmadev, "Aborting I/O %d QID %d\n", cmdid,
+                                                       nvmeq->qid);
+       nvme_submit_cmd(dev->queues[0], &cmd);
+}
+
 /**
  * nvme_cancel_ios - Cancel outstanding I/Os
  * @queue: The queue to cancel I/Os on
@@ -942,7 +1044,12 @@ static void nvme_cancel_ios(struct nvme_queue *nvmeq, bool timeout)
                        continue;
                if (info[cmdid].ctx == CMD_CTX_CANCELLED)
                        continue;
-               dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid);
+               if (timeout && nvmeq->dev->initialized) {
+                       nvme_abort_cmd(cmdid, nvmeq);
+                       continue;
+               }
+               dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d QID %d\n", cmdid,
+                                                               nvmeq->qid);
                ctx = cancel_cmdid(nvmeq, cmdid, &fn);
                fn(nvmeq->dev, ctx, &cqe);
        }
@@ -964,26 +1071,31 @@ static void nvme_free_queue(struct nvme_queue *nvmeq)
        kfree(nvmeq);
 }
 
-static void nvme_free_queues(struct nvme_dev *dev)
+static void nvme_free_queues(struct nvme_dev *dev, int lowest)
 {
        int i;
 
-       for (i = dev->queue_count - 1; i >= 0; i--) {
+       for (i = dev->queue_count - 1; i >= lowest; i--) {
                nvme_free_queue(dev->queues[i]);
                dev->queue_count--;
                dev->queues[i] = NULL;
        }
 }
 
-static void nvme_disable_queue(struct nvme_dev *dev, int qid)
+/**
+ * nvme_suspend_queue - put queue into suspended state
+ * @nvmeq - queue to suspend
+ *
+ * Returns 1 if already suspended, 0 otherwise.
+ */
+static int nvme_suspend_queue(struct nvme_queue *nvmeq)
 {
-       struct nvme_queue *nvmeq = dev->queues[qid];
-       int vector = dev->entry[nvmeq->cq_vector].vector;
+       int vector = nvmeq->dev->entry[nvmeq->cq_vector].vector;
 
        spin_lock_irq(&nvmeq->q_lock);
        if (nvmeq->q_suspended) {
                spin_unlock_irq(&nvmeq->q_lock);
-               return;
+               return 1;
        }
        nvmeq->q_suspended = 1;
        spin_unlock_irq(&nvmeq->q_lock);
@@ -991,18 +1103,35 @@ static void nvme_disable_queue(struct nvme_dev *dev, int qid)
        irq_set_affinity_hint(vector, NULL);
        free_irq(vector, nvmeq);
 
-       /* Don't tell the adapter to delete the admin queue */
-       if (qid) {
-               adapter_delete_sq(dev, qid);
-               adapter_delete_cq(dev, qid);
-       }
+       return 0;
+}
 
+static void nvme_clear_queue(struct nvme_queue *nvmeq)
+{
        spin_lock_irq(&nvmeq->q_lock);
        nvme_process_cq(nvmeq);
        nvme_cancel_ios(nvmeq, false);
        spin_unlock_irq(&nvmeq->q_lock);
 }
 
+static void nvme_disable_queue(struct nvme_dev *dev, int qid)
+{
+       struct nvme_queue *nvmeq = dev->queues[qid];
+
+       if (!nvmeq)
+               return;
+       if (nvme_suspend_queue(nvmeq))
+               return;
+
+       /* Don't tell the adapter to delete the admin queue.
+        * Don't tell a removed adapter to delete IO queues. */
+       if (qid && readl(&dev->bar->csts) != -1) {
+               adapter_delete_sq(dev, qid);
+               adapter_delete_cq(dev, qid);
+       }
+       nvme_clear_queue(nvmeq);
+}
+
 static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
                                                        int depth, int vector)
 {
@@ -1025,15 +1154,18 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
 
        nvmeq->q_dmadev = dmadev;
        nvmeq->dev = dev;
+       snprintf(nvmeq->irqname, sizeof(nvmeq->irqname), "nvme%dq%d",
+                       dev->instance, qid);
        spin_lock_init(&nvmeq->q_lock);
        nvmeq->cq_head = 0;
        nvmeq->cq_phase = 1;
        init_waitqueue_head(&nvmeq->sq_full);
        init_waitqueue_entry(&nvmeq->sq_cong_wait, nvme_thread);
        bio_list_init(&nvmeq->sq_cong);
-       nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)];
+       nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
        nvmeq->q_depth = depth;
        nvmeq->cq_vector = vector;
+       nvmeq->qid = qid;
        nvmeq->q_suspended = 1;
        dev->queue_count++;
 
@@ -1052,11 +1184,10 @@ static int queue_request_irq(struct nvme_dev *dev, struct nvme_queue *nvmeq,
 {
        if (use_threaded_interrupts)
                return request_threaded_irq(dev->entry[nvmeq->cq_vector].vector,
-                                       nvme_irq_check, nvme_irq,
-                                       IRQF_DISABLED | IRQF_SHARED,
+                                       nvme_irq_check, nvme_irq, IRQF_SHARED,
                                        name, nvmeq);
        return request_irq(dev->entry[nvmeq->cq_vector].vector, nvme_irq,
-                               IRQF_DISABLED | IRQF_SHARED, name, nvmeq);
+                               IRQF_SHARED, name, nvmeq);
 }
 
 static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
@@ -1067,7 +1198,7 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
        nvmeq->sq_tail = 0;
        nvmeq->cq_head = 0;
        nvmeq->cq_phase = 1;
-       nvmeq->q_db = &dev->dbs[qid << (dev->db_stride + 1)];
+       nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
        memset(nvmeq->cmdid_data, 0, extra);
        memset((void *)nvmeq->cqes, 0, CQ_SIZE(nvmeq->q_depth));
        nvme_cancel_ios(nvmeq, false);
@@ -1087,13 +1218,13 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
        if (result < 0)
                goto release_cq;
 
-       result = queue_request_irq(dev, nvmeq, "nvme");
+       result = queue_request_irq(dev, nvmeq, nvmeq->irqname);
        if (result < 0)
                goto release_sq;
 
-       spin_lock(&nvmeq->q_lock);
+       spin_lock_irq(&nvmeq->q_lock);
        nvme_init_queue(nvmeq, qid);
-       spin_unlock(&nvmeq->q_lock);
+       spin_unlock_irq(&nvmeq->q_lock);
 
        return result;
 
@@ -1205,13 +1336,13 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
        if (result)
                return result;
 
-       result = queue_request_irq(dev, nvmeq, "nvme admin");
+       result = queue_request_irq(dev, nvmeq, nvmeq->irqname);
        if (result)
                return result;
 
-       spin_lock(&nvmeq->q_lock);
+       spin_lock_irq(&nvmeq->q_lock);
        nvme_init_queue(nvmeq, 0);
-       spin_unlock(&nvmeq->q_lock);
+       spin_unlock_irq(&nvmeq->q_lock);
        return result;
 }
 
@@ -1487,10 +1618,47 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
        }
 }
 
+#ifdef CONFIG_COMPAT
+static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode,
+                                       unsigned int cmd, unsigned long arg)
+{
+       struct nvme_ns *ns = bdev->bd_disk->private_data;
+
+       switch (cmd) {
+       case SG_IO:
+               return nvme_sg_io32(ns, arg);
+       }
+       return nvme_ioctl(bdev, mode, cmd, arg);
+}
+#else
+#define nvme_compat_ioctl      NULL
+#endif
+
+static int nvme_open(struct block_device *bdev, fmode_t mode)
+{
+       struct nvme_ns *ns = bdev->bd_disk->private_data;
+       struct nvme_dev *dev = ns->dev;
+
+       kref_get(&dev->kref);
+       return 0;
+}
+
+static void nvme_free_dev(struct kref *kref);
+
+static void nvme_release(struct gendisk *disk, fmode_t mode)
+{
+       struct nvme_ns *ns = disk->private_data;
+       struct nvme_dev *dev = ns->dev;
+
+       kref_put(&dev->kref, nvme_free_dev);
+}
+
 static const struct block_device_operations nvme_fops = {
        .owner          = THIS_MODULE,
        .ioctl          = nvme_ioctl,
-       .compat_ioctl   = nvme_ioctl,
+       .compat_ioctl   = nvme_compat_ioctl,
+       .open           = nvme_open,
+       .release        = nvme_release,
 };
 
 static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
@@ -1514,13 +1682,25 @@ static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
 
 static int nvme_kthread(void *data)
 {
-       struct nvme_dev *dev;
+       struct nvme_dev *dev, *next;
 
        while (!kthread_should_stop()) {
                set_current_state(TASK_INTERRUPTIBLE);
                spin_lock(&dev_list_lock);
-               list_for_each_entry(dev, &dev_list, node) {
+               list_for_each_entry_safe(dev, next, &dev_list, node) {
                        int i;
+                       if (readl(&dev->bar->csts) & NVME_CSTS_CFS &&
+                                                       dev->initialized) {
+                               if (work_busy(&dev->reset_work))
+                                       continue;
+                               list_del_init(&dev->node);
+                               dev_warn(&dev->pci_dev->dev,
+                                       "Failed status, reset controller\n");
+                               PREPARE_WORK(&dev->reset_work,
+                                                       nvme_reset_failed_dev);
+                               queue_work(nvme_workq, &dev->reset_work);
+                               continue;
+                       }
                        for (i = 0; i < dev->queue_count; i++) {
                                struct nvme_queue *nvmeq = dev->queues[i];
                                if (!nvmeq)
@@ -1541,33 +1721,6 @@ static int nvme_kthread(void *data)
        return 0;
 }
 
-static DEFINE_IDA(nvme_index_ida);
-
-static int nvme_get_ns_idx(void)
-{
-       int index, error;
-
-       do {
-               if (!ida_pre_get(&nvme_index_ida, GFP_KERNEL))
-                       return -1;
-
-               spin_lock(&dev_list_lock);
-               error = ida_get_new(&nvme_index_ida, &index);
-               spin_unlock(&dev_list_lock);
-       } while (error == -EAGAIN);
-
-       if (error)
-               index = -1;
-       return index;
-}
-
-static void nvme_put_ns_idx(int index)
-{
-       spin_lock(&dev_list_lock);
-       ida_remove(&nvme_index_ida, index);
-       spin_unlock(&dev_list_lock);
-}
-
 static void nvme_config_discard(struct nvme_ns *ns)
 {
        u32 logical_block_size = queue_logical_block_size(ns->queue);
@@ -1601,7 +1754,7 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
        ns->dev = dev;
        ns->queue->queuedata = ns;
 
-       disk = alloc_disk(NVME_MINORS);
+       disk = alloc_disk(0);
        if (!disk)
                goto out_free_queue;
        ns->ns_id = nsid;
@@ -1614,12 +1767,12 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
                blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
 
        disk->major = nvme_major;
-       disk->minors = NVME_MINORS;
-       disk->first_minor = NVME_MINORS * nvme_get_ns_idx();
+       disk->first_minor = 0;
        disk->fops = &nvme_fops;
        disk->private_data = ns;
        disk->queue = ns->queue;
        disk->driverfs_dev = &dev->pci_dev->dev;
+       disk->flags = GENHD_FL_EXT_DEVT;
        sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid);
        set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
 
@@ -1635,15 +1788,6 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
        return NULL;
 }
 
-static void nvme_ns_free(struct nvme_ns *ns)
-{
-       int index = ns->disk->first_minor / NVME_MINORS;
-       put_disk(ns->disk);
-       nvme_put_ns_idx(index);
-       blk_cleanup_queue(ns->queue);
-       kfree(ns);
-}
-
 static int set_queue_count(struct nvme_dev *dev, int count)
 {
        int status;
@@ -1659,11 +1803,12 @@ static int set_queue_count(struct nvme_dev *dev, int count)
 
 static size_t db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues)
 {
-       return 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3));
+       return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride);
 }
 
 static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
+       struct nvme_queue *adminq = dev->queues[0];
        struct pci_dev *pdev = dev->pci_dev;
        int result, cpu, i, vecs, nr_io_queues, size, q_depth;
 
@@ -1690,7 +1835,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        }
 
        /* Deregister the admin queue's interrupt */
-       free_irq(dev->entry[0].vector, dev->queues[0]);
+       free_irq(dev->entry[0].vector, adminq);
 
        vecs = nr_io_queues;
        for (i = 0; i < vecs; i++)
@@ -1728,9 +1873,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
         */
        nr_io_queues = vecs;
 
-       result = queue_request_irq(dev, dev->queues[0], "nvme admin");
+       result = queue_request_irq(dev, adminq, adminq->irqname);
        if (result) {
-               dev->queues[0]->q_suspended = 1;
+               adminq->q_suspended = 1;
                goto free_queues;
        }
 
@@ -1739,9 +1884,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        for (i = dev->queue_count - 1; i > nr_io_queues; i--) {
                struct nvme_queue *nvmeq = dev->queues[i];
 
-               spin_lock(&nvmeq->q_lock);
+               spin_lock_irq(&nvmeq->q_lock);
                nvme_cancel_ios(nvmeq, false);
-               spin_unlock(&nvmeq->q_lock);
+               spin_unlock_irq(&nvmeq->q_lock);
 
                nvme_free_queue(nvmeq);
                dev->queue_count--;
@@ -1782,7 +1927,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        return 0;
 
  free_queues:
-       nvme_free_queues(dev);
+       nvme_free_queues(dev, 1);
        return result;
 }
 
@@ -1794,6 +1939,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
  */
 static int nvme_dev_add(struct nvme_dev *dev)
 {
+       struct pci_dev *pdev = dev->pci_dev;
        int res;
        unsigned nn, i;
        struct nvme_ns *ns;
@@ -1803,8 +1949,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
        dma_addr_t dma_addr;
        int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
 
-       mem = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr,
-                                                               GFP_KERNEL);
+       mem = dma_alloc_coherent(&pdev->dev, 8192, &dma_addr, GFP_KERNEL);
        if (!mem)
                return -ENOMEM;
 
@@ -1817,13 +1962,14 @@ static int nvme_dev_add(struct nvme_dev *dev)
        ctrl = mem;
        nn = le32_to_cpup(&ctrl->nn);
        dev->oncs = le16_to_cpup(&ctrl->oncs);
+       dev->abort_limit = ctrl->acl + 1;
        memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
        memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
        memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
        if (ctrl->mdts)
                dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
-       if ((dev->pci_dev->vendor == PCI_VENDOR_ID_INTEL) &&
-                       (dev->pci_dev->device == 0x0953) && ctrl->vs[3])
+       if ((pdev->vendor == PCI_VENDOR_ID_INTEL) &&
+                       (pdev->device == 0x0953) && ctrl->vs[3])
                dev->stripe_size = 1 << (ctrl->vs[3] + shift);
 
        id_ns = mem;
@@ -1871,16 +2017,21 @@ static int nvme_dev_map(struct nvme_dev *dev)
            dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))
                goto disable;
 
-       pci_set_drvdata(pdev, dev);
        dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
        if (!dev->bar)
                goto disable;
-
-       dev->db_stride = NVME_CAP_STRIDE(readq(&dev->bar->cap));
+       if (readl(&dev->bar->csts) == -1) {
+               result = -ENODEV;
+               goto unmap;
+       }
+       dev->db_stride = 1 << NVME_CAP_STRIDE(readq(&dev->bar->cap));
        dev->dbs = ((void __iomem *)dev->bar) + 4096;
 
        return 0;
 
+ unmap:
+       iounmap(dev->bar);
+       dev->bar = NULL;
  disable:
        pci_release_regions(pdev);
  disable_pci:
@@ -1898,37 +2049,183 @@ static void nvme_dev_unmap(struct nvme_dev *dev)
        if (dev->bar) {
                iounmap(dev->bar);
                dev->bar = NULL;
+               pci_release_regions(dev->pci_dev);
        }
 
-       pci_release_regions(dev->pci_dev);
        if (pci_is_enabled(dev->pci_dev))
                pci_disable_device(dev->pci_dev);
 }
 
+struct nvme_delq_ctx {
+       struct task_struct *waiter;
+       struct kthread_worker *worker;
+       atomic_t refcount;
+};
+
+static void nvme_wait_dq(struct nvme_delq_ctx *dq, struct nvme_dev *dev)
+{
+       dq->waiter = current;
+       mb();
+
+       for (;;) {
+               set_current_state(TASK_KILLABLE);
+               if (!atomic_read(&dq->refcount))
+                       break;
+               if (!schedule_timeout(ADMIN_TIMEOUT) ||
+                                       fatal_signal_pending(current)) {
+                       set_current_state(TASK_RUNNING);
+
+                       nvme_disable_ctrl(dev, readq(&dev->bar->cap));
+                       nvme_disable_queue(dev, 0);
+
+                       send_sig(SIGKILL, dq->worker->task, 1);
+                       flush_kthread_worker(dq->worker);
+                       return;
+               }
+       }
+       set_current_state(TASK_RUNNING);
+}
+
+static void nvme_put_dq(struct nvme_delq_ctx *dq)
+{
+       atomic_dec(&dq->refcount);
+       if (dq->waiter)
+               wake_up_process(dq->waiter);
+}
+
+static struct nvme_delq_ctx *nvme_get_dq(struct nvme_delq_ctx *dq)
+{
+       atomic_inc(&dq->refcount);
+       return dq;
+}
+
+static void nvme_del_queue_end(struct nvme_queue *nvmeq)
+{
+       struct nvme_delq_ctx *dq = nvmeq->cmdinfo.ctx;
+
+       nvme_clear_queue(nvmeq);
+       nvme_put_dq(dq);
+}
+
+static int adapter_async_del_queue(struct nvme_queue *nvmeq, u8 opcode,
+                                               kthread_work_func_t fn)
+{
+       struct nvme_command c;
+
+       memset(&c, 0, sizeof(c));
+       c.delete_queue.opcode = opcode;
+       c.delete_queue.qid = cpu_to_le16(nvmeq->qid);
+
+       init_kthread_work(&nvmeq->cmdinfo.work, fn);
+       return nvme_submit_admin_cmd_async(nvmeq->dev, &c, &nvmeq->cmdinfo);
+}
+
+static void nvme_del_cq_work_handler(struct kthread_work *work)
+{
+       struct nvme_queue *nvmeq = container_of(work, struct nvme_queue,
+                                                       cmdinfo.work);
+       nvme_del_queue_end(nvmeq);
+}
+
+static int nvme_delete_cq(struct nvme_queue *nvmeq)
+{
+       return adapter_async_del_queue(nvmeq, nvme_admin_delete_cq,
+                                               nvme_del_cq_work_handler);
+}
+
+static void nvme_del_sq_work_handler(struct kthread_work *work)
+{
+       struct nvme_queue *nvmeq = container_of(work, struct nvme_queue,
+                                                       cmdinfo.work);
+       int status = nvmeq->cmdinfo.status;
+
+       if (!status)
+               status = nvme_delete_cq(nvmeq);
+       if (status)
+               nvme_del_queue_end(nvmeq);
+}
+
+static int nvme_delete_sq(struct nvme_queue *nvmeq)
+{
+       return adapter_async_del_queue(nvmeq, nvme_admin_delete_sq,
+                                               nvme_del_sq_work_handler);
+}
+
+static void nvme_del_queue_start(struct kthread_work *work)
+{
+       struct nvme_queue *nvmeq = container_of(work, struct nvme_queue,
+                                                       cmdinfo.work);
+       allow_signal(SIGKILL);
+       if (nvme_delete_sq(nvmeq))
+               nvme_del_queue_end(nvmeq);
+}
+
+static void nvme_disable_io_queues(struct nvme_dev *dev)
+{
+       int i;
+       DEFINE_KTHREAD_WORKER_ONSTACK(worker);
+       struct nvme_delq_ctx dq;
+       struct task_struct *kworker_task = kthread_run(kthread_worker_fn,
+                                       &worker, "nvme%d", dev->instance);
+
+       if (IS_ERR(kworker_task)) {
+               dev_err(&dev->pci_dev->dev,
+                       "Failed to create queue del task\n");
+               for (i = dev->queue_count - 1; i > 0; i--)
+                       nvme_disable_queue(dev, i);
+               return;
+       }
+
+       dq.waiter = NULL;
+       atomic_set(&dq.refcount, 0);
+       dq.worker = &worker;
+       for (i = dev->queue_count - 1; i > 0; i--) {
+               struct nvme_queue *nvmeq = dev->queues[i];
+
+               if (nvme_suspend_queue(nvmeq))
+                       continue;
+               nvmeq->cmdinfo.ctx = nvme_get_dq(&dq);
+               nvmeq->cmdinfo.worker = dq.worker;
+               init_kthread_work(&nvmeq->cmdinfo.work, nvme_del_queue_start);
+               queue_kthread_work(dq.worker, &nvmeq->cmdinfo.work);
+       }
+       nvme_wait_dq(&dq, dev);
+       kthread_stop(kworker_task);
+}
+
 static void nvme_dev_shutdown(struct nvme_dev *dev)
 {
        int i;
 
-       for (i = dev->queue_count - 1; i >= 0; i--)
-               nvme_disable_queue(dev, i);
+       dev->initialized = 0;
 
        spin_lock(&dev_list_lock);
        list_del_init(&dev->node);
        spin_unlock(&dev_list_lock);
 
-       if (dev->bar)
+       if (!dev->bar || (dev->bar && readl(&dev->bar->csts) == -1)) {
+               for (i = dev->queue_count - 1; i >= 0; i--) {
+                       struct nvme_queue *nvmeq = dev->queues[i];
+                       nvme_suspend_queue(nvmeq);
+                       nvme_clear_queue(nvmeq);
+               }
+       } else {
+               nvme_disable_io_queues(dev);
                nvme_shutdown_ctrl(dev);
+               nvme_disable_queue(dev, 0);
+       }
        nvme_dev_unmap(dev);
 }
 
 static void nvme_dev_remove(struct nvme_dev *dev)
 {
-       struct nvme_ns *ns, *next;
+       struct nvme_ns *ns;
 
-       list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
-               list_del(&ns->list);
-               del_gendisk(ns->disk);
-               nvme_ns_free(ns);
+       list_for_each_entry(ns, &dev->namespaces, list) {
+               if (ns->disk->flags & GENHD_FL_UP)
+                       del_gendisk(ns->disk);
+               if (!blk_queue_dying(ns->queue))
+                       blk_cleanup_queue(ns->queue);
        }
 }
 
@@ -1985,14 +2282,22 @@ static void nvme_release_instance(struct nvme_dev *dev)
        spin_unlock(&dev_list_lock);
 }
 
+static void nvme_free_namespaces(struct nvme_dev *dev)
+{
+       struct nvme_ns *ns, *next;
+
+       list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
+               list_del(&ns->list);
+               put_disk(ns->disk);
+               kfree(ns);
+       }
+}
+
 static void nvme_free_dev(struct kref *kref)
 {
        struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
-       nvme_dev_remove(dev);
-       nvme_dev_shutdown(dev);
-       nvme_free_queues(dev);
-       nvme_release_instance(dev);
-       nvme_release_prp_pools(dev);
+
+       nvme_free_namespaces(dev);
        kfree(dev->queues);
        kfree(dev->entry);
        kfree(dev);
@@ -2056,6 +2361,7 @@ static int nvme_dev_start(struct nvme_dev *dev)
        return result;
 
  disable:
+       nvme_disable_queue(dev, 0);
        spin_lock(&dev_list_lock);
        list_del_init(&dev->node);
        spin_unlock(&dev_list_lock);
@@ -2064,6 +2370,71 @@ static int nvme_dev_start(struct nvme_dev *dev)
        return result;
 }
 
+static int nvme_remove_dead_ctrl(void *arg)
+{
+       struct nvme_dev *dev = (struct nvme_dev *)arg;
+       struct pci_dev *pdev = dev->pci_dev;
+
+       if (pci_get_drvdata(pdev))
+               pci_stop_and_remove_bus_device(pdev);
+       kref_put(&dev->kref, nvme_free_dev);
+       return 0;
+}
+
+static void nvme_remove_disks(struct work_struct *ws)
+{
+       int i;
+       struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work);
+
+       nvme_dev_remove(dev);
+       spin_lock(&dev_list_lock);
+       for (i = dev->queue_count - 1; i > 0; i--) {
+               BUG_ON(!dev->queues[i] || !dev->queues[i]->q_suspended);
+               nvme_free_queue(dev->queues[i]);
+               dev->queue_count--;
+               dev->queues[i] = NULL;
+       }
+       spin_unlock(&dev_list_lock);
+}
+
+static int nvme_dev_resume(struct nvme_dev *dev)
+{
+       int ret;
+
+       ret = nvme_dev_start(dev);
+       if (ret && ret != -EBUSY)
+               return ret;
+       if (ret == -EBUSY) {
+               spin_lock(&dev_list_lock);
+               PREPARE_WORK(&dev->reset_work, nvme_remove_disks);
+               queue_work(nvme_workq, &dev->reset_work);
+               spin_unlock(&dev_list_lock);
+       }
+       dev->initialized = 1;
+       return 0;
+}
+
+static void nvme_dev_reset(struct nvme_dev *dev)
+{
+       nvme_dev_shutdown(dev);
+       if (nvme_dev_resume(dev)) {
+               dev_err(&dev->pci_dev->dev, "Device failed to resume\n");
+               kref_get(&dev->kref);
+               if (IS_ERR(kthread_run(nvme_remove_dead_ctrl, dev, "nvme%d",
+                                                       dev->instance))) {
+                       dev_err(&dev->pci_dev->dev,
+                               "Failed to start controller remove task\n");
+                       kref_put(&dev->kref, nvme_free_dev);
+               }
+       }
+}
+
+static void nvme_reset_failed_dev(struct work_struct *ws)
+{
+       struct nvme_dev *dev = container_of(ws, struct nvme_dev, reset_work);
+       nvme_dev_reset(dev);
+}
+
 static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int result = -ENOMEM;
@@ -2082,8 +2453,9 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto free;
 
        INIT_LIST_HEAD(&dev->namespaces);
+       INIT_WORK(&dev->reset_work, nvme_reset_failed_dev);
        dev->pci_dev = pdev;
-
+       pci_set_drvdata(pdev, dev);
        result = nvme_set_instance(dev);
        if (result)
                goto free;
@@ -2099,6 +2471,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto release_pools;
        }
 
+       kref_init(&dev->kref);
        result = nvme_dev_add(dev);
        if (result)
                goto shutdown;
@@ -2113,15 +2486,16 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (result)
                goto remove;
 
-       kref_init(&dev->kref);
+       dev->initialized = 1;
        return 0;
 
  remove:
        nvme_dev_remove(dev);
+       nvme_free_namespaces(dev);
  shutdown:
        nvme_dev_shutdown(dev);
  release_pools:
-       nvme_free_queues(dev);
+       nvme_free_queues(dev, 0);
        nvme_release_prp_pools(dev);
  release:
        nvme_release_instance(dev);
@@ -2132,10 +2506,28 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        return result;
 }
 
+static void nvme_shutdown(struct pci_dev *pdev)
+{
+       struct nvme_dev *dev = pci_get_drvdata(pdev);
+       nvme_dev_shutdown(dev);
+}
+
 static void nvme_remove(struct pci_dev *pdev)
 {
        struct nvme_dev *dev = pci_get_drvdata(pdev);
+
+       spin_lock(&dev_list_lock);
+       list_del_init(&dev->node);
+       spin_unlock(&dev_list_lock);
+
+       pci_set_drvdata(pdev, NULL);
+       flush_work(&dev->reset_work);
        misc_deregister(&dev->miscdev);
+       nvme_dev_remove(dev);
+       nvme_dev_shutdown(dev);
+       nvme_free_queues(dev, 0);
+       nvme_release_instance(dev);
+       nvme_release_prp_pools(dev);
        kref_put(&dev->kref, nvme_free_dev);
 }
 
@@ -2159,13 +2551,12 @@ static int nvme_resume(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct nvme_dev *ndev = pci_get_drvdata(pdev);
-       int ret;
 
-       ret = nvme_dev_start(ndev);
-       /* XXX: should remove gendisks if resume fails */
-       if (ret)
-               nvme_free_queues(ndev);
-       return ret;
+       if (nvme_dev_resume(ndev) && !work_busy(&ndev->reset_work)) {
+               PREPARE_WORK(&ndev->reset_work, nvme_reset_failed_dev);
+               queue_work(nvme_workq, &ndev->reset_work);
+       }
+       return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(nvme_dev_pm_ops, nvme_suspend, nvme_resume);
@@ -2192,6 +2583,7 @@ static struct pci_driver nvme_driver = {
        .id_table       = nvme_id_table,
        .probe          = nvme_probe,
        .remove         = nvme_remove,
+       .shutdown       = nvme_shutdown,
        .driver         = {
                .pm     = &nvme_dev_pm_ops,
        },
@@ -2206,9 +2598,14 @@ static int __init nvme_init(void)
        if (IS_ERR(nvme_thread))
                return PTR_ERR(nvme_thread);
 
+       result = -ENOMEM;
+       nvme_workq = create_singlethread_workqueue("nvme");
+       if (!nvme_workq)
+               goto kill_kthread;
+
        result = register_blkdev(nvme_major, "nvme");
        if (result < 0)
-               goto kill_kthread;
+               goto kill_workq;
        else if (result > 0)
                nvme_major = result;
 
@@ -2219,6 +2616,8 @@ static int __init nvme_init(void)
 
  unregister_blkdev:
        unregister_blkdev(nvme_major, "nvme");
+ kill_workq:
+       destroy_workqueue(nvme_workq);
  kill_kthread:
        kthread_stop(nvme_thread);
        return result;
@@ -2228,6 +2627,7 @@ static void __exit nvme_exit(void)
 {
        pci_unregister_driver(&nvme_driver);
        unregister_blkdev(nvme_major, "nvme");
+       destroy_workqueue(nvme_workq);
        kthread_stop(nvme_thread);
 }
 
index 4a4ff4e..4a0ceb6 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/bio.h>
 #include <linux/bitops.h>
 #include <linux/blkdev.h>
+#include <linux/compat.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -3038,6 +3039,152 @@ int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr)
        return retcode;
 }
 
+#ifdef CONFIG_COMPAT
+typedef struct sg_io_hdr32 {
+       compat_int_t interface_id;      /* [i] 'S' for SCSI generic (required) */
+       compat_int_t dxfer_direction;   /* [i] data transfer direction  */
+       unsigned char cmd_len;          /* [i] SCSI command length ( <= 16 bytes) */
+       unsigned char mx_sb_len;                /* [i] max length to write to sbp */
+       unsigned short iovec_count;     /* [i] 0 implies no scatter gather */
+       compat_uint_t dxfer_len;                /* [i] byte count of data transfer */
+       compat_uint_t dxferp;           /* [i], [*io] points to data transfer memory
+                                             or scatter gather list */
+       compat_uptr_t cmdp;             /* [i], [*i] points to command to perform */
+       compat_uptr_t sbp;              /* [i], [*o] points to sense_buffer memory */
+       compat_uint_t timeout;          /* [i] MAX_UINT->no timeout (unit: millisec) */
+       compat_uint_t flags;            /* [i] 0 -> default, see SG_FLAG... */
+       compat_int_t pack_id;           /* [i->o] unused internally (normally) */
+       compat_uptr_t usr_ptr;          /* [i->o] unused internally */
+       unsigned char status;           /* [o] scsi status */
+       unsigned char masked_status;    /* [o] shifted, masked scsi status */
+       unsigned char msg_status;               /* [o] messaging level data (optional) */
+       unsigned char sb_len_wr;                /* [o] byte count actually written to sbp */
+       unsigned short host_status;     /* [o] errors from host adapter */
+       unsigned short driver_status;   /* [o] errors from software driver */
+       compat_int_t resid;             /* [o] dxfer_len - actual_transferred */
+       compat_uint_t duration;         /* [o] time taken by cmd (unit: millisec) */
+       compat_uint_t info;             /* [o] auxiliary information */
+} sg_io_hdr32_t;  /* 64 bytes long (on sparc32) */
+
+typedef struct sg_iovec32 {
+       compat_uint_t iov_base;
+       compat_uint_t iov_len;
+} sg_iovec32_t;
+
+static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iovec_count)
+{
+       sg_iovec_t __user *iov = (sg_iovec_t __user *) (sgio + 1);
+       sg_iovec32_t __user *iov32 = dxferp;
+       int i;
+
+       for (i = 0; i < iovec_count; i++) {
+               u32 base, len;
+
+               if (get_user(base, &iov32[i].iov_base) ||
+                   get_user(len, &iov32[i].iov_len) ||
+                   put_user(compat_ptr(base), &iov[i].iov_base) ||
+                   put_user(len, &iov[i].iov_len))
+                       return -EFAULT;
+       }
+
+       if (put_user(iov, &sgio->dxferp))
+               return -EFAULT;
+       return 0;
+}
+
+int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg)
+{
+       sg_io_hdr32_t __user *sgio32 = (sg_io_hdr32_t __user *)arg;
+       sg_io_hdr_t __user *sgio;
+       u16 iovec_count;
+       u32 data;
+       void __user *dxferp;
+       int err;
+       int interface_id;
+
+       if (get_user(interface_id, &sgio32->interface_id))
+               return -EFAULT;
+       if (interface_id != 'S')
+               return -EINVAL;
+
+       if (get_user(iovec_count, &sgio32->iovec_count))
+               return -EFAULT;
+
+       {
+               void __user *top = compat_alloc_user_space(0);
+               void __user *new = compat_alloc_user_space(sizeof(sg_io_hdr_t) +
+                                      (iovec_count * sizeof(sg_iovec_t)));
+               if (new > top)
+                       return -EINVAL;
+
+               sgio = new;
+       }
+
+       /* Ok, now construct.  */
+       if (copy_in_user(&sgio->interface_id, &sgio32->interface_id,
+                        (2 * sizeof(int)) +
+                        (2 * sizeof(unsigned char)) +
+                        (1 * sizeof(unsigned short)) +
+                        (1 * sizeof(unsigned int))))
+               return -EFAULT;
+
+       if (get_user(data, &sgio32->dxferp))
+               return -EFAULT;
+       dxferp = compat_ptr(data);
+       if (iovec_count) {
+               if (sg_build_iovec(sgio, dxferp, iovec_count))
+                       return -EFAULT;
+       } else {
+               if (put_user(dxferp, &sgio->dxferp))
+                       return -EFAULT;
+       }
+
+       {
+               unsigned char __user *cmdp;
+               unsigned char __user *sbp;
+
+               if (get_user(data, &sgio32->cmdp))
+                       return -EFAULT;
+               cmdp = compat_ptr(data);
+
+               if (get_user(data, &sgio32->sbp))
+                       return -EFAULT;
+               sbp = compat_ptr(data);
+
+               if (put_user(cmdp, &sgio->cmdp) ||
+                   put_user(sbp, &sgio->sbp))
+                       return -EFAULT;
+       }
+
+       if (copy_in_user(&sgio->timeout, &sgio32->timeout,
+                        3 * sizeof(int)))
+               return -EFAULT;
+
+       if (get_user(data, &sgio32->usr_ptr))
+               return -EFAULT;
+       if (put_user(compat_ptr(data), &sgio->usr_ptr))
+               return -EFAULT;
+
+       err = nvme_sg_io(ns, sgio);
+       if (err >= 0) {
+               void __user *datap;
+
+               if (copy_in_user(&sgio32->pack_id, &sgio->pack_id,
+                                sizeof(int)) ||
+                   get_user(datap, &sgio->usr_ptr) ||
+                   put_user((u32)(unsigned long)datap,
+                            &sgio32->usr_ptr) ||
+                   copy_in_user(&sgio32->status, &sgio->status,
+                                (4 * sizeof(unsigned char)) +
+                                (2 * sizeof(unsigned short)) +
+                                (3 * sizeof(int))))
+                       err = -EFAULT;
+       }
+
+       return err;
+}
+#endif
+
 int nvme_sg_get_version_num(int __user *ip)
 {
        return put_user(sg_version_num, ip);
index da18046..4b97b86 100644 (file)
@@ -285,7 +285,8 @@ static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
                        !rb_next(&persistent_gnt->node)) {
-                       ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
+                       ret = gnttab_unmap_refs(unmap, NULL, pages,
+                               segs_to_unmap);
                        BUG_ON(ret);
                        put_free_pages(blkif, pages, segs_to_unmap);
                        segs_to_unmap = 0;
@@ -320,7 +321,8 @@ static void unmap_purged_grants(struct work_struct *work)
                pages[segs_to_unmap] = persistent_gnt->page;
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-                       ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
+                       ret = gnttab_unmap_refs(unmap, NULL, pages,
+                               segs_to_unmap);
                        BUG_ON(ret);
                        put_free_pages(blkif, pages, segs_to_unmap);
                        segs_to_unmap = 0;
@@ -328,7 +330,7 @@ static void unmap_purged_grants(struct work_struct *work)
                kfree(persistent_gnt);
        }
        if (segs_to_unmap > 0) {
-               ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
+               ret = gnttab_unmap_refs(unmap, NULL, pages, segs_to_unmap);
                BUG_ON(ret);
                put_free_pages(blkif, pages, segs_to_unmap);
        }
@@ -668,14 +670,15 @@ static void xen_blkbk_unmap(struct xen_blkif *blkif,
                                    GNTMAP_host_map, pages[i]->handle);
                pages[i]->handle = BLKBACK_INVALID_HANDLE;
                if (++invcount == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-                       ret = gnttab_unmap_refs(unmap, unmap_pages, invcount);
+                       ret = gnttab_unmap_refs(unmap, NULL, unmap_pages,
+                                               invcount);
                        BUG_ON(ret);
                        put_free_pages(blkif, unmap_pages, invcount);
                        invcount = 0;
                }
        }
        if (invcount) {
-               ret = gnttab_unmap_refs(unmap, unmap_pages, invcount);
+               ret = gnttab_unmap_refs(unmap, NULL, unmap_pages, invcount);
                BUG_ON(ret);
                put_free_pages(blkif, unmap_pages, invcount);
        }
@@ -737,7 +740,7 @@ again:
        }
 
        if (segs_to_map) {
-               ret = gnttab_map_refs(map, pages_to_gnt, segs_to_map);
+               ret = gnttab_map_refs(map, NULL, pages_to_gnt, segs_to_map);
                BUG_ON(ret);
        }
 
index 86b484c..5194afb 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_SIRF_IRQ)                        += irq-sirfsoc.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)      += irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC)             += irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)       += irq-versatile-fpga.o
+obj-$(CONFIG_ARCH_NSPIRE)              += irq-zevio.o
 obj-$(CONFIG_ARCH_VT8500)              += irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)               += irq-tb10x.o
 obj-$(CONFIG_XTENSA)                   += irq-xtensa-pic.o
index 9300bc3..5409564 100644 (file)
@@ -381,7 +381,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
                                                ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
                                & PCI_MSI_DOORBELL_MASK;
 
-                       writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
+                       writel(~msimask, per_cpu_int_base +
                               ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
 
                        for (msinr = PCI_MSI_DOORBELL_START;
@@ -407,7 +407,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
                                                ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
                                & IPI_DOORBELL_MASK;
 
-                       writel(~IPI_DOORBELL_MASK, per_cpu_int_base +
+                       writel(~ipimask, per_cpu_int_base +
                                ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
 
                        /* Handle all pending doorbells */
diff --git a/drivers/irqchip/irq-zevio.c b/drivers/irqchip/irq-zevio.c
new file mode 100644 (file)
index 0000000..8ed04c4
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  linux/drivers/irqchip/irq-zevio.c
+ *
+ *  Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/exception.h>
+
+#include "irqchip.h"
+
+#define IO_STATUS      0x000
+#define IO_RAW_STATUS  0x004
+#define IO_ENABLE      0x008
+#define IO_DISABLE     0x00C
+#define IO_CURRENT     0x020
+#define IO_RESET       0x028
+#define IO_MAX_PRIOTY  0x02C
+
+#define IO_IRQ_BASE    0x000
+#define IO_FIQ_BASE    0x100
+
+#define IO_INVERT_SEL  0x200
+#define IO_STICKY_SEL  0x204
+#define IO_PRIORITY_SEL        0x300
+
+#define MAX_INTRS      32
+#define FIQ_START      MAX_INTRS
+
+static struct irq_domain *zevio_irq_domain;
+static void __iomem *zevio_irq_io;
+
+static void zevio_irq_ack(struct irq_data *irqd)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(irqd);
+       struct irq_chip_regs *regs =
+               &container_of(irqd->chip, struct irq_chip_type, chip)->regs;
+
+       readl(gc->reg_base + regs->ack);
+}
+
+static asmlinkage void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs)
+{
+       int irqnr;
+
+       while (readl(zevio_irq_io + IO_STATUS)) {
+               irqnr = readl(zevio_irq_io + IO_CURRENT);
+               irqnr = irq_find_mapping(zevio_irq_domain, irqnr);
+               handle_IRQ(irqnr, regs);
+       };
+}
+
+static void __init zevio_init_irq_base(void __iomem *base)
+{
+       /* Disable all interrupts */
+       writel(~0, base + IO_DISABLE);
+
+       /* Accept interrupts of all priorities */
+       writel(0xF, base + IO_MAX_PRIOTY);
+
+       /* Reset existing interrupts */
+       readl(base + IO_RESET);
+}
+
+static int __init zevio_of_init(struct device_node *node,
+                               struct device_node *parent)
+{
+       unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+       struct irq_chip_generic *gc;
+       int ret;
+
+       if (WARN_ON(zevio_irq_io || zevio_irq_domain))
+               return -EBUSY;
+
+       zevio_irq_io = of_iomap(node, 0);
+       BUG_ON(!zevio_irq_io);
+
+       /* Do not invert interrupt status bits */
+       writel(~0, zevio_irq_io + IO_INVERT_SEL);
+
+       /* Disable sticky interrupts */
+       writel(0, zevio_irq_io + IO_STICKY_SEL);
+
+       /* We don't use IRQ priorities. Set each IRQ to highest priority. */
+       memset_io(zevio_irq_io + IO_PRIORITY_SEL, 0, MAX_INTRS * sizeof(u32));
+
+       /* Init IRQ and FIQ */
+       zevio_init_irq_base(zevio_irq_io + IO_IRQ_BASE);
+       zevio_init_irq_base(zevio_irq_io + IO_FIQ_BASE);
+
+       zevio_irq_domain = irq_domain_add_linear(node, MAX_INTRS,
+                                                &irq_generic_chip_ops, NULL);
+       BUG_ON(!zevio_irq_domain);
+
+       ret = irq_alloc_domain_generic_chips(zevio_irq_domain, MAX_INTRS, 1,
+                                            "zevio_intc", handle_level_irq,
+                                            clr, 0, IRQ_GC_INIT_MASK_CACHE);
+       BUG_ON(ret);
+
+       gc = irq_get_domain_generic_chip(zevio_irq_domain, 0);
+       gc->reg_base                            = zevio_irq_io;
+       gc->chip_types[0].chip.irq_ack          = zevio_irq_ack;
+       gc->chip_types[0].chip.irq_mask         = irq_gc_mask_disable_reg;
+       gc->chip_types[0].chip.irq_unmask       = irq_gc_unmask_enable_reg;
+       gc->chip_types[0].regs.mask             = IO_IRQ_BASE + IO_ENABLE;
+       gc->chip_types[0].regs.enable           = IO_IRQ_BASE + IO_ENABLE;
+       gc->chip_types[0].regs.disable          = IO_IRQ_BASE + IO_DISABLE;
+       gc->chip_types[0].regs.ack              = IO_IRQ_BASE + IO_RESET;
+
+       set_handle_irq(zevio_handle_irq);
+
+       pr_info("TI-NSPIRE classic IRQ controller\n");
+       return 0;
+}
+
+IRQCHIP_DECLARE(zevio_irq, "lsi,zevio-intc", zevio_of_init);
index 77b46d0..e10febe 100644 (file)
@@ -498,7 +498,7 @@ static int ab3100_regulator_register(struct platform_device *pdev,
                                     struct ab3100_platform_data *plfdata,
                                     struct regulator_init_data *init_data,
                                     struct device_node *np,
-                                    int id)
+                                    unsigned long id)
 {
        struct regulator_desc *desc;
        struct ab3100_regulator *reg;
@@ -646,7 +646,7 @@ ab3100_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
                err = ab3100_regulator_register(
                        pdev, NULL, ab3100_regulator_matches[i].init_data,
                        ab3100_regulator_matches[i].of_node,
-                       (int) ab3100_regulator_matches[i].driver_data);
+                       (unsigned long)ab3100_regulator_matches[i].driver_data);
                if (err) {
                        ab3100_regulators_remove(pdev);
                        return err;
index b38a6b6..16a309e 100644 (file)
@@ -1272,6 +1272,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
                                if (r->dev.parent &&
                                        node == r->dev.of_node)
                                        return r;
+                       *ret = -EPROBE_DEFER;
+                       return NULL;
                } else {
                        /*
                         * If we couldn't even get the node then it's
@@ -1312,7 +1314,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
        struct regulator_dev *rdev;
        struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
        const char *devname = NULL;
-       int ret = -EPROBE_DEFER;
+       int ret;
 
        if (id == NULL) {
                pr_err("get() with no identifier\n");
@@ -1322,6 +1324,11 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
        if (dev)
                devname = dev_name(dev);
 
+       if (have_full_constraints())
+               ret = -ENODEV;
+       else
+               ret = -EPROBE_DEFER;
+
        mutex_lock(&regulator_list_mutex);
 
        rdev = regulator_dev_lookup(dev, id, &ret);
index d9e5579..cd0b9e3 100644 (file)
@@ -441,6 +441,7 @@ common_reg:
        for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
                if (!reg_np) {
                        config.init_data = pdata->regulators[i].initdata;
+                       config.of_node = pdata->regulators[i].reg_node;
                } else {
                        config.init_data = rdata[i].init_data;
                        config.of_node = rdata[i].of_node;
index 34a2704..073b4a1 100644 (file)
@@ -284,10 +284,8 @@ static int map_grant_pages(struct grant_map *map)
        }
 
        pr_debug("map %d+%d\n", map->index, map->count);
-       err = gnttab_map_refs_userspace(map->map_ops,
-                                       use_ptemod ? map->kmap_ops : NULL,
-                                       map->pages,
-                                       map->count);
+       err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL,
+                       map->pages, map->count);
        if (err)
                return err;
 
@@ -317,10 +315,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
                }
        }
 
-       err = gnttab_unmap_refs_userspace(map->unmap_ops + offset,
-                                         use_ptemod ? map->kmap_ops + offset : NULL,
-                                         map->pages + offset,
-                                         pages);
+       err = gnttab_unmap_refs(map->unmap_ops + offset,
+                       use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset,
+                       pages);
        if (err)
                return err;
 
index 8ee13e2..b84e3ab 100644 (file)
@@ -928,17 +928,15 @@ void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count)
 }
 EXPORT_SYMBOL_GPL(gnttab_batch_copy);
 
-int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
+int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                    struct gnttab_map_grant_ref *kmap_ops,
-                   struct page **pages, unsigned int count,
-                   bool m2p_override)
+                   struct page **pages, unsigned int count)
 {
        int i, ret;
        bool lazy = false;
        pte_t *pte;
-       unsigned long mfn, pfn;
+       unsigned long mfn;
 
-       BUG_ON(kmap_ops && !m2p_override);
        ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
        if (ret)
                return ret;
@@ -957,12 +955,10 @@ int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                        set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT,
                                        map_ops[i].dev_bus_addr >> PAGE_SHIFT);
                }
-               return 0;
+               return ret;
        }
 
-       if (m2p_override &&
-           !in_interrupt() &&
-           paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
+       if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
                arch_enter_lazy_mmu_mode();
                lazy = true;
        }
@@ -979,20 +975,8 @@ int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                } else {
                        mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
                }
-               pfn = page_to_pfn(pages[i]);
-
-               WARN_ON(PagePrivate(pages[i]));
-               SetPagePrivate(pages[i]);
-               set_page_private(pages[i], mfn);
-
-               pages[i]->index = pfn_to_mfn(pfn);
-               if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               if (m2p_override)
-                       ret = m2p_add_override(mfn, pages[i], kmap_ops ?
-                                              &kmap_ops[i] : NULL);
+               ret = m2p_add_override(mfn, pages[i], kmap_ops ?
+                                      &kmap_ops[i] : NULL);
                if (ret)
                        goto out;
        }
@@ -1003,32 +987,15 @@ int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
 
        return ret;
 }
-
-int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
-                   struct page **pages, unsigned int count)
-{
-       return __gnttab_map_refs(map_ops, NULL, pages, count, false);
-}
 EXPORT_SYMBOL_GPL(gnttab_map_refs);
 
-int gnttab_map_refs_userspace(struct gnttab_map_grant_ref *map_ops,
-                             struct gnttab_map_grant_ref *kmap_ops,
-                             struct page **pages, unsigned int count)
-{
-       return __gnttab_map_refs(map_ops, kmap_ops, pages, count, true);
-}
-EXPORT_SYMBOL_GPL(gnttab_map_refs_userspace);
-
-int __gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
+int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                      struct gnttab_map_grant_ref *kmap_ops,
-                     struct page **pages, unsigned int count,
-                     bool m2p_override)
+                     struct page **pages, unsigned int count)
 {
        int i, ret;
        bool lazy = false;
-       unsigned long pfn, mfn;
 
-       BUG_ON(kmap_ops && !m2p_override);
        ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
        if (ret)
                return ret;
@@ -1039,33 +1006,17 @@ int __gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                        set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT,
                                        INVALID_P2M_ENTRY);
                }
-               return 0;
+               return ret;
        }
 
-       if (m2p_override &&
-           !in_interrupt() &&
-           paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
+       if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
                arch_enter_lazy_mmu_mode();
                lazy = true;
        }
 
        for (i = 0; i < count; i++) {
-               pfn = page_to_pfn(pages[i]);
-               mfn = get_phys_to_machine(pfn);
-               if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               set_page_private(pages[i], INVALID_P2M_ENTRY);
-               WARN_ON(!PagePrivate(pages[i]));
-               ClearPagePrivate(pages[i]);
-               set_phys_to_machine(pfn, pages[i]->index);
-               if (m2p_override)
-                       ret = m2p_remove_override(pages[i],
-                                                 kmap_ops ?
-                                                  &kmap_ops[i] : NULL,
-                                                 mfn);
+               ret = m2p_remove_override(pages[i], kmap_ops ?
+                                      &kmap_ops[i] : NULL);
                if (ret)
                        goto out;
        }
@@ -1076,22 +1027,8 @@ int __gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
 
        return ret;
 }
-
-int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *map_ops,
-                   struct page **pages, unsigned int count)
-{
-       return __gnttab_unmap_refs(map_ops, NULL, pages, count, false);
-}
 EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
 
-int gnttab_unmap_refs_userspace(struct gnttab_unmap_grant_ref *map_ops,
-                               struct gnttab_map_grant_ref *kmap_ops,
-                               struct page **pages, unsigned int count)
-{
-       return __gnttab_unmap_refs(map_ops, kmap_ops, pages, count, true);
-}
-EXPORT_SYMBOL_GPL(gnttab_unmap_refs_userspace);
-
 static unsigned nr_status_frames(unsigned nr_grant_frames)
 {
        BUG_ON(grefs_per_grant_frame == 0);
index 49a62b4..0e8388e 100644 (file)
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 #include <linux/mutex.h>
-#include <linux/crc32c.h>
 #include <linux/genhd.h>
 #include <linux/blkdev.h>
 #include "ctree.h"
 #include "disk-io.h"
+#include "hash.h"
 #include "transaction.h"
 #include "extent_io.h"
 #include "volumes.h"
@@ -1823,7 +1823,7 @@ static int btrfsic_test_for_metadata(struct btrfsic_state *state,
                size_t sublen = i ? PAGE_CACHE_SIZE :
                                    (PAGE_CACHE_SIZE - BTRFS_CSUM_SIZE);
 
-               crc = crc32c(crc, data, sublen);
+               crc = btrfs_crc32c(crc, data, sublen);
        }
        btrfs_csum_final(crc, csum);
        if (memcmp(csum, h->csum, state->csum_size))
index 0e69295..5215f04 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/workqueue.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-#include <linux/crc32c.h>
 #include <linux/slab.h>
 #include <linux/migrate.h>
 #include <linux/ratelimit.h>
@@ -35,6 +34,7 @@
 #include <asm/unaligned.h>
 #include "ctree.h"
 #include "disk-io.h"
+#include "hash.h"
 #include "transaction.h"
 #include "btrfs_inode.h"
 #include "volumes.h"
@@ -244,7 +244,7 @@ out:
 
 u32 btrfs_csum_data(char *data, u32 seed, size_t len)
 {
-       return crc32c(seed, data, len);
+       return btrfs_crc32c(seed, data, len);
 }
 
 void btrfs_csum_final(u32 crc, char *result)
index 5c4ab9c..184e9cb 100644 (file)
@@ -2629,7 +2629,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                        EXTENT_DEFRAG, 1, cached_state);
        if (ret) {
                u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item);
-               if (last_snapshot >= BTRFS_I(inode)->generation)
+               if (0 && last_snapshot >= BTRFS_I(inode)->generation)
                        /* the inode is shared */
                        new = record_old_file_extents(inode, ordered_extent);
 
index 730dce3..cf9107a 100644 (file)
 #include <linux/xattr.h>
 #include <linux/posix_acl_xattr.h>
 #include <linux/radix-tree.h>
-#include <linux/crc32c.h>
 #include <linux/vmalloc.h>
 #include <linux/string.h>
 
 #include "send.h"
 #include "backref.h"
+#include "hash.h"
 #include "locking.h"
 #include "disk-io.h"
 #include "btrfs_inode.h"
@@ -620,7 +620,7 @@ static int send_cmd(struct send_ctx *sctx)
        hdr->len = cpu_to_le32(sctx->send_size - sizeof(*hdr));
        hdr->crc = 0;
 
-       crc = crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size);
+       crc = btrfs_crc32c(0, (unsigned char *)sctx->send_buf, sctx->send_size);
        hdr->crc = cpu_to_le32(crc);
 
        ret = write_buf(sctx->send_filp, sctx->send_buf, sctx->send_size,
index c02f633..97cc241 100644 (file)
@@ -1996,7 +1996,7 @@ static void __exit exit_btrfs_fs(void)
        btrfs_hash_exit();
 }
 
-module_init(init_btrfs_fs)
+late_initcall(init_btrfs_fs);
 module_exit(exit_btrfs_fs)
 
 MODULE_LICENSE("GPL");
index e1529b4..3d78fcc 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -748,11 +748,10 @@ EXPORT_SYMBOL(setup_arg_pages);
 
 #endif /* CONFIG_MMU */
 
-struct file *open_exec(const char *name)
+static struct file *do_open_exec(struct filename *name)
 {
        struct file *file;
        int err;
-       struct filename tmp = { .name = name };
        static const struct open_flags open_exec_flags = {
                .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
                .acc_mode = MAY_EXEC | MAY_OPEN,
@@ -760,7 +759,7 @@ struct file *open_exec(const char *name)
                .lookup_flags = LOOKUP_FOLLOW,
        };
 
-       file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags);
+       file = do_filp_open(AT_FDCWD, name, &open_exec_flags);
        if (IS_ERR(file))
                goto out;
 
@@ -784,6 +783,12 @@ exit:
        fput(file);
        return ERR_PTR(err);
 }
+
+struct file *open_exec(const char *name)
+{
+       struct filename tmp = { .name = name };
+       return do_open_exec(&tmp);
+}
 EXPORT_SYMBOL(open_exec);
 
 int kernel_read(struct file *file, loff_t offset,
@@ -1162,7 +1167,7 @@ int prepare_bprm_creds(struct linux_binprm *bprm)
        return -ENOMEM;
 }
 
-void free_bprm(struct linux_binprm *bprm)
+static void free_bprm(struct linux_binprm *bprm)
 {
        free_arg_pages(bprm);
        if (bprm->cred) {
@@ -1432,7 +1437,7 @@ static int exec_binprm(struct linux_binprm *bprm)
 /*
  * sys_execve() executes a new program.
  */
-static int do_execve_common(const char *filename,
+static int do_execve_common(struct filename *filename,
                                struct user_arg_ptr argv,
                                struct user_arg_ptr envp)
 {
@@ -1441,6 +1446,9 @@ static int do_execve_common(const char *filename,
        struct files_struct *displaced;
        int retval;
 
+       if (IS_ERR(filename))
+               return PTR_ERR(filename);
+
        /*
         * We move the actual failure in case of RLIMIT_NPROC excess from
         * set*uid() to execve() because too many poorly written programs
@@ -1473,7 +1481,7 @@ static int do_execve_common(const char *filename,
        check_unsafe_exec(bprm);
        current->in_execve = 1;
 
-       file = open_exec(filename);
+       file = do_open_exec(filename);
        retval = PTR_ERR(file);
        if (IS_ERR(file))
                goto out_unmark;
@@ -1481,8 +1489,7 @@ static int do_execve_common(const char *filename,
        sched_exec();
 
        bprm->file = file;
-       bprm->filename = filename;
-       bprm->interp = filename;
+       bprm->filename = bprm->interp = filename->name;
 
        retval = bprm_mm_init(bprm);
        if (retval)
@@ -1523,6 +1530,7 @@ static int do_execve_common(const char *filename,
        acct_update_integrals(current);
        task_numa_free(current);
        free_bprm(bprm);
+       putname(filename);
        if (displaced)
                put_files_struct(displaced);
        return retval;
@@ -1544,10 +1552,11 @@ out_files:
        if (displaced)
                reset_files_struct(displaced);
 out_ret:
+       putname(filename);
        return retval;
 }
 
-int do_execve(const char *filename,
+int do_execve(struct filename *filename,
        const char __user *const __user *__argv,
        const char __user *const __user *__envp)
 {
@@ -1557,7 +1566,7 @@ int do_execve(const char *filename,
 }
 
 #ifdef CONFIG_COMPAT
-static int compat_do_execve(const char *filename,
+static int compat_do_execve(struct filename *filename,
        const compat_uptr_t __user *__argv,
        const compat_uptr_t __user *__envp)
 {
@@ -1607,25 +1616,13 @@ SYSCALL_DEFINE3(execve,
                const char __user *const __user *, argv,
                const char __user *const __user *, envp)
 {
-       struct filename *path = getname(filename);
-       int error = PTR_ERR(path);
-       if (!IS_ERR(path)) {
-               error = do_execve(path->name, argv, envp);
-               putname(path);
-       }
-       return error;
+       return do_execve(getname(filename), argv, envp);
 }
 #ifdef CONFIG_COMPAT
 asmlinkage long compat_sys_execve(const char __user * filename,
        const compat_uptr_t __user * argv,
        const compat_uptr_t __user * envp)
 {
-       struct filename *path = getname(filename);
-       int error = PTR_ERR(path);
-       if (!IS_ERR(path)) {
-               error = compat_do_execve(path->name, argv, envp);
-               putname(path);
-       }
-       return error;
+       return compat_do_execve(getname(filename), argv, envp);
 }
 #endif
index d580df2..385f781 100644 (file)
@@ -196,6 +196,7 @@ recopy:
                goto error;
 
        result->uptr = filename;
+       result->aname = NULL;
        audit_getname(result);
        return result;
 
@@ -210,6 +211,35 @@ getname(const char __user * filename)
        return getname_flags(filename, 0, NULL);
 }
 
+/*
+ * The "getname_kernel()" interface doesn't do pathnames longer
+ * than EMBEDDED_NAME_MAX. Deal with it - you're a kernel user.
+ */
+struct filename *
+getname_kernel(const char * filename)
+{
+       struct filename *result;
+       char *kname;
+       int len;
+
+       len = strlen(filename);
+       if (len >= EMBEDDED_NAME_MAX)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       result = __getname();
+       if (unlikely(!result))
+               return ERR_PTR(-ENOMEM);
+
+       kname = (char *)result + sizeof(*result);
+       result->name = kname;
+       result->uptr = NULL;
+       result->aname = NULL;
+       result->separate = false;
+
+       strlcpy(kname, filename, EMBEDDED_NAME_MAX);
+       return result;
+}
+
 #ifdef CONFIG_AUDITSYSCALL
 void putname(struct filename *name)
 {
index 9a5ca03..871d6ed 100644 (file)
@@ -80,7 +80,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
        }
 
        if (res.acl_access != NULL) {
-               if (posix_acl_equiv_mode(res.acl_access, NULL) ||
+               if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) ||
                    res.acl_access->a_count == 0) {
                        posix_acl_release(res.acl_access);
                        res.acl_access = NULL;
@@ -113,7 +113,7 @@ getout:
        return ERR_PTR(status);
 }
 
-int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
                struct posix_acl *dfacl)
 {
        struct nfs_server *server = NFS_SERVER(inode);
@@ -198,6 +198,15 @@ out:
        return status;
 }
 
+int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+               struct posix_acl *dfacl)
+{
+       int ret;
+       ret = __nfs3_proc_setacls(inode, acl, dfacl);
+       return (ret == -EOPNOTSUPP) ? 0 : ret;
+
+}
+
 int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
        struct posix_acl *alloc = NULL, *dfacl = NULL;
@@ -225,7 +234,7 @@ int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
                if (IS_ERR(alloc))
                        goto fail;
        }
-       status = nfs3_proc_setacls(inode, acl, dfacl);
+       status = __nfs3_proc_setacls(inode, acl, dfacl);
        posix_acl_release(alloc);
        return status;
 
@@ -233,25 +242,6 @@ fail:
        return PTR_ERR(alloc);
 }
 
-int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
-               umode_t mode)
-{
-       struct posix_acl *default_acl, *acl;
-       int error;
-
-       error = posix_acl_create(dir, &mode, &default_acl, &acl);
-       if (error)
-               return (error == -EOPNOTSUPP) ? 0 : error;
-
-       error = nfs3_proc_setacls(inode, acl, default_acl);
-
-       if (acl)
-               posix_acl_release(acl);
-       if (default_acl)
-               posix_acl_release(default_acl);
-       return error;
-}
-
 const struct xattr_handler *nfs3_xattr_handlers[] = {
        &posix_acl_access_xattr_handler,
        &posix_acl_default_xattr_handler,
index dbb3e1f..860ad26 100644 (file)
@@ -170,7 +170,7 @@ void nfs41_shutdown_client(struct nfs_client *clp)
 void nfs40_shutdown_client(struct nfs_client *clp)
 {
        if (clp->cl_slot_tbl) {
-               nfs4_release_slot_table(clp->cl_slot_tbl);
+               nfs4_shutdown_slot_table(clp->cl_slot_tbl);
                kfree(clp->cl_slot_tbl);
        }
 }
index 42da6af..2da6a69 100644 (file)
@@ -1620,15 +1620,15 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
 {
        struct nfs4_opendata *data = calldata;
 
-       nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args,
-                               &data->o_res.seq_res, task);
+       nfs40_setup_sequence(data->o_arg.server, &data->c_arg.seq_args,
+                               &data->c_res.seq_res, task);
 }
 
 static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
 {
        struct nfs4_opendata *data = calldata;
 
-       nfs40_sequence_done(task, &data->o_res.seq_res);
+       nfs40_sequence_done(task, &data->c_res.seq_res);
 
        data->rpc_status = task->tk_status;
        if (data->rpc_status == 0) {
@@ -1686,7 +1686,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
        };
        int status;
 
-       nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1);
+       nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
        kref_get(&data->kref);
        data->rpc_done = 0;
        data->rpc_status = 0;
index cf883c7..e799dc3 100644 (file)
@@ -231,14 +231,23 @@ out:
        return ret;
 }
 
+/*
+ * nfs4_release_slot_table - release all slot table entries
+ */
+static void nfs4_release_slot_table(struct nfs4_slot_table *tbl)
+{
+       nfs4_shrink_slot_table(tbl, 0);
+}
+
 /**
- * nfs4_release_slot_table - release resources attached to a slot table
+ * nfs4_shutdown_slot_table - release resources attached to a slot table
  * @tbl: slot table to shut down
  *
  */
-void nfs4_release_slot_table(struct nfs4_slot_table *tbl)
+void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl)
 {
-       nfs4_shrink_slot_table(tbl, 0);
+       nfs4_release_slot_table(tbl);
+       rpc_destroy_wait_queue(&tbl->slot_tbl_waitq);
 }
 
 /**
@@ -422,7 +431,7 @@ void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
        spin_unlock(&tbl->slot_tbl_lock);
 }
 
-static void nfs4_destroy_session_slot_tables(struct nfs4_session *session)
+static void nfs4_release_session_slot_tables(struct nfs4_session *session)
 {
        nfs4_release_slot_table(&session->fc_slot_table);
        nfs4_release_slot_table(&session->bc_slot_table);
@@ -450,7 +459,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
        if (status && tbl->slots == NULL)
                /* Fore and back channel share a connection so get
                 * both slot tables or neither */
-               nfs4_destroy_session_slot_tables(ses);
+               nfs4_release_session_slot_tables(ses);
        return status;
 }
 
@@ -470,6 +479,12 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
        return session;
 }
 
+static void nfs4_destroy_session_slot_tables(struct nfs4_session *session)
+{
+       nfs4_shutdown_slot_table(&session->fc_slot_table);
+       nfs4_shutdown_slot_table(&session->bc_slot_table);
+}
+
 void nfs4_destroy_session(struct nfs4_session *session)
 {
        struct rpc_xprt *xprt;
index 2323061..b34ada9 100644 (file)
@@ -74,7 +74,7 @@ enum nfs4_session_state {
 
 extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
                unsigned int max_reqs, const char *queue);
-extern void nfs4_release_slot_table(struct nfs4_slot_table *tbl);
+extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
 extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
 extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
 extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);
index 38bae5a..11c54fd 100644 (file)
@@ -521,8 +521,11 @@ posix_acl_chmod(struct inode *inode, umode_t mode)
                return -EOPNOTSUPP;
 
        acl = get_acl(inode, ACL_TYPE_ACCESS);
-       if (IS_ERR_OR_NULL(acl))
+       if (IS_ERR_OR_NULL(acl)) {
+               if (acl == ERR_PTR(-EOPNOTSUPP))
+                       return 0;
                return PTR_ERR(acl);
+       }
 
        ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
        if (ret)
@@ -544,14 +547,15 @@ posix_acl_create(struct inode *dir, umode_t *mode,
                goto no_acl;
 
        p = get_acl(dir, ACL_TYPE_DEFAULT);
-       if (IS_ERR(p))
+       if (IS_ERR(p)) {
+               if (p == ERR_PTR(-EOPNOTSUPP))
+                       goto apply_umask;
                return PTR_ERR(p);
-
-       if (!p) {
-               *mode &= ~current_umask();
-               goto no_acl;
        }
 
+       if (!p)
+               goto apply_umask;
+
        *acl = posix_acl_clone(p, GFP_NOFS);
        if (!*acl)
                return -ENOMEM;
@@ -575,6 +579,8 @@ posix_acl_create(struct inode *dir, umode_t *mode,
        }
        return 0;
 
+apply_umask:
+       *mode &= ~current_umask();
 no_acl:
        *default_acl = NULL;
        *acl = NULL;
index fd8bf32..b4a745d 100644 (file)
@@ -115,7 +115,6 @@ extern int copy_strings_kernel(int argc, const char *const *argv,
 extern int prepare_bprm_creds(struct linux_binprm *bprm);
 extern void install_exec_creds(struct linux_binprm *bprm);
 extern void set_binfmt(struct linux_binfmt *new);
-extern void free_bprm(struct linux_binprm *);
 extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t);
 
 #endif /* _LINUX_BINFMTS_H */
index 09f553c..d79678c 100644 (file)
@@ -2079,6 +2079,7 @@ extern struct file * dentry_open(const struct path *, int, const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
 
 extern struct filename *getname(const char __user *);
+extern struct filename *getname_kernel(const char *);
 
 enum {
        FILE_CREATED = 1,
index 3ccfcec..b2fb167 100644 (file)
@@ -379,12 +379,14 @@ struct nfs_openres {
  * Arguments to the open_confirm call.
  */
 struct nfs_open_confirmargs {
+       struct nfs4_sequence_args       seq_args;
        const struct nfs_fh *   fh;
        nfs4_stateid *          stateid;
        struct nfs_seqid *      seqid;
 };
 
 struct nfs_open_confirmres {
+       struct nfs4_sequence_res        seq_res;
        nfs4_stateid            stateid;
        struct nfs_seqid *      seqid;
 };
index 26ebcf4..69ae03f 100644 (file)
@@ -80,13 +80,14 @@ struct nvme_dev {
        struct dma_pool *prp_small_pool;
        int instance;
        int queue_count;
-       int db_stride;
+       u32 db_stride;
        u32 ctrl_config;
        struct msix_entry *entry;
        struct nvme_bar __iomem *bar;
        struct list_head namespaces;
        struct kref kref;
        struct miscdevice miscdev;
+       struct work_struct reset_work;
        char name[12];
        char serial[20];
        char model[40];
@@ -94,6 +95,8 @@ struct nvme_dev {
        u32 max_hw_sectors;
        u32 stripe_size;
        u16 oncs;
+       u16 abort_limit;
+       u8 initialized;
 };
 
 /*
@@ -165,6 +168,7 @@ int nvme_set_features(struct nvme_dev *dev, unsigned fid, unsigned dword11,
 struct sg_io_hdr;
 
 int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr);
+int nvme_sg_io32(struct nvme_ns *ns, unsigned long arg);
 int nvme_sg_get_version_num(int __user *ip);
 
 #endif /* _LINUX_NVME_H */
index 68a0e84..a781dec 100644 (file)
@@ -128,6 +128,7 @@ struct bio_list;
 struct fs_struct;
 struct perf_event_context;
 struct blk_plug;
+struct filename;
 
 /*
  * List of flags we want to share for kernel threads,
@@ -2311,7 +2312,7 @@ extern void do_group_exit(int);
 extern int allow_signal(int);
 extern int disallow_signal(int);
 
-extern int do_execve(const char *,
+extern int do_execve(struct filename *,
                     const char __user * const __user *,
                     const char __user * const __user *);
 extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *);
index 989c04e..e5ab622 100644 (file)
@@ -350,6 +350,16 @@ struct nvme_delete_queue {
        __u32                   rsvd11[5];
 };
 
+struct nvme_abort_cmd {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __u32                   rsvd1[9];
+       __le16                  sqid;
+       __u16                   cid;
+       __u32                   rsvd11[5];
+};
+
 struct nvme_download_firmware {
        __u8                    opcode;
        __u8                    flags;
@@ -384,6 +394,7 @@ struct nvme_command {
                struct nvme_download_firmware dlfw;
                struct nvme_format_cmd format;
                struct nvme_dsm_cmd dsm;
+               struct nvme_abort_cmd abort;
        };
 };
 
index 7ad033d..a5af2a2 100644 (file)
@@ -191,15 +191,11 @@ void gnttab_free_auto_xlat_frames(void);
 #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
 
 int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
+                   struct gnttab_map_grant_ref *kmap_ops,
                    struct page **pages, unsigned int count);
-int gnttab_map_refs_userspace(struct gnttab_map_grant_ref *map_ops,
-                             struct gnttab_map_grant_ref *kmap_ops,
-                             struct page **pages, unsigned int count);
 int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
+                     struct gnttab_map_grant_ref *kunmap_ops,
                      struct page **pages, unsigned int count);
-int gnttab_unmap_refs_userspace(struct gnttab_unmap_grant_ref *unmap_ops,
-                               struct gnttab_map_grant_ref *kunmap_ops,
-                               struct page **pages, unsigned int count);
 
 /* Perform a batch of grant map/copy operations. Retry every batch slot
  * for which the hypervisor returns GNTST_eagain. This is typically due
index 2fd9cef..eb03090 100644 (file)
@@ -812,7 +812,7 @@ void __init load_default_modules(void)
 static int run_init_process(const char *init_filename)
 {
        argv_init[0] = init_filename;
-       return do_execve(init_filename,
+       return do_execve(getname_kernel(init_filename),
                (const char __user *const __user *)argv_init,
                (const char __user *const __user *)envp_init);
 }
index 10176cd..7aef2f4 100644 (file)
@@ -1719,7 +1719,7 @@ void audit_putname(struct filename *name)
        struct audit_context *context = current->audit_context;
 
        BUG_ON(!context);
-       if (!context->in_syscall) {
+       if (!name->aname || !context->in_syscall) {
 #if AUDIT_DEBUG == 2
                printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n",
                       __FILE__, __LINE__, context->serial, name);
index b086006..6b375af 100644 (file)
@@ -239,7 +239,7 @@ static int ____call_usermodehelper(void *data)
 
        commit_creds(new);
 
-       retval = do_execve(sub_info->path,
+       retval = do_execve(getname_kernel(sub_info->path),
                           (const char __user *const __user *)sub_info->argv,
                           (const char __user *const __user *)sub_info->envp);
        if (!retval)
index dbf94a7..a48abea 100644 (file)
@@ -119,7 +119,7 @@ menu "Compile-time checks and compiler options"
 
 config DEBUG_INFO
        bool "Compile the kernel with debug info"
-       depends on DEBUG_KERNEL
+       depends on DEBUG_KERNEL && !COMPILE_TEST
        help
           If you say Y here the resulting kernel image will include
          debugging info resulting in a larger kernel image.