[PATCH 10/10] mm: replace access_process_vm() write parameter with gup_flags

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write parameter from access_process_vm() and replaces it
with a gup_flags parameter as use of this function previously _implied_
FOLL_FORCE, whereas after this patch callers explicitly pass this flag.

We make this explicit as use of FOLL_FORCE can result in surprising behaviour
(and hence bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 arch/alpha/kernel/ptrace.c |  9 ++---
 arch/blackfin/kernel/ptrace.c  |  5 +++--
 arch/cris/arch-v32/kernel/ptrace.c |  4 ++--
 arch/ia64/kernel/ptrace.c  | 14 +-
 arch/m32r/kernel/ptrace.c  | 15 ++-
 arch/mips/kernel/ptrace32.c|  5 +++--
 arch/powerpc/kernel/ptrace32.c |  5 +++--
 arch/score/kernel/ptrace.c | 10 ++
 arch/sparc/kernel/ptrace_64.c  | 24 
 arch/x86/kernel/step.c |  3 ++-
 arch/x86/um/ptrace_32.c|  3 ++-
 arch/x86/um/ptrace_64.c|  3 ++-
 include/linux/mm.h |  3 ++-
 kernel/ptrace.c| 16 ++--
 mm/memory.c|  8 ++--
 mm/nommu.c |  6 +++---
 mm/util.c  |  5 +++--
 17 files changed, 84 insertions(+), 54 deletions(-)

diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index d9ee817..940dfb4 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -157,14 +157,16 @@ put_reg(struct task_struct *task, unsigned long regno, 
unsigned long data)
 static inline int
 read_int(struct task_struct *task, unsigned long addr, int * data)
 {
-   int copied = access_process_vm(task, addr, data, sizeof(int), 0);
+   int copied = access_process_vm(task, addr, data, sizeof(int),
+   FOLL_FORCE);
return (copied == sizeof(int)) ? 0 : -EIO;
 }
 
 static inline int
 write_int(struct task_struct *task, unsigned long addr, int data)
 {
-   int copied = access_process_vm(task, addr, , sizeof(int), 1);
+   int copied = access_process_vm(task, addr, , sizeof(int),
+   FOLL_FORCE | FOLL_WRITE);
return (copied == sizeof(int)) ? 0 : -EIO;
 }
 
@@ -281,7 +283,8 @@ long arch_ptrace(struct task_struct *child, long request,
/* When I and D space are separate, these will need to be fixed.  */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
-   copied = access_process_vm(child, addr, , sizeof(tmp), 0);
+   copied = access_process_vm(child, addr, , sizeof(tmp),
+   FOLL_FORCE);
ret = -EIO;
if (copied != sizeof(tmp))
break;
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 8b8fe67..8d79286 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -271,7 +271,7 @@ long arch_ptrace(struct task_struct *child, long request,
case BFIN_MEM_ACCESS_CORE:
case BFIN_MEM_ACCESS_CORE_ONLY:
copied = access_process_vm(child, addr, ,
-  to_copy, 0);
+  to_copy, FOLL_FORCE);
if (copied)
break;
 
@@ -324,7 +324,8 @@ long arch_ptrace(struct task_struct *child, long request,
case BFIN_MEM_ACCESS_CORE:
case BFIN_MEM_ACCESS_CORE_ONLY:
copied = access_process_vm(child, addr, ,
-  to_copy, 1);
+  to_copy,
+  FOLL_FORCE | 
FOLL_WRITE);
break;
case BFIN_MEM_ACCESS_DMA:
if (safe_dma_memcpy(paddr, , to_copy))
diff --git a/arch/cris/arch-v32/kernel/ptrace.c 
b/arch/cris/arch-v32/kernel/ptrace.c
index f085229..f0df654 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *child, long request,
/* The trampoline page is globally mapped, no 
page table to traverse.*/
tmp = *(unsigned long*)addr;
} else {
-   copied = access_process_vm(child, addr, , 
sizeof(tmp), 0);
+   copied = access_process_vm(child, addr, , 
sizeof(tmp), FOLL_FORCE);
 
if (copied != sizeof(tmp))
break;
@@ -279,7 +279,7 @@ static int insn_size(struct task_struct *child, unsigned 
long pc)
   int opsize = 0;
 
   /* Read the 

[PATCH 06/10] mm: replace get_user_pages() write/force parameters with gup_flags

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write and force parameters from get_user_pages() and
replaces them with a gup_flags parameter to make the use of FOLL_FORCE explicit
in callers as use of this flag can result in surprising behaviour (and hence
bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 arch/cris/arch-v32/drivers/cryptocop.c |  4 +---
 arch/ia64/kernel/err_inject.c  |  2 +-
 arch/x86/mm/mpx.c  |  5 ++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c|  7 +--
 drivers/gpu/drm/radeon/radeon_ttm.c|  3 ++-
 drivers/gpu/drm/via/via_dmablit.c  |  4 ++--
 drivers/infiniband/core/umem.c |  6 +-
 drivers/infiniband/hw/mthca/mthca_memfree.c|  2 +-
 drivers/infiniband/hw/qib/qib_user_pages.c |  3 ++-
 drivers/infiniband/hw/usnic/usnic_uiom.c   |  5 -
 drivers/media/v4l2-core/videobuf-dma-sg.c  |  7 +--
 drivers/misc/mic/scif/scif_rma.c   |  3 +--
 drivers/misc/sgi-gru/grufault.c|  2 +-
 drivers/platform/goldfish/goldfish_pipe.c  |  3 ++-
 drivers/rapidio/devices/rio_mport_cdev.c   |  3 ++-
 .../vc04_services/interface/vchiq_arm/vchiq_2835_arm.c |  3 +--
 .../vc04_services/interface/vchiq_arm/vchiq_arm.c  |  3 +--
 drivers/virt/fsl_hypervisor.c  |  4 ++--
 include/linux/mm.h |  2 +-
 mm/gup.c   | 12 +++-
 mm/mempolicy.c |  2 +-
 mm/nommu.c | 18 --
 22 files changed, 49 insertions(+), 54 deletions(-)

diff --git a/arch/cris/arch-v32/drivers/cryptocop.c 
b/arch/cris/arch-v32/drivers/cryptocop.c
index b5698c8..099e170 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -2722,7 +2722,6 @@ static int cryptocop_ioctl_process(struct inode *inode, 
struct file *filp, unsig
err = get_user_pages((unsigned long int)(oper.indata + prev_ix),
 noinpages,
 0,  /* read access only for in data */
-0, /* no force */
 inpages,
 NULL);
 
@@ -2736,8 +2735,7 @@ static int cryptocop_ioctl_process(struct inode *inode, 
struct file *filp, unsig
if (oper.do_cipher){
err = get_user_pages((unsigned long int)oper.cipher_outdata,
 nooutpages,
-1, /* write access for out data */
-0, /* no force */
+FOLL_WRITE, /* write access for out data */
 outpages,
 NULL);
up_read(>mm->mmap_sem);
diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c
index 09f8457..5ed0ea9 100644
--- a/arch/ia64/kernel/err_inject.c
+++ b/arch/ia64/kernel/err_inject.c
@@ -142,7 +142,7 @@ store_virtual_to_phys(struct device *dev, struct 
device_attribute *attr,
u64 virt_addr=simple_strtoull(buf, NULL, 16);
int ret;
 
-   ret = get_user_pages(virt_addr, 1, VM_READ, 0, NULL, NULL);
+   ret = get_user_pages(virt_addr, 1, FOLL_WRITE, NULL, NULL);
if (ret<=0) {
 #ifdef ERR_INJ_DEBUG
printk("Virtual address %lx is not existing.\n",virt_addr);
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index 8047687..e4f8009 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -544,10 +544,9 @@ static int mpx_resolve_fault(long __user *addr, int write)
 {
long gup_ret;
int nr_pages = 1;
-   int force = 0;
 
-   gup_ret = get_user_pages((unsigned long)addr, nr_pages, write,
-   force, NULL, NULL);
+   gup_ret = get_user_pages((unsigned long)addr, nr_pages,
+   write ? FOLL_WRITE : 0, NULL, NULL);
/*
 * get_user_pages() returns number of pages gotten.
 * 0 means we failed to fault in and get anything,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 887483b..dcaf691 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -555,10 +555,13 @@ struct amdgpu_ttm_tt {
 int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages)
 {
struct amdgpu_ttm_tt *gtt = (void *)ttm;
-   int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
+   unsigned int flags = 0;
unsigned pinned = 0;
int r;
 
+   if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY))
+   flags |= FOLL_WRITE;
+
if (gtt->userflags & 

[PATCH 05/10] mm: replace get_vaddr_frames() write/force parameters with gup_flags

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write and force parameters from get_vaddr_frames() and
replaces them with a gup_flags parameter to make the use of FOLL_FORCE explicit
in callers as use of this flag can result in surprising behaviour (and hence
bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c|  3 ++-
 drivers/media/platform/omap/omap_vout.c|  2 +-
 drivers/media/v4l2-core/videobuf2-memops.c |  6 +-
 include/linux/mm.h |  2 +-
 mm/frame_vector.c  | 13 ++---
 5 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c 
b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index aa92dec..fbd13fa 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -488,7 +488,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct 
drm_device *drm_dev,
goto err_free;
}
 
-   ret = get_vaddr_frames(start, npages, true, true, g2d_userptr->vec);
+   ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE,
+   g2d_userptr->vec);
if (ret != npages) {
DRM_ERROR("failed to get user pages from userptr.\n");
if (ret < 0)
diff --git a/drivers/media/platform/omap/omap_vout.c 
b/drivers/media/platform/omap/omap_vout.c
index e668dde..a31b95c 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -214,7 +214,7 @@ static int omap_vout_get_userptr(struct videobuf_buffer 
*vb, u32 virtp,
if (!vec)
return -ENOMEM;
 
-   ret = get_vaddr_frames(virtp, 1, true, false, vec);
+   ret = get_vaddr_frames(virtp, 1, FOLL_WRITE, vec);
if (ret != 1) {
frame_vector_destroy(vec);
return -EINVAL;
diff --git a/drivers/media/v4l2-core/videobuf2-memops.c 
b/drivers/media/v4l2-core/videobuf2-memops.c
index 3c3b517..1cd322e 100644
--- a/drivers/media/v4l2-core/videobuf2-memops.c
+++ b/drivers/media/v4l2-core/videobuf2-memops.c
@@ -42,6 +42,10 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
unsigned long first, last;
unsigned long nr;
struct frame_vector *vec;
+   unsigned int flags = FOLL_FORCE;
+
+   if (write)
+   flags |= FOLL_WRITE;
 
first = start >> PAGE_SHIFT;
last = (start + length - 1) >> PAGE_SHIFT;
@@ -49,7 +53,7 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
vec = frame_vector_create(nr);
if (!vec)
return ERR_PTR(-ENOMEM);
-   ret = get_vaddr_frames(start & PAGE_MASK, nr, write, true, vec);
+   ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec);
if (ret < 0)
goto out_destroy;
/* We accept only complete set of PFNs */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 27ab538..5ff084f6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1305,7 +1305,7 @@ struct frame_vector {
 struct frame_vector *frame_vector_create(unsigned int nr_frames);
 void frame_vector_destroy(struct frame_vector *vec);
 int get_vaddr_frames(unsigned long start, unsigned int nr_pfns,
-bool write, bool force, struct frame_vector *vec);
+unsigned int gup_flags, struct frame_vector *vec);
 void put_vaddr_frames(struct frame_vector *vec);
 int frame_vector_to_pages(struct frame_vector *vec);
 void frame_vector_to_pfns(struct frame_vector *vec);
diff --git a/mm/frame_vector.c b/mm/frame_vector.c
index 81b6749..db77dcb 100644
--- a/mm/frame_vector.c
+++ b/mm/frame_vector.c
@@ -11,10 +11,7 @@
  * get_vaddr_frames() - map virtual addresses to pfns
  * @start: starting user address
  * @nr_frames: number of pages / pfns from start to map
- * @write: whether pages will be written to by the caller
- * @force: whether to force write access even if user mapping is
- * readonly. See description of the same argument of
-   get_user_pages().
+ * @gup_flags: flags modifying lookup behaviour
  * @vec:   structure which receives pages / pfns of the addresses mapped.
  * It should have space for at least nr_frames entries.
  *
@@ -34,23 +31,17 @@
  * This function takes care of grabbing mmap_sem as necessary.
  */
 int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
-bool write, bool force, struct frame_vector *vec)
+unsigned int gup_flags, struct frame_vector *vec)
 {
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
int ret = 0;
int err;
int locked;
-   unsigned int gup_flags = 0;
 
if (nr_frames == 0)
return 0;
 
-   if (write)
-   gup_flags |= FOLL_WRITE;
-   if (force)
-   gup_flags |= FOLL_FORCE;
-
if 

[PATCH 08/10] mm: replace __access_remote_vm() write parameter with gup_flags

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write parameter from __access_remote_vm() and replaces it
with a gup_flags parameter as use of this function previously _implied_
FOLL_FORCE, whereas after this patch callers explicitly pass this flag.

We make this explicit as use of FOLL_FORCE can result in surprising behaviour
(and hence bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 mm/memory.c | 23 +++
 mm/nommu.c  |  9 ++---
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/mm/memory.c b/mm/memory.c
index 20a9adb..79ebed3 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3869,14 +3869,11 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
  * given task for page fault accounting.
  */
 static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
-   unsigned long addr, void *buf, int len, int write)
+   unsigned long addr, void *buf, int len, unsigned int gup_flags)
 {
struct vm_area_struct *vma;
void *old_buf = buf;
-   unsigned int flags = FOLL_FORCE;
-
-   if (write)
-   flags |= FOLL_WRITE;
+   int write = gup_flags & FOLL_WRITE;
 
down_read(>mmap_sem);
/* ignore errors, just check how much was successfully transferred */
@@ -3886,7 +3883,7 @@ static int __access_remote_vm(struct task_struct *tsk, 
struct mm_struct *mm,
struct page *page = NULL;
 
ret = get_user_pages_remote(tsk, mm, addr, 1,
-   flags, , );
+   gup_flags, , );
if (ret <= 0) {
 #ifndef CONFIG_HAVE_IOREMAP_PROT
break;
@@ -3945,7 +3942,12 @@ static int __access_remote_vm(struct task_struct *tsk, 
struct mm_struct *mm,
 int access_remote_vm(struct mm_struct *mm, unsigned long addr,
void *buf, int len, int write)
 {
-   return __access_remote_vm(NULL, mm, addr, buf, len, write);
+   unsigned int flags = FOLL_FORCE;
+
+   if (write)
+   flags |= FOLL_WRITE;
+
+   return __access_remote_vm(NULL, mm, addr, buf, len, flags);
 }
 
 /*
@@ -3958,12 +3960,17 @@ int access_process_vm(struct task_struct *tsk, unsigned 
long addr,
 {
struct mm_struct *mm;
int ret;
+   unsigned int flags = FOLL_FORCE;
 
mm = get_task_mm(tsk);
if (!mm)
return 0;
 
-   ret = __access_remote_vm(tsk, mm, addr, buf, len, write);
+   if (write)
+   flags |= FOLL_WRITE;
+
+   ret = __access_remote_vm(tsk, mm, addr, buf, len, flags);
+
mmput(mm);
 
return ret;
diff --git a/mm/nommu.c b/mm/nommu.c
index 70cb844..bde7df3 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1809,9 +1809,10 @@ void filemap_map_pages(struct fault_env *fe,
 EXPORT_SYMBOL(filemap_map_pages);
 
 static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
-   unsigned long addr, void *buf, int len, int write)
+   unsigned long addr, void *buf, int len, unsigned int gup_flags)
 {
struct vm_area_struct *vma;
+   int write = gup_flags & FOLL_WRITE;
 
down_read(>mmap_sem);
 
@@ -1853,7 +1854,8 @@ static int __access_remote_vm(struct task_struct *tsk, 
struct mm_struct *mm,
 int access_remote_vm(struct mm_struct *mm, unsigned long addr,
void *buf, int len, int write)
 {
-   return __access_remote_vm(NULL, mm, addr, buf, len, write);
+   return __access_remote_vm(NULL, mm, addr, buf, len,
+   write ? FOLL_WRITE : 0);
 }
 
 /*
@@ -1871,7 +1873,8 @@ int access_process_vm(struct task_struct *tsk, unsigned 
long addr, void *buf, in
if (!mm)
return 0;
 
-   len = __access_remote_vm(tsk, mm, addr, buf, len, write);
+   len = __access_remote_vm(tsk, mm, addr, buf, len,
+   write ? FOLL_WRITE : 0);
 
mmput(mm);
return len;
-- 
2.10.0

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/10] mm: replace access_remote_vm() write parameter with gup_flags

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write parameter from access_remote_vm() and replaces it
with a gup_flags parameter as use of this function previously _implied_
FOLL_FORCE, whereas after this patch callers explicitly pass this flag.

We make this explicit as use of FOLL_FORCE can result in surprising behaviour
(and hence bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 fs/proc/base.c | 19 +--
 include/linux/mm.h |  2 +-
 mm/memory.c| 11 +++
 mm/nommu.c |  7 +++
 4 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index c2964d8..8e65446 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -252,7 +252,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, 
char __user *buf,
 * Inherently racy -- command line shares address space
 * with code and data.
 */
-   rv = access_remote_vm(mm, arg_end - 1, , 1, 0);
+   rv = access_remote_vm(mm, arg_end - 1, , 1, FOLL_FORCE);
if (rv <= 0)
goto out_free_page;
 
@@ -270,7 +270,8 @@ static ssize_t proc_pid_cmdline_read(struct file *file, 
char __user *buf,
int nr_read;
 
_count = min3(count, len, PAGE_SIZE);
-   nr_read = access_remote_vm(mm, p, page, _count, 0);
+   nr_read = access_remote_vm(mm, p, page, _count,
+   FOLL_FORCE);
if (nr_read < 0)
rv = nr_read;
if (nr_read <= 0)
@@ -305,7 +306,8 @@ static ssize_t proc_pid_cmdline_read(struct file *file, 
char __user *buf,
bool final;
 
_count = min3(count, len, PAGE_SIZE);
-   nr_read = access_remote_vm(mm, p, page, _count, 0);
+   nr_read = access_remote_vm(mm, p, page, _count,
+   FOLL_FORCE);
if (nr_read < 0)
rv = nr_read;
if (nr_read <= 0)
@@ -354,7 +356,8 @@ static ssize_t proc_pid_cmdline_read(struct file *file, 
char __user *buf,
bool final;
 
_count = min3(count, len, PAGE_SIZE);
-   nr_read = access_remote_vm(mm, p, page, _count, 0);
+   nr_read = access_remote_vm(mm, p, page, _count,
+   FOLL_FORCE);
if (nr_read < 0)
rv = nr_read;
if (nr_read <= 0)
@@ -832,6 +835,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
unsigned long addr = *ppos;
ssize_t copied;
char *page;
+   unsigned int flags = FOLL_FORCE;
 
if (!mm)
return 0;
@@ -844,6 +848,9 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
if (!atomic_inc_not_zero(>mm_users))
goto free;
 
+   if (write)
+   flags |= FOLL_WRITE;
+
while (count > 0) {
int this_len = min_t(int, count, PAGE_SIZE);
 
@@ -852,7 +859,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
break;
}
 
-   this_len = access_remote_vm(mm, addr, page, this_len, write);
+   this_len = access_remote_vm(mm, addr, page, this_len, flags);
if (!this_len) {
if (!copied)
copied = -EIO;
@@ -965,7 +972,7 @@ static ssize_t environ_read(struct file *file, char __user 
*buf,
this_len = min(max_len, this_len);
 
retval = access_remote_vm(mm, (env_start + src),
-   page, this_len, 0);
+   page, this_len, FOLL_FORCE);
 
if (retval <= 0) {
ret = retval;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2a481d3..3e5234e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1268,7 +1268,7 @@ static inline int fixup_user_fault(struct task_struct 
*tsk,
 
 extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void 
*buf, int len, int write);
 extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
-   void *buf, int len, int write);
+   void *buf, int len, unsigned int gup_flags);
 
 long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
  unsigned long start, unsigned long nr_pages,
diff --git a/mm/memory.c b/mm/memory.c
index 79ebed3..bac2d99 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3935,19 +3935,14 @@ static int __access_remote_vm(struct task_struct *tsk, 
struct mm_struct *mm,
  * @addr:  start address to access
  * @buf:   source or destination buffer
  * @len:   number of bytes to transfer
- * @write: 

[PATCH 07/10] mm: replace get_user_pages_remote() write/force parameters with gup_flags

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write and force parameters from get_user_pages_remote()
and replaces them with a gup_flags parameter to make the use of FOLL_FORCE
explicit in callers as use of this flag can result in surprising behaviour (and
hence bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 drivers/gpu/drm/etnaviv/etnaviv_gem.c   |  7 +--
 drivers/gpu/drm/i915/i915_gem_userptr.c |  6 +-
 drivers/infiniband/core/umem_odp.c  |  7 +--
 fs/exec.c   |  9 +++--
 include/linux/mm.h  |  2 +-
 kernel/events/uprobes.c |  6 --
 mm/gup.c| 22 +++---
 mm/memory.c |  6 +-
 security/tomoyo/domain.c|  2 +-
 9 files changed, 40 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c 
b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 5ce3603..0370b84 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -748,19 +748,22 @@ static struct page **etnaviv_gem_userptr_do_get_pages(
int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
struct page **pvec;
uintptr_t ptr;
+   unsigned int flags = 0;
 
pvec = drm_malloc_ab(npages, sizeof(struct page *));
if (!pvec)
return ERR_PTR(-ENOMEM);
 
+   if (!etnaviv_obj->userptr.ro)
+   flags |= FOLL_WRITE;
+
pinned = 0;
ptr = etnaviv_obj->userptr.ptr;
 
down_read(>mmap_sem);
while (pinned < npages) {
ret = get_user_pages_remote(task, mm, ptr, npages - pinned,
-   !etnaviv_obj->userptr.ro, 0,
-   pvec + pinned, NULL);
+   flags, pvec + pinned, NULL);
if (ret < 0)
break;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c 
b/drivers/gpu/drm/i915/i915_gem_userptr.c
index e537930..c6f780f 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -508,6 +508,10 @@ __i915_gem_userptr_get_pages_worker(struct work_struct 
*_work)
pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY);
if (pvec != NULL) {
struct mm_struct *mm = obj->userptr.mm->mm;
+   unsigned int flags = 0;
+
+   if (!obj->userptr.read_only)
+   flags |= FOLL_WRITE;
 
ret = -EFAULT;
if (atomic_inc_not_zero(>mm_users)) {
@@ -517,7 +521,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct 
*_work)
(work->task, mm,
 obj->userptr.ptr + pinned * PAGE_SIZE,
 npages - pinned,
-!obj->userptr.read_only, 0,
+flags,
 pvec + pinned, NULL);
if (ret < 0)
break;
diff --git a/drivers/infiniband/core/umem_odp.c 
b/drivers/infiniband/core/umem_odp.c
index 75077a0..1f0fe32 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -527,6 +527,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 
user_virt, u64 bcnt,
u64 off;
int j, k, ret = 0, start_idx, npages = 0;
u64 base_virt_addr;
+   unsigned int flags = 0;
 
if (access_mask == 0)
return -EINVAL;
@@ -556,6 +557,9 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 
user_virt, u64 bcnt,
goto out_put_task;
}
 
+   if (access_mask & ODP_WRITE_ALLOWED_BIT)
+   flags |= FOLL_WRITE;
+
start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
k = start_idx;
 
@@ -574,8 +578,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 
user_virt, u64 bcnt,
 */
npages = get_user_pages_remote(owning_process, owning_mm,
user_virt, gup_num_pages,
-   access_mask & ODP_WRITE_ALLOWED_BIT,
-   0, local_page_list, NULL);
+   flags, local_page_list, NULL);
up_read(_mm->mmap_sem);
 
if (npages < 0)
diff --git a/fs/exec.c b/fs/exec.c
index 6fcfb3f..4e497b9 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -191,6 +191,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, 
unsigned long pos,
 {
struct page *page;
int ret;
+   unsigned int gup_flags = FOLL_FORCE;
 
 #ifdef CONFIG_STACK_GROWSUP
if (write) {
@@ -199,12 +200,16 @@ static struct page *get_arg_page(struct linux_binprm 
*bprm, unsigned 

Re: [Open-FCoE] Issue with fc_exch_alloc failing initiated by fc_queuecommand on NUMA or large configurations with Intel ixgbe running FCOE

2016-10-12 Thread Laurence Oberman


- Original Message -
> From: "Hannes Reinecke" 
> To: emi...@redhat.com, "vasu dev" , "robert w love" 
> 
> Cc: "Laurence Oberman" , "Linux SCSI Mailinglist" 
> ,
> fcoe-de...@open-fcoe.org, "Curtis Taylor (c...@us.ibm.com)" 
> , "Bud Brown" 
> Sent: Wednesday, October 12, 2016 11:46:16 AM
> Subject: Re: [Open-FCoE] Issue with fc_exch_alloc failing initiated by 
> fc_queuecommand on NUMA or large
> configurations with Intel ixgbe running FCOE
> 
> On 10/12/2016 05:26 PM, Ewan D. Milne wrote:
> > On Tue, 2016-10-11 at 10:51 -0400, Ewan D. Milne wrote:
> >> On Sat, 2016-10-08 at 19:35 +0200, Hannes Reinecke wrote:
> >>> You might actually be hitting a limitation in the exchange manager code.
> >>> The libfc exchange manager tries to be really clever and will assign a
> >>> per-cpu exchange manager (probably to increase locality). However, we
> >>> only have a limited number of exchanges, so on large systems we might
> >>> actually run into a exchange starvation problem, where we have in theory
> >>> enough free exchanges, but none for the submitting cpu.
> >>>
> >>> (Personally, the exchange manager code is in urgent need of reworking.
> >>> It should be replaced by the sbitmap code from Omar).
> >>>
> >>> Do check how many free exchanges are actually present for the stalling
> >>> CPU; it might be that you run into a starvation issue.
> >>
> >> We are still looking into this but one thing that looks bad is that
> >> the exchange manager code rounds up the number of CPUs to the next
> >> power of 2 before dividing up the exchange id space (and uses the lsbs
> >> of the xid to extract the CPU when looking up an xid). We have a machine
> >> with 288 CPUs, this code is just begging for a rewrite as it looks to
> >> be wasting most of the limited xid space on ixgbe FCoE.
> >>
> >> Looks like we get 512 offloaded xids on this adapter and 4096-512
> >> non-offloaded xids.  This would give 1 + 7 xids per CPU.  However, I'm
> >> not sure that even 4096 / 288 = 14 would be enough to prevent stalling.
> >>
> >> And, of course, potentially most of the CPUs aren't submitting I/O, so
> >> the whole idea of per-CPU xid space is questionable.
> >>
> >
> > fc_exch_alloc() used to try all the available exchange managers in the
> > list for an available exchange id, but this was changed in 2010 so that
> > if the first matched exchange manager couldn't allocate one, it fails
> > and we end up returning host busy.  This was due to commit:
> >
> > commit 3e22760d4db6fd89e0be46c3d132390a251da9c6
> > Author: Vasu Dev 
> > Date:   Fri Mar 12 16:08:39 2010 -0800
> >
> > [SCSI] libfc: use offload EM instance again instead jumping to next EM
> >
> > Since use of offloads is more efficient than switching
> > to non-offload EM. However kept logic same to call em_match
> > if it is provided in the list of EMs.
> >
> > Converted fc_exch_alloc to inline being now tiny a function
> > and already not an exported libfc API any more.
> >
> > Signed-off-by: Vasu Dev 
> > Signed-off-by: Robert Love 
> > Signed-off-by: James Bottomley 
> >
> > ---
> >
> > Setting the ddp_min module parameter to fcoe to 128MB prevents the ->match
> > function from permitting the use of the offload exchange manager for the
> > frame,
> > and we no longer see the problem with host busy status, since it uses the
> > larger non-offloaded pool.
> >
> Yes, this is also the impression I got from reading the spec.
> The offload pool is mainly designed for large read or write commands, so
> using it for _every_ frame is probably not a good idea.
> And limiting it by the size of the transfers solves the problem quite
> nicely, as a large size typically is only used by read and writes.
> So please send a patch to revert that.
> 
> Cheers,
> 
> Hannes
> --
> Dr. Hannes Reinecke zSeries & Storage
> h...@suse.de+49 911 74053 688
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
> GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
I will revert the commit and test it here in the lab, and then submit the 
revert patch.
Ewan can review.

Thanks
Laurence
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/10] mm: remove write/force parameters from __get_user_pages_unlocked()

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write and force parameters from
__get_user_pages_unlocked() to make the use of FOLL_FORCE explicit in callers as
use of this flag can result in surprising behaviour (and hence bugs) within the
mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 include/linux/mm.h |  3 +--
 mm/gup.c   | 17 +
 mm/nommu.c | 12 +---
 mm/process_vm_access.c |  7 +--
 virt/kvm/async_pf.c|  3 ++-
 virt/kvm/kvm_main.c| 11 ---
 6 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index e9caec6..2db98b6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1285,8 +1285,7 @@ long get_user_pages_locked(unsigned long start, unsigned 
long nr_pages,
int write, int force, struct page **pages, int *locked);
 long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
   unsigned long start, unsigned long nr_pages,
-  int write, int force, struct page **pages,
-  unsigned int gup_flags);
+  struct page **pages, unsigned int gup_flags);
 long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
int write, int force, struct page **pages);
 int get_user_pages_fast(unsigned long start, int nr_pages, int write,
diff --git a/mm/gup.c b/mm/gup.c
index ba83942..3d620dd 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -865,17 +865,11 @@ EXPORT_SYMBOL(get_user_pages_locked);
  */
 __always_inline long __get_user_pages_unlocked(struct task_struct *tsk, struct 
mm_struct *mm,
   unsigned long start, unsigned 
long nr_pages,
-  int write, int force, struct 
page **pages,
-  unsigned int gup_flags)
+  struct page **pages, unsigned 
int gup_flags)
 {
long ret;
int locked = 1;
 
-   if (write)
-   gup_flags |= FOLL_WRITE;
-   if (force)
-   gup_flags |= FOLL_FORCE;
-
down_read(>mmap_sem);
ret = __get_user_pages_locked(tsk, mm, start, nr_pages, pages, NULL,
  , false, gup_flags);
@@ -905,8 +899,15 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
 long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
 int write, int force, struct page **pages)
 {
+   unsigned int flags = FOLL_TOUCH;
+
+   if (write)
+   flags |= FOLL_WRITE;
+   if (force)
+   flags |= FOLL_FORCE;
+
return __get_user_pages_unlocked(current, current->mm, start, nr_pages,
-write, force, pages, FOLL_TOUCH);
+pages, flags);
 }
 EXPORT_SYMBOL(get_user_pages_unlocked);
 
diff --git a/mm/nommu.c b/mm/nommu.c
index 95daf81..925dcc1 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -185,8 +185,7 @@ EXPORT_SYMBOL(get_user_pages_locked);
 
 long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
   unsigned long start, unsigned long nr_pages,
-  int write, int force, struct page **pages,
-  unsigned int gup_flags)
+  struct page **pages, unsigned int gup_flags)
 {
long ret;
down_read(>mmap_sem);
@@ -200,8 +199,15 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
 long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
 int write, int force, struct page **pages)
 {
+   unsigned int flags = 0;
+
+   if (write)
+   flags |= FOLL_WRITE;
+   if (force)
+   flags |= FOLL_FORCE;
+
return __get_user_pages_unlocked(current, current->mm, start, nr_pages,
-write, force, pages, 0);
+pages, flags);
 }
 EXPORT_SYMBOL(get_user_pages_unlocked);
 
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
index 07514d4..be8dc8d 100644
--- a/mm/process_vm_access.c
+++ b/mm/process_vm_access.c
@@ -88,12 +88,16 @@ static int process_vm_rw_single_vec(unsigned long addr,
ssize_t rc = 0;
unsigned long max_pages_per_loop = PVM_MAX_KMALLOC_PAGES
/ sizeof(struct pages *);
+   unsigned int flags = FOLL_REMOTE;
 
/* Work out address and page range required */
if (len == 0)
return 0;
nr_pages = (addr + len - 1) / PAGE_SIZE - addr / PAGE_SIZE + 1;
 
+   if (vm_write)
+   flags |= FOLL_WRITE;
+
while (!rc && nr_pages && iov_iter_count(iter)) {
int pages = min(nr_pages, max_pages_per_loop);
size_t bytes;
@@ -104,8 

[PATCH 00/10] mm: adjust get_user_pages* functions to explicitly pass FOLL_* flags

2016-10-12 Thread Lorenzo Stoakes
This patch series adjusts functions in the get_user_pages* family such that
desired FOLL_* flags are passed as an argument rather than implied by flags.

The purpose of this change is to make the use of FOLL_FORCE explicit so it is
easier to grep for and clearer to callers that this flag is being used. The use
of FOLL_FORCE is an issue as it overrides missing VM_READ/VM_WRITE flags for the
VMA whose pages we are reading from/writing to, which can result in surprising
behaviour.

The patch series came out of the discussion around commit 38e0885, which
addressed a BUG_ON() being triggered when a page was faulted in with PROT_NONE
set but having been overridden by FOLL_FORCE. do_numa_page() was run on the
assumption the page _must_ be one marked for NUMA node migration as an actual
PROT_NONE page would have been dealt with prior to this code path, however
FOLL_FORCE introduced a situation where this assumption did not hold.

See https://marc.info/?l=linux-mm=147585445805166 for the patch proposal.

Lorenzo Stoakes (10):
  mm: remove write/force parameters from __get_user_pages_locked()
  mm: remove write/force parameters from __get_user_pages_unlocked()
  mm: replace get_user_pages_unlocked() write/force parameters with gup_flags
  mm: replace get_user_pages_locked() write/force parameters with gup_flags
  mm: replace get_vaddr_frames() write/force parameters with gup_flags
  mm: replace get_user_pages() write/force parameters with gup_flags
  mm: replace get_user_pages_remote() write/force parameters with gup_flags
  mm: replace __access_remote_vm() write parameter with gup_flags
  mm: replace access_remote_vm() write parameter with gup_flags
  mm: replace access_process_vm() write parameter with gup_flags

 arch/alpha/kernel/ptrace.c |  9 ++--
 arch/blackfin/kernel/ptrace.c  |  5 ++-
 arch/cris/arch-v32/drivers/cryptocop.c |  4 +-
 arch/cris/arch-v32/kernel/ptrace.c |  4 +-
 arch/ia64/kernel/err_inject.c  |  2 +-
 arch/ia64/kernel/ptrace.c  | 14 +++---
 arch/m32r/kernel/ptrace.c  | 15 ---
 arch/mips/kernel/ptrace32.c|  5 ++-
 arch/mips/mm/gup.c |  2 +-
 arch/powerpc/kernel/ptrace32.c |  5 ++-
 arch/s390/mm/gup.c |  3 +-
 arch/score/kernel/ptrace.c | 10 +++--
 arch/sh/mm/gup.c   |  3 +-
 arch/sparc/kernel/ptrace_64.c  | 24 +++
 arch/sparc/mm/gup.c|  3 +-
 arch/x86/kernel/step.c |  3 +-
 arch/x86/mm/gup.c  |  2 +-
 arch/x86/mm/mpx.c  |  5 +--
 arch/x86/um/ptrace_32.c|  3 +-
 arch/x86/um/ptrace_64.c|  3 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c|  7 ++-
 drivers/gpu/drm/etnaviv/etnaviv_gem.c  |  7 ++-
 drivers/gpu/drm/exynos/exynos_drm_g2d.c|  3 +-
 drivers/gpu/drm/i915/i915_gem_userptr.c|  6 ++-
 drivers/gpu/drm/radeon/radeon_ttm.c|  3 +-
 drivers/gpu/drm/via/via_dmablit.c  |  4 +-
 drivers/infiniband/core/umem.c |  6 ++-
 drivers/infiniband/core/umem_odp.c |  7 ++-
 drivers/infiniband/hw/mthca/mthca_memfree.c|  2 +-
 drivers/infiniband/hw/qib/qib_user_pages.c |  3 +-
 drivers/infiniband/hw/usnic/usnic_uiom.c   |  5 ++-
 drivers/media/pci/ivtv/ivtv-udma.c |  4 +-
 drivers/media/pci/ivtv/ivtv-yuv.c  |  5 ++-
 drivers/media/platform/omap/omap_vout.c|  2 +-
 drivers/media/v4l2-core/videobuf-dma-sg.c  |  7 ++-
 drivers/media/v4l2-core/videobuf2-memops.c |  6 ++-
 drivers/misc/mic/scif/scif_rma.c   |  3 +-
 drivers/misc/sgi-gru/grufault.c|  2 +-
 drivers/platform/goldfish/goldfish_pipe.c  |  3 +-
 drivers/rapidio/devices/rio_mport_cdev.c   |  3 +-
 drivers/scsi/st.c  |  5 +--
 .../interface/vchiq_arm/vchiq_2835_arm.c   |  3 +-
 .../vc04_services/interface/vchiq_arm/vchiq_arm.c  |  3 +-
 drivers/video/fbdev/pvr2fb.c   |  4 +-
 drivers/virt/fsl_hypervisor.c  |  4 +-
 fs/exec.c  |  9 +++-
 fs/proc/base.c | 19 +---
 include/linux/mm.h | 18 
 kernel/events/uprobes.c|  6 ++-
 kernel/ptrace.c| 16 ---
 mm/frame_vector.c  |  9 ++--
 mm/gup.c   | 50 ++
 mm/memory.c| 16 ---

[PATCH 01/10] mm: remove write/force parameters from __get_user_pages_locked()

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write and force parameters from __get_user_pages_locked()
to make the use of FOLL_FORCE explicit in callers as use of this flag can result
in surprising behaviour (and hence bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 mm/gup.c | 47 +--
 1 file changed, 33 insertions(+), 14 deletions(-)

diff --git a/mm/gup.c b/mm/gup.c
index 96b2b2f..ba83942 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -729,7 +729,6 @@ static __always_inline long __get_user_pages_locked(struct 
task_struct *tsk,
struct mm_struct *mm,
unsigned long start,
unsigned long nr_pages,
-   int write, int force,
struct page **pages,
struct vm_area_struct **vmas,
int *locked, bool notify_drop,
@@ -747,10 +746,6 @@ static __always_inline long __get_user_pages_locked(struct 
task_struct *tsk,
 
if (pages)
flags |= FOLL_GET;
-   if (write)
-   flags |= FOLL_WRITE;
-   if (force)
-   flags |= FOLL_FORCE;
 
pages_done = 0;
lock_dropped = false;
@@ -846,9 +841,15 @@ long get_user_pages_locked(unsigned long start, unsigned 
long nr_pages,
   int write, int force, struct page **pages,
   int *locked)
 {
+   unsigned int flags = FOLL_TOUCH;
+
+   if (write)
+   flags |= FOLL_WRITE;
+   if (force)
+   flags |= FOLL_FORCE;
+
return __get_user_pages_locked(current, current->mm, start, nr_pages,
-  write, force, pages, NULL, locked, true,
-  FOLL_TOUCH);
+  pages, NULL, locked, true, flags);
 }
 EXPORT_SYMBOL(get_user_pages_locked);
 
@@ -869,9 +870,15 @@ __always_inline long __get_user_pages_unlocked(struct 
task_struct *tsk, struct m
 {
long ret;
int locked = 1;
+
+   if (write)
+   gup_flags |= FOLL_WRITE;
+   if (force)
+   gup_flags |= FOLL_FORCE;
+
down_read(>mmap_sem);
-   ret = __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
- pages, NULL, , false, gup_flags);
+   ret = __get_user_pages_locked(tsk, mm, start, nr_pages, pages, NULL,
+ , false, gup_flags);
if (locked)
up_read(>mmap_sem);
return ret;
@@ -963,9 +970,15 @@ long get_user_pages_remote(struct task_struct *tsk, struct 
mm_struct *mm,
int write, int force, struct page **pages,
struct vm_area_struct **vmas)
 {
-   return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
-  pages, vmas, NULL, false,
-  FOLL_TOUCH | FOLL_REMOTE);
+   unsigned int flags = FOLL_TOUCH | FOLL_REMOTE;
+
+   if (write)
+   flags |= FOLL_WRITE;
+   if (force)
+   flags |= FOLL_FORCE;
+
+   return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas,
+  NULL, false, flags);
 }
 EXPORT_SYMBOL(get_user_pages_remote);
 
@@ -979,9 +992,15 @@ long get_user_pages(unsigned long start, unsigned long 
nr_pages,
int write, int force, struct page **pages,
struct vm_area_struct **vmas)
 {
+   unsigned int flags = FOLL_TOUCH;
+
+   if (write)
+   flags |= FOLL_WRITE;
+   if (force)
+   flags |= FOLL_FORCE;
+
return __get_user_pages_locked(current, current->mm, start, nr_pages,
-  write, force, pages, vmas, NULL, false,
-  FOLL_TOUCH);
+  pages, vmas, NULL, false, flags);
 }
 EXPORT_SYMBOL(get_user_pages);
 
-- 
2.10.0

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/10] mm: replace get_user_pages_unlocked() write/force parameters with gup_flags

2016-10-12 Thread Lorenzo Stoakes
This patch removes the write and force parameters from get_user_pages_unlocked()
and replaces them with a gup_flags parameter to make the use of FOLL_FORCE
explicit in callers as use of this flag can result in surprising behaviour (and
hence bugs) within the mm subsystem.

Signed-off-by: Lorenzo Stoakes 
---
 arch/mips/mm/gup.c |  2 +-
 arch/s390/mm/gup.c |  3 ++-
 arch/sh/mm/gup.c   |  3 ++-
 arch/sparc/mm/gup.c|  3 ++-
 arch/x86/mm/gup.c  |  2 +-
 drivers/media/pci/ivtv/ivtv-udma.c |  4 ++--
 drivers/media/pci/ivtv/ivtv-yuv.c  |  5 +++--
 drivers/scsi/st.c  |  5 ++---
 drivers/video/fbdev/pvr2fb.c   |  4 ++--
 include/linux/mm.h |  2 +-
 mm/gup.c   | 14 --
 mm/nommu.c | 11 ++-
 mm/util.c  |  3 ++-
 net/ceph/pagevec.c |  2 +-
 14 files changed, 27 insertions(+), 36 deletions(-)

diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c
index 42d124f..d8c3c15 100644
--- a/arch/mips/mm/gup.c
+++ b/arch/mips/mm/gup.c
@@ -287,7 +287,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, 
int write,
pages += nr;
 
ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT,
- write, 0, pages);
+ pages, write ? FOLL_WRITE : 0);
 
/* Have to be a bit careful with return values */
if (nr > 0) {
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
index adb0c34..18d4107 100644
--- a/arch/s390/mm/gup.c
+++ b/arch/s390/mm/gup.c
@@ -266,7 +266,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, 
int write,
/* Try to get the remaining pages with get_user_pages */
start += nr << PAGE_SHIFT;
pages += nr;
-   ret = get_user_pages_unlocked(start, nr_pages - nr, write, 0, pages);
+   ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
+ write ? FOLL_WRITE : 0);
/* Have to be a bit careful with return values */
if (nr > 0)
ret = (ret < 0) ? nr : ret + nr;
diff --git a/arch/sh/mm/gup.c b/arch/sh/mm/gup.c
index 40fa6c8..063c298 100644
--- a/arch/sh/mm/gup.c
+++ b/arch/sh/mm/gup.c
@@ -258,7 +258,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, 
int write,
pages += nr;
 
ret = get_user_pages_unlocked(start,
-   (end - start) >> PAGE_SHIFT, write, 0, pages);
+   (end - start) >> PAGE_SHIFT, pages,
+   write ? FOLL_WRITE : 0);
 
/* Have to be a bit careful with return values */
if (nr > 0) {
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c
index 4e06750..cd0e32b 100644
--- a/arch/sparc/mm/gup.c
+++ b/arch/sparc/mm/gup.c
@@ -238,7 +238,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, 
int write,
pages += nr;
 
ret = get_user_pages_unlocked(start,
-   (end - start) >> PAGE_SHIFT, write, 0, pages);
+   (end - start) >> PAGE_SHIFT, pages,
+   write ? FOLL_WRITE : 0);
 
/* Have to be a bit careful with return values */
if (nr > 0) {
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
index b8b6a60..0d4fb3e 100644
--- a/arch/x86/mm/gup.c
+++ b/arch/x86/mm/gup.c
@@ -435,7 +435,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, 
int write,
 
ret = get_user_pages_unlocked(start,
  (end - start) >> PAGE_SHIFT,
- write, 0, pages);
+ pages, write ? FOLL_WRITE : 0);
 
/* Have to be a bit careful with return values */
if (nr > 0) {
diff --git a/drivers/media/pci/ivtv/ivtv-udma.c 
b/drivers/media/pci/ivtv/ivtv-udma.c
index 4769469..2c9232e 100644
--- a/drivers/media/pci/ivtv/ivtv-udma.c
+++ b/drivers/media/pci/ivtv/ivtv-udma.c
@@ -124,8 +124,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long 
ivtv_dest_addr,
}
 
/* Get user pages for DMA Xfer */
-   err = get_user_pages_unlocked(user_dma.uaddr, user_dma.page_count, 0,
-   1, dma->map);
+   err = get_user_pages_unlocked(user_dma.uaddr, user_dma.page_count,
+   dma->map, FOLL_FORCE);
 
if (user_dma.page_count != err) {
IVTV_DEBUG_WARN("failed to map user pages, returned %d instead 
of %d\n",
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c 
b/drivers/media/pci/ivtv/ivtv-yuv.c
index b094054..f7299d3 100644
--- a/drivers/media/pci/ivtv/ivtv-yuv.c
+++ b/drivers/media/pci/ivtv/ivtv-yuv.c
@@ -76,11 +76,12 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct 

[PATCH 12/17 v2] lpfc: Revise strings with full lpfc parameter name

2016-10-12 Thread James Smart

Revise strings with full lpfc parameter name

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_attr.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 1b6090c..3740e5d 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -2877,9 +2877,9 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val)
vport->cfg_nodev_tmo = vport->cfg_devloss_tmo;
if (val != LPFC_DEF_DEVLOSS_TMO)
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-"0407 Ignoring nodev_tmo module "
-"parameter because devloss_tmo is "
-"set.\n");
+"0407 Ignoring lpfc_nodev_tmo module "
+"parameter because lpfc_devloss_tmo "
+"is set.\n");
return 0;
}
 
@@ -2938,8 +2938,8 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
if (vport->dev_loss_tmo_changed ||
(lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-"0401 Ignoring change to nodev_tmo "
-"because devloss_tmo is set.\n");
+"0401 Ignoring change to lpfc_nodev_tmo "
+"because lpfc_devloss_tmo is set.\n");
return 0;
}
if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
@@ -2954,7 +2954,7 @@ lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val)
return 0;
}
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-"0403 lpfc_nodev_tmo attribute cannot be set to"
+"0403 lpfc_nodev_tmo attribute cannot be set to "
 "%d, allowed range is [%d, %d]\n",
 val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);
return -EINVAL;
@@ -3005,8 +3005,8 @@ lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val)
}
 
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-"0404 lpfc_devloss_tmo attribute cannot be set to"
-" %d, allowed range is [%d, %d]\n",
+"0404 lpfc_devloss_tmo attribute cannot be set to "
+"%d, allowed range is [%d, %d]\n",
 val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO);
return -EINVAL;
 }
@@ -4174,7 +4174,8 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val)
}
 
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-   "3016 fcp_imax: %d out of range, using default\n", val);
+   "3016 lpfc_fcp_imax: %d out of range, using default\n",
+   val);
phba->cfg_fcp_imax = LPFC_DEF_IMAX;
 
return 0;
@@ -4324,8 +4325,8 @@ lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val)
}
 
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-   "3326 fcp_cpu_map: %d out of range, using default\n",
-   val);
+   "3326 lpfc_fcp_cpu_map: %d out of range, using "
+   "default\n", val);
phba->cfg_fcp_cpu_map = LPFC_DRIVER_CPU_MAP;
 
return 0;
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/17 v2] lpfc: Correct embedded io wq element size

2016-10-12 Thread James Smart

Correct embedded io wq element size. Embedded element sizes are
128 byte elements

Modified per review:
change style of selecting wqesize using local variable

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_init.c | 14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 734a042..af64d70 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -7256,6 +7256,7 @@ int
 lpfc_sli4_queue_create(struct lpfc_hba *phba)
 {
struct lpfc_queue *qdesc;
+   uint32_t wqesize;
int idx;
 
/*
@@ -7340,15 +7341,10 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
phba->sli4_hba.fcp_cq[idx] = qdesc;
 
/* Create Fast Path FCP WQs */
-   if (phba->fcp_embed_io) {
-   qdesc = lpfc_sli4_queue_alloc(phba,
- LPFC_WQE128_SIZE,
- LPFC_WQE128_DEF_COUNT);
-   } else {
-   qdesc = lpfc_sli4_queue_alloc(phba,
- phba->sli4_hba.wq_esize,
- phba->sli4_hba.wq_ecount);
-   }
+   wqesize = (phba->fcp_embed_io) ?
+   LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize;
+   qdesc = lpfc_sli4_queue_alloc(phba, wqesize,
+   phba->sli4_hba.wq_ecount);
if (!qdesc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"0503 Failed allocate fast-path FCP "
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 13/17 v2] lpfc: Fix lost target in pt-to-pt connect

2016-10-12 Thread James Smart

Fix lost target in pt-to-pt connect

Change reject code to something that allows a retry

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_els.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index b7d54bf..236e4e5 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -7610,7 +7610,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
/* reject till our FLOGI completes */
if ((vport->port_state < LPFC_FABRIC_CFG_LINK) &&
(cmd != ELS_CMD_FLOGI)) {
-   rjt_err = LSRJT_UNABLE_TPC;
+   rjt_err = LSRJT_LOGICAL_BSY;
rjt_exp = LSEXP_NOTHING_MORE;
goto lsrjt;
}
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/17 v2] lpfc: Code cleanup for lpfc_sriov_nr_virtfn parameter

2016-10-12 Thread James Smart

Code cleanup for lpfc_sriov_nr_virtfn parameter

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_attr.c | 35 +++
 1 file changed, 3 insertions(+), 32 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 3051e66..1b6090c 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -4007,39 +4007,10 @@ lpfc_sriov_nr_virtfn_store(struct device *dev, struct 
device_attribute *attr,
return rc;
 }
 
-static int lpfc_sriov_nr_virtfn = LPFC_DEF_VFN_PER_PFN;
-module_param(lpfc_sriov_nr_virtfn, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(lpfc_sriov_nr_virtfn, "Enable PCIe device SR-IOV virtual fn");
-lpfc_param_show(sriov_nr_virtfn)
+LPFC_ATTR(sriov_nr_virtfn, LPFC_DEF_VFN_PER_PFN, 0, LPFC_MAX_VFN_PER_PFN,
+   "Enable PCIe device SR-IOV virtual fn");
 
-/**
- * lpfc_sriov_nr_virtfn_init - Set the initial sr-iov virtual function enable
- * @phba: lpfc_hba pointer.
- * @val: link speed value.
- *
- * Description:
- * If val is in a valid range [0,255], then set the adapter's initial
- * cfg_sriov_nr_virtfn field. If it's greater than the maximum, the maximum
- * number shall be used instead. It will be up to the driver's probe_one
- * routine to determine whether the device's SR-IOV is supported or not.
- *
- * Returns:
- * zero if val saved.
- * -EINVAL val out of range
- **/
-static int
-lpfc_sriov_nr_virtfn_init(struct lpfc_hba *phba, int val)
-{
-   if (val >= 0 && val <= LPFC_MAX_VFN_PER_PFN) {
-   phba->cfg_sriov_nr_virtfn = val;
-   return 0;
-   }
-
-   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-   "3017 Enabling %d virtual functions is not "
-   "allowed.\n", val);
-   return -EINVAL;
-}
+lpfc_param_show(sriov_nr_virtfn)
 static DEVICE_ATTR(lpfc_sriov_nr_virtfn, S_IRUGO | S_IWUSR,
   lpfc_sriov_nr_virtfn_show, lpfc_sriov_nr_virtfn_store);
 
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 17/17 v2] lpfc: lpfc version changed to 11.2.0.2

2016-10-12 Thread James Smart

lpfc version changed to 11.2.0.2

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index c9bf20e..50bfc43 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "11.2.0.0."
+#define LPFC_DRIVER_VERSION "11.2.0.2"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 16/17 v2] lpfc: Fix fw download on SLI-4 FC adapters

2016-10-12 Thread James Smart

Fix fw download on SLI-4 FC adapters

Driver performs a quick validation of magic numbers in the fw
download image. Driver needed to be updated for more recent
magic numbers.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_hw4.h  |  3 ++-
 drivers/scsi/lpfc/lpfc_init.c | 15 ---
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index bbdcb5a..5646699 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -3996,7 +3996,8 @@ union lpfc_wqe128 {
struct gen_req64_wqe gen_req;
 };
 
-#define LPFC_GROUP_OJECT_MAGIC_NUM 0xfeaa0001
+#define LPFC_GROUP_OJECT_MAGIC_G5  0xfeaa0001
+#define LPFC_GROUP_OJECT_MAGIC_G6  0xfeaa0003
 #define LPFC_FILE_TYPE_GROUP   0xf7
 #define LPFC_FILE_ID_GROUP 0xa2
 struct lpfc_grp_hdr {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 53227e5..442bbb8 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -10321,17 +10321,18 @@ lpfc_write_firmware(const struct firmware *fw, void 
*context)
image = (struct lpfc_grp_hdr *)fw->data;
 
INIT_LIST_HEAD(_buffer_list);
-   if ((be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_NUM) ||
-   (bf_get_be32(lpfc_grp_hdr_file_type, image) !=
-LPFC_FILE_TYPE_GROUP) ||
-   (bf_get_be32(lpfc_grp_hdr_id, image) != LPFC_FILE_ID_GROUP) ||
-   (be32_to_cpu(image->size) != fw->size)) {
+   if (((be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_G5) &&
+(be32_to_cpu(image->magic_number) != LPFC_GROUP_OJECT_MAGIC_G6)) ||
+  (bf_get_be32(lpfc_grp_hdr_file_type, image) !=
+   LPFC_FILE_TYPE_GROUP) ||
+  (be32_to_cpu(image->size) != fw->size)) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3022 Invalid FW image found. "
-   "Magic:%x Type:%x ID:%x\n",
+   "Magic:%x Type:%x ID:%x Size %d %ld\n",
be32_to_cpu(image->magic_number),
bf_get_be32(lpfc_grp_hdr_file_type, image),
-   bf_get_be32(lpfc_grp_hdr_id, image));
+   bf_get_be32(lpfc_grp_hdr_id, image),
+   be32_to_cpu(image->size), fw->size);
rc = -EINVAL;
goto release_out;
}
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/17 v2] lpfc: Correct panics with eh_timeout and eh_deadline

2016-10-12 Thread James Smart

Correct panics with eh_timeout and eh_deadline

We were having double completions on our SLI-3 version of adapters.
Solved by clearing our command pointer before calling scsi_done.

The eh paths potentially ran simulatenously and would see the non-null
value and invoke scsi_done again.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_scsi.c |  6 +++---
 drivers/scsi/lpfc/lpfc_sli.c  | 12 
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 4c53149e..1b0ef79 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4142,13 +4142,13 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct 
lpfc_iocbq *pIocbIn,
 
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
 
-   /* The sdev is not guaranteed to be valid post scsi_done upcall. */
-   cmd->scsi_done(cmd);
-
spin_lock_irqsave(>hbalock, flags);
lpfc_cmd->pCmd = NULL;
spin_unlock_irqrestore(>hbalock, flags);
 
+   /* The sdev is not guaranteed to be valid post scsi_done upcall. */
+   cmd->scsi_done(cmd);
+
/*
 * If there is a thread waiting for command completion
 * wake up the thread.
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index cb59f4e..27cbd68 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -2677,15 +2677,16 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
 
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
cmd_iocb = phba->sli.iocbq_lookup[iotag];
-   list_del_init(_iocb->list);
if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) {
+   /* remove from txcmpl queue list */
+   list_del_init(_iocb->list);
cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
+   return cmd_iocb;
}
-   return cmd_iocb;
}
 
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-   "0317 iotag x%x is out off "
+   "0317 iotag x%x is out of "
"range: max iotag x%x wd0 x%x\n",
iotag, phba->sli.last_iotag,
*(((uint32_t *) >iocb) + 7));
@@ -2720,8 +2721,9 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
return cmd_iocb;
}
}
+
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-   "0372 iotag x%x is out off range: max iotag (x%x)\n",
+   "0372 iotag x%x is out of range: max iotag (x%x)\n",
iotag, phba->sli.last_iotag);
return NULL;
 }
@@ -11808,6 +11810,8 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
/* Look up the ELS command IOCB and create pseudo response IOCB */
cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
bf_get(lpfc_wcqe_c_request_tag, wcqe));
+   /* Put the iocb back on the txcmplq */
+   lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq);
spin_unlock_irqrestore(>ring_lock, iflags);
 
if (unlikely(!cmdiocbq)) {
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/17 v2] lpfc: Code cleanup for lpfc_max_scsicmpl_time parameter

2016-10-12 Thread James Smart

Code cleanup for lpfc_max_scsicmpl_time parameter

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_attr.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 81b1faf..3051e66 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -4393,12 +4393,10 @@ LPFC_VPORT_ATTR_RW(first_burst_size, 0, 0, 65536,
 # to limit the I/O completion time to the parameter value.
 # The value is set in milliseconds.
 */
-static int lpfc_max_scsicmpl_time;
-module_param(lpfc_max_scsicmpl_time, int, S_IRUGO);
-MODULE_PARM_DESC(lpfc_max_scsicmpl_time,
+LPFC_VPORT_ATTR(max_scsicmpl_time, 0, 0, 6,
"Use command completion time to control queue depth");
+
 lpfc_vport_param_show(max_scsicmpl_time);
-lpfc_vport_param_init(max_scsicmpl_time, 0, 0, 6);
 static int
 lpfc_max_scsicmpl_time_set(struct lpfc_vport *vport, int val)
 {
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/17 v2] lpfc: Code clean up for lpfc_iocb_cnt parameter

2016-10-12 Thread James Smart

Code clean up for lpfc_iocb_cnt parameter

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_attr.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index be81e61..e5092dc 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -2827,14 +2827,8 @@ lpfc_txcmplq_hw_show(struct device *dev, struct 
device_attribute *attr,
 static DEVICE_ATTR(txcmplq_hw, S_IRUGO,
 lpfc_txcmplq_hw_show, NULL);
 
-int lpfc_iocb_cnt = 2;
-module_param(lpfc_iocb_cnt, int, S_IRUGO);
-MODULE_PARM_DESC(lpfc_iocb_cnt,
+LPFC_ATTR_R(iocb_cnt, 2, 1, 5,
"Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs");
-lpfc_param_show(iocb_cnt);
-lpfc_param_init(iocb_cnt, 2, 1, 5);
-static DEVICE_ATTR(lpfc_iocb_cnt, S_IRUGO,
-lpfc_iocb_cnt_show, NULL);
 
 /*
 # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 15/17 v2] lpfc: Synchronize link speed with boot driver

2016-10-12 Thread James Smart

Synchronize link speed with boot driver

Link speed settings set by the boot driver are reported by the hw.
Driver will attempt to read them, and if set, will respect their
values.
The driver can override the settings with its own if instructed by
user space (via bsg), with the new values being picked up by the
boot driver.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h  |  4 
 drivers/scsi/lpfc/lpfc_attr.c |  7 +-
 drivers/scsi/lpfc/lpfc_bsg.c  | 44 +++
 drivers/scsi/lpfc/lpfc_bsg.h  | 10 
 drivers/scsi/lpfc/lpfc_hw4.h  |  3 +++
 drivers/scsi/lpfc/lpfc_init.c | 54 +++
 6 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index debba5e..8a20b4e 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -648,6 +648,10 @@ struct lpfc_hba {
 #define HBA_FCP_IOQ_FLUSH  0x8000 /* FCP I/O queues being flushed */
 #define HBA_FW_DUMP_OP 0x1 /* Skips fn reset before FW dump */
 #define HBA_RECOVERABLE_UE 0x2 /* Firmware supports recoverable UE */
+#define HBA_FORCED_LINK_SPEED  0x4 /*
+* Firmware supports Forced Link Speed
+* capability
+*/
uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
struct lpfc_dmabuf slim2p;
 
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 3740e5d..39ba01a 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3668,7 +3668,12 @@ lpfc_link_speed_store(struct device *dev, struct 
device_attribute *attr,
int nolip = 0;
const char *val_buf = buf;
int err;
-   uint32_t prev_val;
+   uint32_t prev_val, if_type;
+
+   if_type = bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf);
+   if ((if_type == LPFC_SLI_INTF_IF_TYPE_2) &&
+   (phba->hba_flag & HBA_FORCED_LINK_SPEED))
+   return -EPERM;
 
if (!strncmp(buf, "nolip ", strlen("nolip "))) {
nolip = 1;
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 05dcc2a..f9f5972 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -5185,6 +5185,47 @@ no_dd_data:
return rc;
 }
 
+static int
+lpfc_forced_link_speed(struct fc_bsg_job *job)
+{
+   struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
+   struct lpfc_hba *phba = vport->phba;
+   struct forced_link_speed_support_reply *forced_reply;
+   int rc = 0;
+
+   if (job->request_len <
+   sizeof(struct fc_bsg_request) +
+   sizeof(struct get_forced_link_speed_support)) {
+   lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+   "0048 Received FORCED_LINK_SPEED request "
+   "below minimum size\n");
+   rc = -EINVAL;
+   goto job_error;
+   }
+
+   forced_reply = (struct forced_link_speed_support_reply *)
+   job->reply->reply_data.vendor_reply.vendor_rsp;
+
+   if (job->reply_len <
+   sizeof(struct fc_bsg_request) +
+   sizeof(struct forced_link_speed_support_reply)) {
+   lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
+   "0049 Received FORCED_LINK_SPEED reply below "
+   "minimum size\n");
+   rc = -EINVAL;
+   goto job_error;
+   }
+
+   forced_reply->supported = (phba->hba_flag & HBA_FORCED_LINK_SPEED)
+  ? LPFC_FORCED_LINK_SPEED_SUPPORTED
+  : LPFC_FORCED_LINK_SPEED_NOT_SUPPORTED;
+job_error:
+   job->reply->result = rc;
+   if (rc == 0)
+   job->job_done(job);
+   return rc;
+}
+
 /**
  * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
  * @job: fc_bsg_job to handle
@@ -5227,6 +5268,9 @@ lpfc_bsg_hst_vendor(struct fc_bsg_job *job)
case LPFC_BSG_VENDOR_MENLO_DATA:
rc = lpfc_menlo_cmd(job);
break;
+   case LPFC_BSG_VENDOR_FORCED_LINK_SPEED:
+   rc = lpfc_forced_link_speed(job);
+   break;
default:
rc = -EINVAL;
job->reply->reply_payload_rcv_len = 0;
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h
index e557bcd..f2247aa 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.h
+++ b/drivers/scsi/lpfc/lpfc_bsg.h
@@ -35,6 +35,7 @@
 #define LPFC_BSG_VENDOR_MENLO_DATA 9
 #define LPFC_BSG_VENDOR_DIAG_MODE_END  10
 #define LPFC_BSG_VENDOR_LINK_DIAG_TEST 11
+#define LPFC_BSG_VENDOR_FORCED_LINK_SPEED  14
 
 struct set_ct_event {
uint32_t 

[PATCH 07/17 v2] lpfc: Code cleanup for lpfc_enable_rrq parameter

2016-10-12 Thread James Smart

Code cleanup for lpfc_enable_rrq parameter

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_attr.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index e5092dc..22a66c7 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -2759,18 +2759,14 @@ LPFC_ATTR_R(enable_npiv, 1, 0, 1,
 LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2,
"FCF Fast failover=1 Priority failover=2");
 
-int lpfc_enable_rrq = 2;
-module_param(lpfc_enable_rrq, int, S_IRUGO);
-MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
-lpfc_param_show(enable_rrq);
 /*
 # lpfc_enable_rrq: Track XRI/OXID reuse after IO failures
 #  0x0 = disabled, XRI/OXID use not tracked.
 #  0x1 = XRI/OXID reuse is timed with ratov, RRQ sent.
 #  0x2 = XRI/OXID reuse is timed with ratov, No RRQ sent.
 */
-lpfc_param_init(enable_rrq, 2, 0, 2);
-static DEVICE_ATTR(lpfc_enable_rrq, S_IRUGO, lpfc_enable_rrq_show, NULL);
+LPFC_ATTR_R(enable_rrq, 2, 0, 2,
+   "Enable RRQ functionality");
 
 /*
 # lpfc_suppress_link_up:  Bring link up at initialization
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/17 v2] lpfc: Code cleanup for lpfc_topology parameter

2016-10-12 Thread James Smart

Code cleanup for lpfc_topology parameter

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_attr.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index ae76aaa..81b1faf 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3194,6 +3194,8 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1,
 # Set loop mode if you want to run as an NL_Port. Value range is [0,0x6].
 # Default value is 0.
 */
+LPFC_ATTR(topology, 0, 0, 6,
+   "Select Fibre Channel topology");
 
 /**
  * lpfc_topology_set - Set the adapters topology field
@@ -3271,11 +3273,8 @@ lpfc_topology_store(struct device *dev, struct 
device_attribute *attr,
phba->brd_no, val);
return -EINVAL;
 }
-static int lpfc_topology = 0;
-module_param(lpfc_topology, int, S_IRUGO);
-MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");
+
 lpfc_param_show(topology)
-lpfc_param_init(topology, 0, 0, 6)
 static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
lpfc_topology_show, lpfc_topology_store);
 
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/17 v2] lpfc: Code cleanup for lpfc_aer_support parameter

2016-10-12 Thread James Smart

Code cleanup for lpfc_aer_support parameter

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_attr.c | 43 +++
 1 file changed, 3 insertions(+), 40 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 22a66c7..ae76aaa 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3779,6 +3779,9 @@ static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
 #   1  = aer supported and enabled (default)
 # Value range is [0,1]. Default value is 1.
 */
+LPFC_ATTR(aer_support, 1, 0, 1,
+   "Enable PCIe device AER support");
+lpfc_param_show(aer_support)
 
 /**
  * lpfc_aer_support_store - Set the adapter for aer support
@@ -3861,46 +3864,6 @@ lpfc_aer_support_store(struct device *dev, struct 
device_attribute *attr,
return rc;
 }
 
-static int lpfc_aer_support = 1;
-module_param(lpfc_aer_support, int, S_IRUGO);
-MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support");
-lpfc_param_show(aer_support)
-
-/**
- * lpfc_aer_support_init - Set the initial adapters aer support flag
- * @phba: lpfc_hba pointer.
- * @val: enable aer or disable aer flag.
- *
- * Description:
- * If val is in a valid range [0,1], then set the adapter's initial
- * cfg_aer_support field. It will be up to the driver's probe_one
- * routine to determine whether the device's AER support can be set
- * or not.
- *
- * Notes:
- * If the value is not in range log a kernel error message, and
- * choose the default value of setting AER support and return.
- *
- * Returns:
- * zero if val saved.
- * -EINVAL val out of range
- **/
-static int
-lpfc_aer_support_init(struct lpfc_hba *phba, int val)
-{
-   if (val == 0 || val == 1) {
-   phba->cfg_aer_support = val;
-   return 0;
-   }
-   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-   "2712 lpfc_aer_support attribute value %d out "
-   "of range, allowed values are 0|1, setting it "
-   "to default value of 1\n", val);
-   /* By default, try to enable AER on a device */
-   phba->cfg_aer_support = 1;
-   return -EINVAL;
-}
-
 static DEVICE_ATTR(lpfc_aer_support, S_IRUGO | S_IWUSR,
   lpfc_aer_support_show, lpfc_aer_support_store);
 
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/17 v2] Fix few small typos in lpfc_scsi.c

2016-10-12 Thread James Smart

From: "Milan P. Gandhi" 

This patch does a cleanup and fixes few small typos in lpfc_scsi.c

Signed-off-by: Milan P. Gandhi 
Signed-off-by: James Smart 
---
 
 drivers/scsi/lpfc/lpfc_scsi.c | 21 -
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index d197aa1..ca56f28 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -607,7 +607,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
 }
 
 /**
- * lpfc_sli4_post_scsi_sgl_list - Psot blocks of scsi buffer sgls from a list
+ * lpfc_sli4_post_scsi_sgl_list - Post blocks of scsi buffer sgls from a list
  * @phba: pointer to lpfc hba data structure.
  * @post_sblist: pointer to the scsi buffer list.
  *
@@ -736,7 +736,7 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
 }
 
 /**
- * lpfc_sli4_repost_scsi_sgl_list - Repsot all the allocated scsi buffer sgls
+ * lpfc_sli4_repost_scsi_sgl_list - Repost all the allocated scsi buffer sgls
  * @phba: pointer to lpfc hba data structure.
  *
  * This routine walks the list of scsi buffers that have been allocated and
@@ -857,7 +857,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int 
num_to_alloc)
psb->data, psb->dma_handle);
kfree(psb);
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-   "3368 Failed to allocated IOTAG for"
+   "3368 Failed to allocate IOTAG for"
" XRI:0x%x\n", lxri);
lpfc_sli4_free_xri(phba, lxri);
break;
@@ -1136,7 +1136,7 @@ lpfc_release_scsi_buf(struct lpfc_hba *phba, struct 
lpfc_scsi_buf *psb)
  *
  * This routine does the pci dma mapping for scatter-gather list of scsi cmnd
  * field of @lpfc_cmd for device with SLI-3 interface spec. This routine scans
- * through sg elements and format the bdea. This routine also initializes all
+ * through sg elements and format the bde. This routine also initializes all
  * IOCB fields which are dependent on scsi command request buffer.
  *
  * Return codes:
@@ -1269,13 +1269,16 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct 
lpfc_scsi_buf *lpfc_cmd)
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
 
-/* Return if if error injection is detected by Initiator */
+/* Return BG_ERR_INIT if error injection is detected by Initiator */
 #define BG_ERR_INIT0x1
-/* Return if if error injection is detected by Target */
+/* Return BG_ERR_TGT if error injection is detected by Target */
 #define BG_ERR_TGT 0x2
-/* Return if if swapping CSUM<-->CRC is required for error injection */
+/* Return BG_ERR_SWAP if swapping CSUM<-->CRC is required for error injection 
*/
 #define BG_ERR_SWAP0x10
-/* Return if disabling Guard/Ref/App checking is required for error injection 
*/
+/**
+ * Return BG_ERR_CHECK if disabling Guard/Ref/App checking is required for
+ * error injection
+ **/
 #define BG_ERR_CHECK   0x20
 
 /**
@@ -4822,7 +4825,7 @@ wait_for_cmpl:
ret = FAILED;
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
 "0748 abort handler timed out waiting "
-"for abortng I/O (xri:x%x) to complete: "
+"for aborting I/O (xri:x%x) to complete: "
 "ret %#x, ID %d, LUN %llu\n",
 iocb->sli4_xritag, ret,
 cmnd->device->id, cmnd->device->lun);

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/17 v2] lpfc: Make lpfc_prot_xxx params per hba parameters

2016-10-12 Thread James Smart

Make lpfc_prot_mask and lpfc_prot_guard per hba parameters

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc.h  |  2 ++
 drivers/scsi/lpfc/lpfc_attr.c | 23 ++-
 drivers/scsi/lpfc/lpfc_crtn.h |  2 --
 drivers/scsi/lpfc/lpfc_init.c | 28 +++-
 4 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index b484859..debba5e 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -746,6 +746,8 @@ struct lpfc_hba {
uint32_t cfg_oas_priority;
uint32_t cfg_XLanePriority;
uint32_t cfg_enable_bg;
+   uint32_t cfg_prot_mask;
+   uint32_t cfg_prot_guard;
uint32_t cfg_hostmem_hgp;
uint32_t cfg_log_verbose;
uint32_t cfg_aer_support;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index f101990..be81e61 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -4691,12 +4691,15 @@ unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF;
 #  HBA supports DIX Type 1: Host to HBA  Type 1 protection
 #
 */
-unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION |
- SHOST_DIX_TYPE0_PROTECTION |
- SHOST_DIX_TYPE1_PROTECTION;
-
-module_param(lpfc_prot_mask, uint, S_IRUGO);
-MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");
+LPFC_ATTR(prot_mask,
+   (SHOST_DIF_TYPE1_PROTECTION |
+   SHOST_DIX_TYPE0_PROTECTION |
+   SHOST_DIX_TYPE1_PROTECTION),
+   0,
+   (SHOST_DIF_TYPE1_PROTECTION |
+   SHOST_DIX_TYPE0_PROTECTION |
+   SHOST_DIX_TYPE1_PROTECTION),
+   "T10-DIF host protection capabilities mask");
 
 /*
 # lpfc_prot_guard: i
@@ -4706,9 +4709,9 @@ MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");
 #  - Default will result in registering capabilities for all guard types
 #
 */
-unsigned char lpfc_prot_guard = SHOST_DIX_GUARD_IP;
-module_param(lpfc_prot_guard, byte, S_IRUGO);
-MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type");
+LPFC_ATTR(prot_guard,
+   SHOST_DIX_GUARD_IP, SHOST_DIX_GUARD_CRC, SHOST_DIX_GUARD_IP,
+   "T10-DIF host protection guard type");
 
 /*
  * Delay initial NPort discovery when Clean Address bit is cleared in
@@ -5828,6 +5831,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
phba->cfg_oas_flags = 0;
phba->cfg_oas_priority = 0;
lpfc_enable_bg_init(phba, lpfc_enable_bg);
+   lpfc_prot_mask_init(phba, lpfc_prot_mask);
+   lpfc_prot_guard_init(phba, lpfc_prot_guard);
if (phba->sli_rev == LPFC_SLI_REV4)
phba->cfg_poll = 0;
else
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index bd7576d..16195b7 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -397,8 +397,6 @@ extern spinlock_t _dump_buf_lock;
 extern int _dump_buf_done;
 extern spinlock_t pgcnt_lock;
 extern unsigned int pgcnt;
-extern unsigned int lpfc_prot_mask;
-extern unsigned char lpfc_prot_guard;
 extern unsigned int lpfc_fcp_look_ahead;
 
 /* Interface exported by fabric iocb scheduler */
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index af64d70..117c69a 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -6279,34 +6279,36 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host 
*shost)
uint32_t old_guard;
 
int pagecnt = 10;
-   if (lpfc_prot_mask && lpfc_prot_guard) {
+   if (phba->cfg_prot_mask && phba->cfg_prot_guard) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"1478 Registering BlockGuard with the "
"SCSI layer\n");
 
-   old_mask = lpfc_prot_mask;
-   old_guard = lpfc_prot_guard;
+   old_mask = phba->cfg_prot_mask;
+   old_guard = phba->cfg_prot_guard;
 
/* Only allow supported values */
-   lpfc_prot_mask &= (SHOST_DIF_TYPE1_PROTECTION |
+   phba->cfg_prot_mask &= (SHOST_DIF_TYPE1_PROTECTION |
SHOST_DIX_TYPE0_PROTECTION |
SHOST_DIX_TYPE1_PROTECTION);
-   lpfc_prot_guard &= (SHOST_DIX_GUARD_IP | SHOST_DIX_GUARD_CRC);
+   phba->cfg_prot_guard &= (SHOST_DIX_GUARD_IP |
+SHOST_DIX_GUARD_CRC);
 
/* DIF Type 1 protection for profiles AST1/C1 is end to end */
-   if (lpfc_prot_mask == SHOST_DIX_TYPE1_PROTECTION)
-   lpfc_prot_mask |= SHOST_DIF_TYPE1_PROTECTION;
+   if (phba->cfg_prot_mask == SHOST_DIX_TYPE1_PROTECTION)
+   phba->cfg_prot_mask |= SHOST_DIF_TYPE1_PROTECTION;
 
-   if 

[PATCH 04/17 v2] lpfc: Set driver environment data on adapter

2016-10-12 Thread James Smart

Set driver environment data on adapter

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_hw4.h | 12 
 drivers/scsi/lpfc/lpfc_sli.c | 29 +
 2 files changed, 41 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index ee80227..0b2c337 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -921,6 +921,7 @@ struct mbox_header {
 #define LPFC_MBOX_OPCODE_GET_PORT_NAME 0x4D
 #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT 0x5A
 #define LPFC_MBOX_OPCODE_GET_VPD_DATA  0x5B
+#define LPFC_MBOX_OPCODE_SET_HOST_DATA 0x5D
 #define LPFC_MBOX_OPCODE_SEND_ACTIVATION   0x73
 #define LPFC_MBOX_OPCODE_RESET_LICENSES0x74
 #define LPFC_MBOX_OPCODE_GET_RSRC_EXTENT_INFO  0x9A
@@ -2919,6 +2920,16 @@ struct lpfc_mbx_set_feature {
 };
 
 
+#define LPFC_SET_HOST_OS_DRIVER_VERSION0x2
+struct lpfc_mbx_set_host_data {
+#define LPFC_HOST_OS_DRIVER_VERSION_SIZE   48
+   struct mbox_header header;
+   uint32_t param_id;
+   uint32_t param_len;
+   uint8_t  data[LPFC_HOST_OS_DRIVER_VERSION_SIZE];
+};
+
+
 struct lpfc_mbx_get_sli4_parameters {
struct mbox_header header;
struct lpfc_sli4_parameters sli4_parameters;
@@ -3313,6 +3324,7 @@ struct lpfc_mqe {
struct lpfc_mbx_get_port_name get_port_name;
struct lpfc_mbx_set_feature  set_feature;
struct lpfc_mbx_memory_dump_type3 mem_dump_type3;
+   struct lpfc_mbx_set_host_data set_host_data;
struct lpfc_mbx_nop nop;
} un;
 };
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index c532605..cb59f4e 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -47,6 +47,7 @@
 #include "lpfc_compat.h"
 #include "lpfc_debugfs.h"
 #include "lpfc_vport.h"
+#include "lpfc_version.h"
 
 /* There are only four IOCB completion types. */
 typedef enum _lpfc_iocb_type {
@@ -6289,6 +6290,25 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
return 0;
 }
 
+void
+lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
+{
+   uint32_t len;
+
+   len = sizeof(struct lpfc_mbx_set_host_data) -
+   sizeof(struct lpfc_sli4_cfg_mhdr);
+   lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
+LPFC_MBOX_OPCODE_SET_HOST_DATA, len,
+LPFC_SLI4_MBX_EMBED);
+
+   mbox->u.mqe.un.set_host_data.param_id = LPFC_SET_HOST_OS_DRIVER_VERSION;
+   mbox->u.mqe.un.set_host_data.param_len = 8;
+   snprintf(mbox->u.mqe.un.set_host_data.data,
+LPFC_HOST_OS_DRIVER_VERSION_SIZE,
+"Linux %s v"LPFC_DRIVER_VERSION,
+(phba->hba_flag & HBA_FCOE_MODE) ? "FCoE" : "FC");
+}
+
 /**
  * lpfc_sli4_hba_setup - SLI4 device intialization PCI function
  * @phba: Pointer to HBA context object.
@@ -6540,6 +6560,15 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
goto out_free_mbox;
}
 
+   lpfc_set_host_data(phba, mboxq);
+
+   rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+   if (rc) {
+   lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+   "2134 Failed to set host os driver version %x",
+   rc);
+   }
+
/* Read the port's service parameters. */
rc = lpfc_read_sparam(phba, mboxq, vport->vpi);
if (rc) {
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/17 v2] lpfc: Fix sg_reset on SCSI device causing kernel crash

2016-10-12 Thread James Smart

Fix sg_reset on SCSI device causing kernel crash

Driver could reference stale node pointers in task mgmt call.
Changed to use resetting cmd and look up node pointer in task mgmt
function.

Modified per review:
Revised lpfc_send_taskmgmt() to check rdata

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_scsi.c | 22 +-
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index ca56f28..4c53149e 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4948,26 +4948,30 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct 
lpfc_scsi_buf *lpfc_cmd)
  *   0x2002 - Success.
  **/
 static int
-lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata,
-   unsigned  tgt_id, uint64_t lun_id,
-   uint8_t task_mgmt_cmd)
+lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+  unsigned int tgt_id, uint64_t lun_id,
+  uint8_t task_mgmt_cmd)
 {
struct lpfc_hba   *phba = vport->phba;
struct lpfc_scsi_buf *lpfc_cmd;
struct lpfc_iocbq *iocbq;
struct lpfc_iocbq *iocbqrsp;
-   struct lpfc_nodelist *pnode = rdata->pnode;
+   struct lpfc_rport_data *rdata;
+   struct lpfc_nodelist *pnode;
int ret;
int status;
 
-   if (!pnode || !NLP_CHK_NODE_ACT(pnode))
+   rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
+   if (!rdata || !rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode))
return FAILED;
+   pnode = rdata->pnode;
 
-   lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode);
+   lpfc_cmd = lpfc_get_scsi_buf(phba, pnode);
if (lpfc_cmd == NULL)
return FAILED;
lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo;
lpfc_cmd->rdata = rdata;
+   lpfc_cmd->pCmd = cmnd;
 
status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id,
   task_mgmt_cmd);
@@ -5174,7 +5178,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
fc_host_post_vendor_event(shost, fc_get_event_number(),
sizeof(scsi_event), (char *)_event, LPFC_NL_VENDOR_ID);
 
-   status = lpfc_send_taskmgmt(vport, rdata, tgt_id, lun_id,
+   status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id,
FCP_LUN_RESET);
 
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
@@ -5252,7 +5256,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
fc_host_post_vendor_event(shost, fc_get_event_number(),
sizeof(scsi_event), (char *)_event, LPFC_NL_VENDOR_ID);
 
-   status = lpfc_send_taskmgmt(vport, rdata, tgt_id, lun_id,
+   status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id,
FCP_TARGET_RESET);
 
lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
@@ -5331,7 +5335,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
if (!match)
continue;
 
-   status = lpfc_send_taskmgmt(vport, ndlp->rport->dd_data,
+   status = lpfc_send_taskmgmt(vport, cmnd,
i, 0, FCP_TARGET_RESET);
 
if (status != SUCCESS) {
-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/17 v2] lpfc: Update driver to version 11.2.0.2

2016-10-12 Thread James Smart

This patch set updates the lpfc driver to revision 11.2.0.2

The patches were cut against scsi-misc


James Smart (17):
  Fix few small typos in lpfc_scsi.c
   originally posted by Milan Gandhi
  lpfc: Correct embedded io wq element size
  lpfc: Fix sg_reset on SCSI device causing kernel crash
  lpfc: Set driver environment data on adapter
  lpfc: Make lpfc_prot_mask and lpfc_prot_guard per hba parameters
  lpfc: Code clean up for lpfc_iocb_cnt parameter
  lpfc: Code cleanup for lpfc_enable_rrq parameter
  lpfc: Code cleanup for lpfc_aer_support parameter
  lpfc: Code cleanup for lpfc_topology parameter
  lpfc: Code cleanup for lpfc_max_scsicmpl_time parameter
  lpfc: Code cleanup for lpfc_sriov_nr_virtfn parameter
  lpfc: Revise strings with full lpfc parameter name
  lpfc: Fix lost target in pt-to-pt connect
  lpfc: Correct panics with eh_timeout and eh_deadline
  lpfc: Synchronize link speed with boot driver
  lpfc: Fix fw download on SLI-4 FC adapters
  lpfc: lpfc version changed to 11.2.0.2

 drivers/scsi/lpfc/lpfc.h |   6 ++
 drivers/scsi/lpfc/lpfc_attr.c| 160 +++
 drivers/scsi/lpfc/lpfc_bsg.c |  44 +++
 drivers/scsi/lpfc/lpfc_bsg.h |  10 +++
 drivers/scsi/lpfc/lpfc_crtn.h|   2 -
 drivers/scsi/lpfc/lpfc_els.c |   2 +-
 drivers/scsi/lpfc/lpfc_hw4.h |  18 -
 drivers/scsi/lpfc/lpfc_init.c| 111 ---
 drivers/scsi/lpfc/lpfc_scsi.c|  49 +++-
 drivers/scsi/lpfc/lpfc_sli.c |  41 +-
 drivers/scsi/lpfc/lpfc_version.h |   2 +-
 11 files changed, 272 insertions(+), 173 deletions(-)

-- 
2.5.0


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 00/16] Convert FibreChannel bsg code to use bsg-lib

2016-10-12 Thread Steffen Maier

Hi Johannes,

On 10/12/2016 03:06 PM, Johannes Thumshirn wrote:

This series converts the current bsg usage in the FibreChannel drivers over
to use bsg-lib. SAS will follow once FC is in a good enough shape.

I did take some inspiration from a similar patchset from Mike Christie
dating back to 2011 but it's not a 1:1 copy. Patch 15/16 is heavily based
on his series and attribution is given to him in the commit message.

It is currently regression tested on FCoE using the 'fcns' and
'fcrls' utilities.  I'm still trying to figure out how to test the other
LLDDs. So any pointer from the respective maintainers are appreciated


The first thing that comes to mind for zfcp is libzfcphbaapi and simply 
run its tools for starters. They issue a few different CT GLS requests.

http://www.ibm.com/support/knowledgecenter/linuxonibm/com.ibm.linux.z.lhdd/lhdd_t_fcp_api_runappl.html
or
http://www.ibm.com/support/knowledgecenter/linuxonibm/com.ibm.linux.z.lgdd/lgdd_t_fcp_api_runappl.html
(upstream: 
http://www.ibm.com/developerworks/linux/linux390/zfcp-hbaapi.html)


Theoretically above tools could be built against libHBAAPI on other 
architectures.

Currently I don't have anything handy for ELS requests.

Maybe there is some common code tool (possibly building directly on BSG 
IOCTL) to exercise more code paths?


Just as a heads up the result of my example run (need to dig deeper why 
it crashed):


# zfcp_show -n

Local Port List:
<<>>

[  799.640378] Oops: 0038 ilc:3 [#1] [  799.640387] PREEMPT  SMP [  799.640393]
[  799.640399] Modules linked in: nf_log_ipv6 xt_pkttype nf_log_ipv4 
nf_log_common xt_LOG xt_limit ip6t_REJECT nf_reject_ipv6 xt_tcpudp 
nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_raw ipt_REJECT nf_reject_ipv4 
iptable_raw xt_CT iptable_filter ip6table_mangle nf_conntrack_netbios_ns 
nf_conntrack_broadcast nf_conntrack_ipv4 nf_defrag_ipv4 ip_tables xt_conntrack 
nf_conntrack ip6table_filter ip6_tables x_tables ghash_s390 prng ecb aes_s390 
des_s390 dm_mod des_generic sha512_s390 sha256_s390 qeth_l2 sha1_s390 qeth zfcp 
sha_common ccwgroup qdio autofs4
[  799.640542] CPU: 1 PID: 2210 Comm: zfcp_show Not tainted 4.8.0fcbsg+ #6
[  799.640550] Hardware name: IBM  2964 N96  702
  (z/VM)
[  799.640558] task: 47b60008 task.stack: 62428000
[  799.640567] Krnl PSW : 0404e0018000 001b125c[  799.640581]  
(__lock_acquire+0x104/0x7d8)
[  799.640590]
[  799.640599]R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:2 PM:0[  
799.640618]  RI:0 EA:3
[  799.640621]
[  799.640621] Krnl GPRS:  0008 07f40707c004 

[  799.640624]  0001 

[  799.640627] 00355cb4  
47b60008
[  799.640630]0300 009b17b0 6242b800 
6242b778
[  799.640643] Krnl Code: 001b124c: b9040029lgr %r2,%r9
[  799.640648]001b1250: c0e5d6a4brasl   
%r14,1abf98
 #001b1256: ec28ffad007c   cgij
%r2,0,8,1b11b0
[  799.640659]   >001b125c: eb012198006aasi 
408(%r2,1
  001b1262: 5830ba10   l   
%r3,2576(%r11)
[  799.640669]001b1266: 5030f0a4st  
%r3,164(%r15)
  001b126a: c01000e3f9db   larl
%r1,1e30620
[  799.640678]001b1270: e3101012lt  
%r1,0(%r1)
[  799.640682]
[  799.640684] Call Trace:
[  799.640687] ([] 0x)
[  799.640691] ([<001b21f4>] lock_acquire+0x30c/0x358)
[  799.640699] ([<0099fdae>] mutex_lock_interruptible_nested+0x7e/0x4f8)
[  799.640717] ([<03ff8047a090>] zfcp_fc_wka_port_get+0x40/0x128 [zfcp])
[  799.640724] ([<03ff8047bd54>] zfcp_fc_exec_bsg_job+0x244/0x2d8 [zfcp])
[  799.640732] ([<007c8b1e>] fc_bsg_dispatch+0x20e/0x280)
[  799.640739] ([<006dea1a>] bsg_request_fn+0x132/0x1e0)
[  799.640746] ([<006b8e0a>] __blk_run_queue+0x52/0x68)
[  799.640751] ([<006c549a>] blk_execute_rq_nowait+0xf2/0x110)
[  799.640754] ([<006c557a>] blk_execute_rq+0xa2/0x110)
[  799.640757] ([<006de0ee>] bsg_ioctl+0x1f6/0x268)
[  799.640763] ([<0036ca20>] do_vfs_ioctl+0x680/0x6d8)
[  799.640767] ([<0036caf4>] SyS_ioctl+0x7c/0xb0)
[  799.640771] ([<009a50de>] system_call+0xd6/0x270)
[  799.640774] INFO: lockdep is turned off.
[  799.640776] Last Breaking-Event-Address:
[  799.640779]  [<001b1244>] __lock_acquire+0xec/0x7d8
[  799.640782]  [  799.640785] Kernel panic - not syncing: Fatal exception: 
panic_on_oops




although the LLDD changes are purely mechanical. All they do is change from
'struct fc_bsg_job' to 'struct bsg_job' and corresponding changes in order
to get the series bisectable.


Re: [Open-FCoE] Issue with fc_exch_alloc failing initiated by fc_queuecommand on NUMA or large configurations with Intel ixgbe running FCOE

2016-10-12 Thread Hannes Reinecke

On 10/12/2016 05:26 PM, Ewan D. Milne wrote:

On Tue, 2016-10-11 at 10:51 -0400, Ewan D. Milne wrote:

On Sat, 2016-10-08 at 19:35 +0200, Hannes Reinecke wrote:

You might actually be hitting a limitation in the exchange manager code.
The libfc exchange manager tries to be really clever and will assign a
per-cpu exchange manager (probably to increase locality). However, we
only have a limited number of exchanges, so on large systems we might
actually run into a exchange starvation problem, where we have in theory
enough free exchanges, but none for the submitting cpu.

(Personally, the exchange manager code is in urgent need of reworking.
It should be replaced by the sbitmap code from Omar).

Do check how many free exchanges are actually present for the stalling
CPU; it might be that you run into a starvation issue.


We are still looking into this but one thing that looks bad is that
the exchange manager code rounds up the number of CPUs to the next
power of 2 before dividing up the exchange id space (and uses the lsbs
of the xid to extract the CPU when looking up an xid). We have a machine
with 288 CPUs, this code is just begging for a rewrite as it looks to
be wasting most of the limited xid space on ixgbe FCoE.

Looks like we get 512 offloaded xids on this adapter and 4096-512
non-offloaded xids.  This would give 1 + 7 xids per CPU.  However, I'm
not sure that even 4096 / 288 = 14 would be enough to prevent stalling.

And, of course, potentially most of the CPUs aren't submitting I/O, so
the whole idea of per-CPU xid space is questionable.



fc_exch_alloc() used to try all the available exchange managers in the
list for an available exchange id, but this was changed in 2010 so that
if the first matched exchange manager couldn't allocate one, it fails
and we end up returning host busy.  This was due to commit:

commit 3e22760d4db6fd89e0be46c3d132390a251da9c6
Author: Vasu Dev 
Date:   Fri Mar 12 16:08:39 2010 -0800

[SCSI] libfc: use offload EM instance again instead jumping to next EM

Since use of offloads is more efficient than switching
to non-offload EM. However kept logic same to call em_match
if it is provided in the list of EMs.

Converted fc_exch_alloc to inline being now tiny a function
and already not an exported libfc API any more.

Signed-off-by: Vasu Dev 
Signed-off-by: Robert Love 
Signed-off-by: James Bottomley 

---

Setting the ddp_min module parameter to fcoe to 128MB prevents the ->match
function from permitting the use of the offload exchange manager for the frame,
and we no longer see the problem with host busy status, since it uses the
larger non-offloaded pool.


Yes, this is also the impression I got from reading the spec.
The offload pool is mainly designed for large read or write commands, so 
using it for _every_ frame is probably not a good idea.
And limiting it by the size of the transfers solves the problem quite 
nicely, as a large size typically is only used by read and writes.

So please send a patch to revert that.

Cheers,

Hannes
--
Dr. Hannes Reinecke   zSeries & Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Open-FCoE] Issue with fc_exch_alloc failing initiated by fc_queuecommand on NUMA or large configurations with Intel ixgbe running FCOE

2016-10-12 Thread Ewan D. Milne
On Tue, 2016-10-11 at 10:51 -0400, Ewan D. Milne wrote:
> On Sat, 2016-10-08 at 19:35 +0200, Hannes Reinecke wrote:
> > You might actually be hitting a limitation in the exchange manager code.
> > The libfc exchange manager tries to be really clever and will assign a 
> > per-cpu exchange manager (probably to increase locality). However, we 
> > only have a limited number of exchanges, so on large systems we might 
> > actually run into a exchange starvation problem, where we have in theory 
> > enough free exchanges, but none for the submitting cpu.
> > 
> > (Personally, the exchange manager code is in urgent need of reworking.
> > It should be replaced by the sbitmap code from Omar).
> > 
> > Do check how many free exchanges are actually present for the stalling 
> > CPU; it might be that you run into a starvation issue.
> 
> We are still looking into this but one thing that looks bad is that
> the exchange manager code rounds up the number of CPUs to the next
> power of 2 before dividing up the exchange id space (and uses the lsbs
> of the xid to extract the CPU when looking up an xid). We have a machine
> with 288 CPUs, this code is just begging for a rewrite as it looks to
> be wasting most of the limited xid space on ixgbe FCoE.
> 
> Looks like we get 512 offloaded xids on this adapter and 4096-512
> non-offloaded xids.  This would give 1 + 7 xids per CPU.  However, I'm
> not sure that even 4096 / 288 = 14 would be enough to prevent stalling.
> 
> And, of course, potentially most of the CPUs aren't submitting I/O, so
> the whole idea of per-CPU xid space is questionable.
> 

fc_exch_alloc() used to try all the available exchange managers in the
list for an available exchange id, but this was changed in 2010 so that
if the first matched exchange manager couldn't allocate one, it fails
and we end up returning host busy.  This was due to commit:

commit 3e22760d4db6fd89e0be46c3d132390a251da9c6
Author: Vasu Dev 
Date:   Fri Mar 12 16:08:39 2010 -0800

[SCSI] libfc: use offload EM instance again instead jumping to next EM

Since use of offloads is more efficient than switching
to non-offload EM. However kept logic same to call em_match
if it is provided in the list of EMs.

Converted fc_exch_alloc to inline being now tiny a function
and already not an exported libfc API any more.

Signed-off-by: Vasu Dev 
Signed-off-by: Robert Love 
Signed-off-by: James Bottomley 

---

Setting the ddp_min module parameter to fcoe to 128MB prevents the ->match
function from permitting the use of the offload exchange manager for the frame,
and we no longer see the problem with host busy status, since it uses the
larger non-offloaded pool.

I couldn't find any history on the motivation for the above commit, was
there a significant benefit in some case?  There seems to be a big downside.

-Ewan



--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 1/3] Synchronization of cmds during termination conditions

2016-10-12 Thread Bryant G. Ly


On 10/11/16 5:58 PM, Michael Cyr wrote:

Signed-off-by: Michael Cyr 
---
  drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 1082 +-
  drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h |5 +-
  2 files changed, 486 insertions(+), 601 deletions(-)


I would make the first patch reorganization and styling fixes, no actual 
code changes.
Then for each of the commits make sure you amend them to give more 
description

as to what you are doing in each specific patch.

i.e. First patch:

ibmvscsis: Re-organization of commands/styling

Need to move functions around in order for the proceeding patches to work.

Patch 2/3 and 3/3 look fine to me after you change the title to include 
"ibmvscsis:" in it.


-Bryant

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 14/16] block: add bsg_job_put() and bsg_job_get()

2016-10-12 Thread Johannes Thumshirn
Add bsg_job_put() and bsg_job_get() so don't need to export
bsg_destroy_job() any more.

Signed-off-by: Johannes Thumshirn 
---
 block/bsg-lib.c  | 17 ++---
 drivers/scsi/scsi_transport_fc.c |  4 ++--
 include/linux/bsg-lib.h  |  3 ++-
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 5d24d25..46a4fee 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -32,7 +32,7 @@
  * bsg_destroy_job - routine to teardown/delete a bsg job
  * @job: bsg_job that is to be torn down
  */
-void bsg_destroy_job(struct kref *kref)
+static void bsg_destroy_job(struct kref *kref)
 {
struct bsg_job *job = container_of(kref, struct bsg_job, kref);
 
@@ -42,7 +42,18 @@ void bsg_destroy_job(struct kref *kref)
kfree(job->reply_payload.sg_list);
kfree(job);
 }
-EXPORT_SYMBOL_GPL(bsg_destroy_job);
+
+void bsg_job_put(struct bsg_job *job)
+{
+   kref_put(>kref, bsg_destroy_job);
+}
+EXPORT_SYMBOL_GPL(bsg_job_put);
+
+int bsg_job_get(struct bsg_job *job)
+{
+   return kref_get_unless_zero(>kref);
+}
+EXPORT_SYMBOL_GPL(bsg_job_get);
 
 /**
  * bsg_job_done - completion routine for bsg requests
@@ -87,7 +98,7 @@ void bsg_softirq_done(struct request *rq)
struct bsg_job *job = rq->special;
 
blk_end_request_all(rq, rq->errors);
-   kref_put(>kref, bsg_destroy_job);
+   bsg_job_put(job);
 }
 EXPORT_SYMBOL_GPL(bsg_softirq_done);
 
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 720ddc9..7fae045 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3571,13 +3571,13 @@ fc_bsg_job_timeout(struct request *req)
if (rport && rport->port_state == FC_PORTSTATE_BLOCKED)
return BLK_EH_RESET_TIMER;
 
-   inflight = kref_get_unless_zero(>kref);
+   inflight = bsg_job_get(job);
 
if (inflight && i->f->bsg_timeout) {
/* call LLDD to abort the i/o as it has timed out */
err = i->f->bsg_timeout(job);
if (err == -EAGAIN) {
-   kref_put(>kref, bsg_destroy_job);
+   bsg_job_put(job);
return BLK_EH_RESET_TIMER;
} else if (err)
printk(KERN_ERR "ERROR: FC BSG request timeout - LLD "
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
index 09f3044..b708db9 100644
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -69,7 +69,8 @@ void bsg_job_done(struct bsg_job *job, int result,
 int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name,
bsg_job_fn *job_fn, int dd_job_size);
 void bsg_request_fn(struct request_queue *q);
-void bsg_destroy_job(struct kref *kref);
 void bsg_softirq_done(struct request *rq);
+void bsg_job_put(struct bsg_job *job);
+int __must_check bsg_job_get(struct bsg_job *job);
 
 #endif
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 11/16] scsi: fc: Use bsg_destroy_job

2016-10-12 Thread Johannes Thumshirn
fc_destroy_bsgjob() and bsg_destroy_job() are now 1:1 copies, so use the
later.

Signed-off-by: Johannes Thumshirn 
---
 block/bsg-lib.c  |  3 ++-
 drivers/scsi/scsi_transport_fc.c | 20 ++--
 include/linux/bsg-lib.h  |  1 +
 3 files changed, 5 insertions(+), 19 deletions(-)

diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 632fb40..6b99c7f 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -32,7 +32,7 @@
  * bsg_destroy_job - routine to teardown/delete a bsg job
  * @job: bsg_job that is to be torn down
  */
-static void bsg_destroy_job(struct kref *kref)
+void bsg_destroy_job(struct kref *kref)
 {
struct bsg_job *job = container_of(kref, struct bsg_job, kref);
 
@@ -42,6 +42,7 @@ static void bsg_destroy_job(struct kref *kref)
kfree(job->reply_payload.sg_list);
kfree(job);
 }
+EXPORT_SYMBOL_GPL(bsg_destroy_job);
 
 /**
  * bsg_job_done - completion routine for bsg requests
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index a0e150a..4b9324f 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -3554,23 +3555,6 @@ fc_vport_sched_delete(struct work_struct *work)
  * BSG support
  */
 
-
-/**
- * fc_destroy_bsgjob - routine to teardown/delete a fc bsg job
- * @job:   fc_bsg_job that is to be torn down
- */
-static void
-fc_destroy_bsgjob(struct kref *kref)
-{
-   struct bsg_job *job = container_of(kref, struct bsg_job, kref);
-
-   put_device(job->dev);   /* release reference for the request */
-
-   kfree(job->request_payload.sg_list);
-   kfree(job->reply_payload.sg_list);
-   kfree(job);
-}
-
 /**
  * fc_bsg_jobdone - completion routine for bsg requests that the LLD has
  *  completed
@@ -3640,7 +3624,7 @@ fc_bsg_job_timeout(struct request *req)
/* call LLDD to abort the i/o as it has timed out */
err = i->f->bsg_timeout(job);
if (err == -EAGAIN) {
-   kref_put(>kref, fc_destroy_bsgjob);
+   kref_put(>kref, bsg_destroy_job);
return BLK_EH_RESET_TIMER;
} else if (err)
printk(KERN_ERR "ERROR: FC BSG request timeout - LLD "
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
index 58e0717..67f7de6 100644
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -69,5 +69,6 @@ void bsg_job_done(struct bsg_job *job, int result,
 int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name,
bsg_job_fn *job_fn, int dd_job_size);
 void bsg_request_fn(struct request_queue *q);
+void bsg_destroy_job(struct kref *kref);
 
 #endif
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 12/16] scsi: fc: use bsg_softirq_done

2016-10-12 Thread Johannes Thumshirn
bsg_softirq_done() and fc_bsg_softirq_done() are copies of each other, so
ditch the fc specific one.

Signed-off-by: Johannes Thumshirn 
---
 block/bsg-lib.c  |  3 ++-
 drivers/scsi/scsi_transport_fc.c | 16 ++--
 include/linux/bsg-lib.h  |  1 +
 3 files changed, 5 insertions(+), 15 deletions(-)

diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 6b99c7f..5d24d25 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -82,13 +82,14 @@ EXPORT_SYMBOL_GPL(bsg_job_done);
  * bsg_softirq_done - softirq done routine for destroying the bsg requests
  * @rq: BSG request that holds the job to be destroyed
  */
-static void bsg_softirq_done(struct request *rq)
+void bsg_softirq_done(struct request *rq)
 {
struct bsg_job *job = rq->special;
 
blk_end_request_all(rq, rq->errors);
kref_put(>kref, bsg_destroy_job);
 }
+EXPORT_SYMBOL_GPL(bsg_softirq_done);
 
 static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
 {
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 4b9324f..1ae6d86 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3591,18 +3591,6 @@ void fc_bsg_jobdone(struct bsg_job *job, int result,
 EXPORT_SYMBOL_GPL(fc_bsg_jobdone);
 
 /**
- * fc_bsg_softirq_done - softirq done routine for destroying the bsg requests
- * @rq:BSG request that holds the job to be destroyed
- */
-static void fc_bsg_softirq_done(struct request *rq)
-{
-   struct bsg_job *job = rq->special;
-
-   blk_end_request_all(rq, rq->errors);
-   kref_put(>kref, fc_destroy_bsgjob);
-}
-
-/**
  * fc_bsg_job_timeout - handler for when a bsg request timesout
  * @req:   request that timed out
  */
@@ -4036,7 +4024,7 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct 
fc_host_attrs *fc_host)
 
q->queuedata = shost;
queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
-   blk_queue_softirq_done(q, fc_bsg_softirq_done);
+   blk_queue_softirq_done(q, bsg_softirq_done);
blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT);
 
@@ -4082,7 +4070,7 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport 
*rport)
 
q->queuedata = rport;
queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
-   blk_queue_softirq_done(q, fc_bsg_softirq_done);
+   blk_queue_softirq_done(q, bsg_softirq_done);
blk_queue_rq_timed_out(q, fc_bsg_job_timeout);
blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
 
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
index 67f7de6..09f3044 100644
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -70,5 +70,6 @@ int bsg_setup_queue(struct device *dev, struct request_queue 
*q, char *name,
bsg_job_fn *job_fn, int dd_job_size);
 void bsg_request_fn(struct request_queue *q);
 void bsg_destroy_job(struct kref *kref);
+void bsg_softirq_done(struct request *rq);
 
 #endif
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 16/16] block: unexport bsg_softirq_done() again

2016-10-12 Thread Johannes Thumshirn
Unexport bsg_softirq_done() again, we don't need it outside of bsg-lib.c
anymore now that scsi_transport_fc is a pure bsg-lib client.

Signed-off-by: Johannes Thumshirn 
---
 block/bsg-lib.c | 3 +--
 include/linux/bsg-lib.h | 1 -
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 46a4fee..4ac0ade 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -93,14 +93,13 @@ EXPORT_SYMBOL_GPL(bsg_job_done);
  * bsg_softirq_done - softirq done routine for destroying the bsg requests
  * @rq: BSG request that holds the job to be destroyed
  */
-void bsg_softirq_done(struct request *rq)
+static void bsg_softirq_done(struct request *rq)
 {
struct bsg_job *job = rq->special;
 
blk_end_request_all(rq, rq->errors);
bsg_job_put(job);
 }
-EXPORT_SYMBOL_GPL(bsg_softirq_done);
 
 static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
 {
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
index b708db9..657a718 100644
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -69,7 +69,6 @@ void bsg_job_done(struct bsg_job *job, int result,
 int bsg_setup_queue(struct device *dev, struct request_queue *q, char *name,
bsg_job_fn *job_fn, int dd_job_size);
 void bsg_request_fn(struct request_queue *q);
-void bsg_softirq_done(struct request *rq);
 void bsg_job_put(struct bsg_job *job);
 int __must_check bsg_job_get(struct bsg_job *job);
 
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 07/16] scsi: libfc: don't set FC_RQST_STATE_DONE before calling fc_bsg_jobdone()

2016-10-12 Thread Johannes Thumshirn
Don't set FC_RQST_STATE_DONE before calling fc_bsg_jobdone() as
fc_bsg_jobdone() calls blk_complete_requeust() which raises a soft-IRQ that
ends up in fc_bsg_sofirq_done() and fc_bsg_softirq_done() sets the
FC_RQST_STATE_DONE flag.

Signed-off-by: Johannes Thumshirn 
---
 drivers/scsi/libfc/fc_lport.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 156708a..53d13721 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1911,7 +1911,6 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct 
fc_frame *fp,
bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ?
-ECONNABORTED : -ETIMEDOUT;
job->reply_len = sizeof(uint32_t);
-   job->state_flags |= FC_RQST_STATE_DONE;
fc_bsg_jobdone(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
kfree(info);
@@ -1947,7 +1946,6 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct 
fc_frame *fp,
bsg_reply->reply_payload_rcv_len =
job->reply_payload.payload_len;
bsg_reply->result = 0;
-   job->state_flags |= FC_RQST_STATE_DONE;
fc_bsg_jobdone(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
kfree(info);
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 15/16] scsi: fc: move FC transport's bsg code to bsg-lib

2016-10-12 Thread Johannes Thumshirn
Now that all conversions are done, move the FibreChannel bsg code over to the
bsg library. Note that CONFIG_SCSI_FC_ATTRS now needs to select BLK_DEV_BSGLIB
in order to build correctly.

This patch is derived from work done by Mike Christie in 2011 [1] but only the
iscsi parts got merged back then.

[1] http://marc.info/?l=linux-scsi=131149780921009=2

Signed-off-by: Johannes Thumshirn 
---
 drivers/scsi/Kconfig |   1 +
 drivers/scsi/scsi_transport_fc.c | 287 ++-
 2 files changed, 44 insertions(+), 244 deletions(-)

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 7d1b431..1a0338c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -263,6 +263,7 @@ config SCSI_SPI_ATTRS
 config SCSI_FC_ATTRS
tristate "FiberChannel Transport Attributes"
depends on SCSI && NET
+   select BLK_DEV_BSGLIB
select SCSI_NETLINK
help
  If you wish to export transport-specific information about
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 7fae045..916d488 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3591,111 +3591,12 @@ fc_bsg_job_timeout(struct request *req)
return BLK_EH_HANDLED;
 }
 
-static int
-fc_bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
-{
-   size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
-
-   BUG_ON(!req->nr_phys_segments);
-
-   buf->sg_list = kzalloc(sz, GFP_KERNEL);
-   if (!buf->sg_list)
-   return -ENOMEM;
-   sg_init_table(buf->sg_list, req->nr_phys_segments);
-   buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
-   buf->payload_len = blk_rq_bytes(req);
-   return 0;
-}
-
-
-/**
- * fc_req_to_bsgjob - Allocate/create the fc_bsg_job structure for the
- *   bsg request
- * @shost: SCSI Host corresponding to the bsg object
- * @rport: (optional) FC Remote Port corresponding to the bsg object
- * @req:   BSG request that needs a job structure
- */
-static int
-fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport *rport,
-   struct request *req)
-{
-   struct fc_internal *i = to_fc_internal(shost->transportt);
-   struct request *rsp = req->next_rq;
-   struct bsg_job *job;
-   struct fc_bsg_request *bsg_request;
-   struct fc_bsg_reply *bsg_reply;
-   int ret;
-
-   BUG_ON(req->special);
-
-   job = kzalloc(sizeof(struct bsg_job) + i->f->dd_bsg_size,
-   GFP_KERNEL);
-   if (!job)
-   return -ENOMEM;
-
-   /*
-* Note: this is a bit silly.
-* The request gets formatted as a SGIO v4 ioctl request, which
-* then gets reformatted as a blk request, which then gets
-* reformatted as a fc bsg request. And on completion, we have
-* to wrap return results such that SGIO v4 thinks it was a scsi
-* status.  I hope this was all worth it.
-*/
-
-   req->special = job;
-   job->req = req;
-   if (i->f->dd_bsg_size)
-   job->dd_data = (void *)[1];
-   bsg_request = (struct fc_bsg_request *)req->cmd;
-   job->request_len = req->cmd_len;
-   bsg_reply = req->sense;
-   job->reply_len = SCSI_SENSE_BUFFERSIZE; /* Size of sense buffer
-* allocated */
-   if (req->bio) {
-   ret = fc_bsg_map_buffer(>request_payload, req);
-   if (ret)
-   goto failjob_rls_job;
-   }
-   if (rsp && rsp->bio) {
-   ret = fc_bsg_map_buffer(>reply_payload, rsp);
-   if (ret)
-   goto failjob_rls_rqst_payload;
-   }
-   if (rport)
-   job->dev = >dev;
-   else
-   job->dev = >shost_gendev;
-   get_device(job->dev);   /* take a reference for the request */
-
-   kref_init(>kref);
-
-   return 0;
-
-
-failjob_rls_rqst_payload:
-   kfree(job->request_payload.sg_list);
-failjob_rls_job:
-   kfree(job);
-   return -ENOMEM;
-}
-
-
-enum fc_dispatch_result {
-   FC_DISPATCH_BREAK,  /* on return, q is locked, break from q loop */
-   FC_DISPATCH_LOCKED, /* on return, q is locked, continue on */
-   FC_DISPATCH_UNLOCKED,   /* on return, q is unlocked, continue on */
-};
-
-
 /**
  * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD
- * @q: fc host request queue
  * @shost: scsi host rport attached to
  * @job:   bsg job to be processed
  */
-static enum fc_dispatch_result
-fc_bsg_host_dispatch(struct request_queue *q, struct Scsi_Host *shost,
-struct bsg_job *job)
+static int fc_bsg_host_dispatch(struct Scsi_Host *shost, struct bsg_job *job)
 {
struct fc_internal *i = to_fc_internal(shost->transportt);
struct fc_bsg_request *bsg_request = 

[PATCH v2 00/16] Convert FibreChannel bsg code to use bsg-lib

2016-10-12 Thread Johannes Thumshirn
This series converts the current bsg usage in the FibreChannel drivers over
to use bsg-lib. SAS will follow once FC is in a good enough shape.

I did take some inspiration from a similar patchset from Mike Christie
dating back to 2011 but it's not a 1:1 copy. Patch 15/16 is heavily based
on his series and attribution is given to him in the commit message.

It is currently regression tested on FCoE using the 'fcns' and
'fcrls' utilities.  I'm still trying to figure out how to test the other
LLDDs. So any pointer from the respective maintainers are appreciated
although the LLDD changes are purely mechanical. All they do is change from
'struct fc_bsg_job' to 'struct bsg_job' and corresponding changes in order
to get the series bisectable.

The idea for this change arose when discussing racy sysfs handling the FC
bsg code with Christoph and is a next step in moving all bsg clients to
bsg-lib to eventually clean up the in kernel bsg API.

Changes to v1:
* Reduce the number of individual patches (44 -> 16)
* Fix s390 build failure (forgotten to kill fc_bsg_job from zfcp_ext.h)
* Fix build failure on configs without CONFIG_BLK_DEV_BSGLIB
* Make bsg_job_get() call kref_get_unless_zero() and use it in 
scsi_transport_fc.c

Johannes Thumshirn (16):
  scsi: Get rid of struct fc_bsg_buffer
  scsi: don't use fc_bsg_job::request and fc_bsg_job::reply directly
  scsi: fc: Export fc_bsg_jobdone and use it in FC drivers
  scsi: Unify interfaces of fc_bsg_jobdone and bsg_job_done
  scsi: fc: provide fc_bsg_to_shost() helper
  scsi: fc: provide fc_bsg_to_rport() helper
  scsi: libfc: don't set FC_RQST_STATE_DONE before calling
fc_bsg_jobdone()
  scsi: fc: implement kref backed reference counting
  block: add reference counting for struct bsg_job
  scsi: change FC drivers to use 'struct bsg_job'
  scsi: fc: Use bsg_destroy_job
  scsi: fc: use bsg_softirq_done
  scsi: fc: use bsg_job_done
  block: add bsg_job_put() and bsg_job_get()
  scsi: fc: move FC transport's bsg code to bsg-lib
  block: unexport bsg_softirq_done() again

 block/bsg-lib.c  |  19 +-
 drivers/s390/scsi/zfcp_ext.h |   4 +-
 drivers/s390/scsi/zfcp_fc.c  |  33 +--
 drivers/scsi/Kconfig |   1 +
 drivers/scsi/bfa/bfad_bsg.c  |  62 +++---
 drivers/scsi/bfa/bfad_im.h   |   4 +-
 drivers/scsi/ibmvscsi/ibmvfc.c   |  40 ++--
 drivers/scsi/libfc/fc_lport.c|  47 ++--
 drivers/scsi/lpfc/lpfc_bsg.c | 375 +++-
 drivers/scsi/lpfc/lpfc_crtn.h|   4 +-
 drivers/scsi/qla2xxx/qla_bsg.c   | 449 ++-
 drivers/scsi/qla2xxx/qla_def.h   |   2 +-
 drivers/scsi/qla2xxx/qla_gbl.h   |   4 +-
 drivers/scsi/qla2xxx/qla_iocb.c  |  13 +-
 drivers/scsi/qla2xxx/qla_isr.c   |  52 +++--
 drivers/scsi/qla2xxx/qla_mr.c|  15 +-
 drivers/scsi/scsi_transport_fc.c | 409 ++-
 include/linux/bsg-lib.h  |   4 +
 include/scsi/libfc.h |   2 +-
 include/scsi/scsi_transport_fc.h |  62 ++
 20 files changed, 745 insertions(+), 856 deletions(-)

-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 13/16] scsi: fc: use bsg_job_done

2016-10-12 Thread Johannes Thumshirn
fc_bsg_jobdone() and bsg_job_done() are 1:1 copies now so use the bsg-lib one
instead of the FC private implementation.

Signed-off-by: Johannes Thumshirn 
---
 drivers/s390/scsi/zfcp_fc.c  |  2 +-
 drivers/scsi/bfa/bfad_bsg.c  |  4 ++--
 drivers/scsi/ibmvscsi/ibmvfc.c   |  2 +-
 drivers/scsi/libfc/fc_lport.c|  4 ++--
 drivers/scsi/lpfc/lpfc_bsg.c | 38 +-
 drivers/scsi/qla2xxx/qla_bsg.c   | 44 
 drivers/scsi/scsi_transport_fc.c | 41 +++--
 include/scsi/scsi_transport_fc.h |  2 --
 8 files changed, 50 insertions(+), 87 deletions(-)

diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index b1b4129..a0f9c82 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -893,7 +893,7 @@ static void zfcp_fc_ct_els_job_handler(void *data)
jr->reply_payload_rcv_len = job->reply_payload.payload_len;
jr->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
jr->result = zfcp_ct_els->status ? -EIO : 0;
-   fc_bsg_jobdone(job, jr->result, jr->reply_payload_rcv_len);
+   bsg_job_done(job, jr->result, jr->reply_payload_rcv_len);
 }
 
 static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct bsg_job *job)
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index cdc25e6..a9a0016 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -3179,7 +3179,7 @@ bfad_im_bsg_vendor_request(struct bsg_job *job)
bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len;
bsg_reply->result = rc;
 
-   fc_bsg_jobdone(job, bsg_reply->result,
+   bsg_job_done(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
return rc;
 error:
@@ -3555,7 +3555,7 @@ out:
bsg_reply->result = rc;
 
if (rc == BFA_STATUS_OK)
-   fc_bsg_jobdone(job, bsg_reply->result,
+   bsg_job_done(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
 
return rc;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 9fd8975..85aa8ab 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1940,7 +1940,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job)
ibmvfc_free_event(evt);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
bsg_reply->result = rc;
-   fc_bsg_jobdone(job, bsg_reply->result,
+   bsg_job_done(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
rc = 0;
 out:
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 58a3ccb..40d9038 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1911,7 +1911,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct 
fc_frame *fp,
bsg_reply->result = (PTR_ERR(fp) == -FC_EX_CLOSED) ?
-ECONNABORTED : -ETIMEDOUT;
job->reply_len = sizeof(uint32_t);
-   fc_bsg_jobdone(job, bsg_reply->result,
+   bsg_job_done(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
kfree(info);
return;
@@ -1946,7 +1946,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct 
fc_frame *fp,
bsg_reply->reply_payload_rcv_len =
job->reply_payload.payload_len;
bsg_reply->result = 0;
-   fc_bsg_jobdone(job, bsg_reply->result,
+   bsg_job_done(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
kfree(info);
}
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index ca21f25..a862437 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -371,7 +371,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
 
if (job) {
bsg_reply->result = rc;
-   fc_bsg_jobdone(job, bsg_reply->result,
+   bsg_job_done(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
}
return;
@@ -645,7 +645,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
 
if (job) {
bsg_reply->result = rc;
-   fc_bsg_jobdone(job, bsg_reply->result,
+   bsg_job_done(job, bsg_reply->result,
   bsg_reply->reply_payload_rcv_len);
}
return;
@@ -1138,7 +1138,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
job->dd_data = NULL;
/* complete the job back to userspace */
spin_unlock_irqrestore(>ct_ev_lock, flags);
-   fc_bsg_jobdone(job, bsg_reply->result,
+  

[PATCH v2 01/16] scsi: Get rid of struct fc_bsg_buffer

2016-10-12 Thread Johannes Thumshirn
struct fc_bsg_buffer is just a clone of struct bsg_buffer from bsg-lib,
so use this one instead.

Signed-off-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_bsg.c |  3 ++-
 drivers/scsi/scsi_transport_fc.c |  2 +-
 include/scsi/scsi_transport_fc.h | 12 +++-
 3 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 05dcc2a..1002627 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -211,7 +212,7 @@ lpfc_alloc_bsg_buffers(struct lpfc_hba *phba, unsigned int 
size,
 
 static unsigned int
 lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers,
-  struct fc_bsg_buffer *bsg_buffers,
+  struct bsg_buffer *bsg_buffers,
   unsigned int bytes_to_transfer, int to_buffers)
 {
 
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 0f3a386..8ff2067 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3671,7 +3671,7 @@ fc_bsg_job_timeout(struct request *req)
 }
 
 static int
-fc_bsg_map_buffer(struct fc_bsg_buffer *buf, struct request *req)
+fc_bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
 {
size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
 
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index bf66ea6..921b097 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -28,6 +28,7 @@
 #define SCSI_TRANSPORT_FC_H
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -624,13 +625,6 @@ struct fc_host_attrs {
 #define fc_host_dev_loss_tmo(x) \
(((struct fc_host_attrs *)(x)->shost_data)->dev_loss_tmo)
 
-
-struct fc_bsg_buffer {
-   unsigned int payload_len;
-   int sg_cnt;
-   struct scatterlist *sg_list;
-};
-
 /* Values for fc_bsg_job->state_flags (bitflags) */
 #define FC_RQST_STATE_INPROGRESS   0
 #define FC_RQST_STATE_DONE 1
@@ -659,8 +653,8 @@ struct fc_bsg_job {
 */
 
/* DMA payloads for the request/response */
-   struct fc_bsg_buffer request_payload;
-   struct fc_bsg_buffer reply_payload;
+   struct bsg_buffer request_payload;
+   struct bsg_buffer reply_payload;
 
void *dd_data;  /* Used for driver-specific storage */
 };
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 02/16] scsi: don't use fc_bsg_job::request and fc_bsg_job::reply directly

2016-10-12 Thread Johannes Thumshirn
Don't use fc_bsg_job::request and fc_bsg_job::reply directly, but use
helper variables bsg_request and bsg_reply. This will be helpfull  when
transitioning to bsg-lib.

Signed-off-by: Johannes Thumshirn 
---
 drivers/s390/scsi/zfcp_fc.c  |   9 +-
 drivers/scsi/bfa/bfad_bsg.c  |  40 +++---
 drivers/scsi/ibmvscsi/ibmvfc.c   |  22 ++--
 drivers/scsi/libfc/fc_lport.c|  23 ++--
 drivers/scsi/lpfc/lpfc_bsg.c | 194 +---
 drivers/scsi/qla2xxx/qla_bsg.c   | 264 ++-
 drivers/scsi/qla2xxx/qla_iocb.c  |   5 +-
 drivers/scsi/qla2xxx/qla_isr.c   |  46 ---
 drivers/scsi/qla2xxx/qla_mr.c|  10 +-
 drivers/scsi/scsi_transport_fc.c |  37 +++---
 10 files changed, 387 insertions(+), 263 deletions(-)

diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 237688a..4c4023f 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -900,8 +900,9 @@ static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct 
fc_bsg_job *job)
u32 preamble_word1;
u8 gs_type;
struct zfcp_adapter *adapter;
+   struct fc_bsg_request *bsg_request = job->request;
 
-   preamble_word1 = job->request->rqst_data.r_ct.preamble_word1;
+   preamble_word1 = bsg_request->rqst_data.r_ct.preamble_word1;
gs_type = (preamble_word1 & 0xff00) >> 24;
 
adapter = (struct zfcp_adapter *) job->shost->hostdata[0];
@@ -938,6 +939,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
 {
struct zfcp_fsf_ct_els *els = job->dd_data;
struct fc_rport *rport = job->rport;
+   struct fc_bsg_request *bsg_request = job->request;
struct zfcp_port *port;
u32 d_id;
 
@@ -949,7 +951,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
d_id = port->d_id;
put_device(>dev);
} else
-   d_id = ntoh24(job->request->rqst_data.h_els.port_id);
+   d_id = ntoh24(bsg_request->rqst_data.h_els.port_id);
 
els->handler = zfcp_fc_ct_els_job_handler;
return zfcp_fsf_send_els(adapter, d_id, els, job->req->timeout / HZ);
@@ -983,6 +985,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
struct Scsi_Host *shost;
struct zfcp_adapter *adapter;
struct zfcp_fsf_ct_els *ct_els = job->dd_data;
+   struct fc_bsg_request *bsg_request = job->request;
 
shost = job->rport ? rport_to_shost(job->rport) : job->shost;
adapter = (struct zfcp_adapter *)shost->hostdata[0];
@@ -994,7 +997,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
ct_els->resp = job->reply_payload.sg_list;
ct_els->handler_data = job;
 
-   switch (job->request->msgcode) {
+   switch (bsg_request->msgcode) {
case FC_BSG_RPT_ELS:
case FC_BSG_HST_ELS_NOLOGIN:
return zfcp_fc_exec_els_job(job, adapter);
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index d1ad020..48366d8 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -3132,7 +3132,9 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, 
void *iocmd,
 static int
 bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
 {
-   uint32_t vendor_cmd = job->request->rqst_data.h_vendor.vendor_cmd[0];
+   struct fc_bsg_request *bsg_request = job->request;
+   struct fc_bsg_reply *bsg_reply = job->reply;
+   uint32_t vendor_cmd = bsg_request->rqst_data.h_vendor.vendor_cmd[0];
struct bfad_im_port_s *im_port =
(struct bfad_im_port_s *) job->shost->hostdata[0];
struct bfad_s *bfad = im_port->bfad;
@@ -3175,8 +3177,8 @@ bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
 
/* Fill the BSG job reply data */
job->reply_len = job->reply_payload.payload_len;
-   job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
-   job->reply->result = rc;
+   bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len;
+   bsg_reply->result = rc;
 
job->job_done(job);
return rc;
@@ -3184,9 +3186,9 @@ error:
/* free the command buffer */
kfree(payload_kbuf);
 out:
-   job->reply->result = rc;
+   bsg_reply->result = rc;
job->reply_len = sizeof(uint32_t);
-   job->reply->reply_payload_rcv_len = 0;
+   bsg_reply->reply_payload_rcv_len = 0;
return rc;
 }
 
@@ -3362,18 +3364,20 @@ bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
struct bfad_fcxp*drv_fcxp;
struct bfa_fcs_lport_s *fcs_port;
struct bfa_fcs_rport_s *fcs_rport;
-   uint32_t command_type = job->request->msgcode;
+   struct fc_bsg_request *bsg_request = bsg_request;
+   struct fc_bsg_reply *bsg_reply = job->reply;
+   uint32_t command_type = bsg_request->msgcode;
unsigned long flags;
struct bfad_buf_info *rsp_buf_info;
void *req_kbuf = NULL, *rsp_kbuf = 

[PATCH v2 06/16] scsi: fc: provide fc_bsg_to_rport() helper

2016-10-12 Thread Johannes Thumshirn
Provide fc_bsg_to_rport() helper that will become handy when we're moving
from struct fc_bsg_job to a plain struct bsg_job. Also move all LLDDs to use
the new helper.

Signed-off-by: Johannes Thumshirn 
---
 drivers/s390/scsi/zfcp_fc.c  | 5 +++--
 drivers/scsi/ibmvscsi/ibmvfc.c   | 2 +-
 drivers/scsi/libfc/fc_lport.c| 4 ++--
 drivers/scsi/lpfc/lpfc_bsg.c | 4 ++--
 drivers/scsi/qla2xxx/qla_bsg.c   | 4 ++--
 drivers/scsi/scsi_transport_fc.c | 3 ++-
 include/scsi/scsi_transport_fc.h | 5 +
 7 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 813c286..1977a66 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -938,7 +938,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
struct zfcp_adapter *adapter)
 {
struct zfcp_fsf_ct_els *els = job->dd_data;
-   struct fc_rport *rport = job->rport;
+   struct fc_rport *rport = fc_bsg_to_rport(job);
struct fc_bsg_request *bsg_request = job->request;
struct zfcp_port *port;
u32 d_id;
@@ -986,8 +986,9 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
struct zfcp_adapter *adapter;
struct zfcp_fsf_ct_els *ct_els = job->dd_data;
struct fc_bsg_request *bsg_request = job->request;
+   struct fc_rport *rport = fc_bsg_to_rport(job);
 
-   shost = job->rport ? rport_to_shost(job->rport) : fc_bsg_to_shost(job);
+   shost = rport ? rport_to_shost(rport) : fc_bsg_to_shost(job);
adapter = (struct zfcp_adapter *)shost->hostdata[0];
 
if (!(atomic_read(>status) & ZFCP_STATUS_COMMON_OPEN))
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index f7b50af..35114d9 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1816,7 +1816,7 @@ unlock_out:
 static int ibmvfc_bsg_request(struct fc_bsg_job *job)
 {
struct ibmvfc_host *vhost = shost_priv(fc_bsg_to_shost(job));
-   struct fc_rport *rport = job->rport;
+   struct fc_rport *rport = fc_bsg_to_rport(job);
struct ibmvfc_passthru_mad *mad;
struct ibmvfc_event *evt;
union ibmvfc_iu rsp_iu;
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index c60fdb9..156708a 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -2102,7 +2102,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
 
switch (bsg_request->msgcode) {
case FC_BSG_RPT_ELS:
-   rport = job->rport;
+   rport = fc_bsg_to_rport(job);
if (!rport)
break;
 
@@ -2112,7 +2112,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
break;
 
case FC_BSG_RPT_CT:
-   rport = job->rport;
+   rport = fc_bsg_to_rport(job);
if (!rport)
break;
 
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index bfcc37d..dae7cc3 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -386,7 +386,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
 {
struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
struct lpfc_hba *phba = vport->phba;
-   struct lpfc_rport_data *rdata = job->rport->dd_data;
+   struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data;
struct lpfc_nodelist *ndlp = rdata->pnode;
struct fc_bsg_reply *bsg_reply = job->reply;
struct ulp_bde64 *bpl = NULL;
@@ -660,7 +660,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
 {
struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
struct lpfc_hba *phba = vport->phba;
-   struct lpfc_rport_data *rdata = job->rport->dd_data;
+   struct lpfc_rport_data *rdata = fc_bsg_to_rport(job)->dd_data;
struct lpfc_nodelist *ndlp = rdata->pnode;
struct fc_bsg_request *bsg_request = job->request;
struct fc_bsg_reply *bsg_reply = job->reply;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 109b852..917eafe 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -264,7 +264,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
uint16_t nextlid = 0;
 
if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
-   rport = bsg_job->rport;
+   rport = fc_bsg_to_rport(bsg_job);
fcport = *(fc_port_t **) rport->dd_data;
host = rport_to_shost(rport);
vha = shost_priv(host);
@@ -2485,7 +2485,7 @@ qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
bsg_reply->reply_payload_rcv_len = 0;
 
if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
-   rport = bsg_job->rport;
+   rport = fc_bsg_to_rport(bsg_job);
host = rport_to_shost(rport);
vha = 

Re: [PATCH 1/2] scsi: Handle Unit Attention when issuing SCSI command

2016-10-12 Thread James Bottomley
On Wed, 2016-10-12 at 02:25 -0300, Gabriel Krisman Bertazi wrote:
> Usually, re-sending the SCSI command is enough to recover from a Unit
> Attention (UA).  This adds a generic retry code to the SCSI command 
> path in case of an UA, before giving up and returning the error 
> condition to the caller.
> 
> I added the UA verification into scsi_execute instead of
> scsi_execute_req because there are at least a few callers that invoke
> scsi_execute directly and would benefit from the internal UA retry.
> Also, I didn't use scsi_normalize_sense to not duplicate 
> functionality with scsi_execute_req_flags.  Instead, scsi_execute 
> uses a small helper function that verifies only the UA condition 
> directly from the raw sense buffer.  If this design is not OK, I can 
> refactor to use scsi_normalize_sense.
> 
> This prevents us from duplicating the retry code in at least a few
> places.  In particular, it fixes an issue found in some IBM 
> enclosures, in which the device may return an Unit Attention during 
> probe, breaking the bind with the ses module:
> 
> scsi 1:0:7:0: Failed to get diagnostic page 0x802
> scsi 1:0:7:0: Failed to bind enclosure -19
> 
> Finally, should we have a NORETRY_UA flag to allow callers to disable
> this mechanism?

I think not: let's use retries for this.  Allowing no retries would be
the signal that you want the UA condition returned.

> Link: https://patchwork.kernel.org/patch/9336763/
> Suggested-by: Brian King 
> Suggested-by: James Bottomley 
> Signed-off-by: Gabriel Krisman Bertazi 
> ---
>  drivers/scsi/scsi_lib.c| 47
> +-
>  include/scsi/scsi_common.h |  9 +
>  2 files changed, 51 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index c71344aebdbb..a4af411de2a4 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -47,6 +47,9 @@ struct kmem_cache *scsi_sdb_cache;
>   */
>  #define SCSI_QUEUE_DELAY 3
>  
> +/* Maximum number of retries when a scsi command triggers an Unit
> Attention. */
> +#define UNIT_ATTENTION_RETRIES 5

We would also tick down the passed in retries so you don't need this
artificial setting.

>  static void
>  scsi_set_blocked(struct scsi_cmnd *cmd, int reason)
>  {
> @@ -164,7 +167,7 @@ void scsi_queue_insert(struct scsi_cmnd *cmd, int
> reason)
>   __scsi_queue_insert(cmd, reason, 1);
>  }
>  /**
> - * scsi_execute - insert request and wait for the result
> + * __scsi_execute - insert request and wait for the result
>   * @sdev:scsi device
>   * @cmd: scsi command
>   * @data_direction: data direction
> @@ -179,10 +182,10 @@ void scsi_queue_insert(struct scsi_cmnd *cmd,
> int reason)
>   * returns the req->errors value which is the scsi_cmnd result
>   * field.
>   */
> -int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
> -  int data_direction, void *buffer, unsigned bufflen,
> -  unsigned char *sense, int timeout, int retries, u64
> flags,
> -  int *resid)
> +int __scsi_execute(struct scsi_device *sdev, const unsigned char
> *cmd,
> +int data_direction, void *buffer, unsigned
> bufflen,
> +unsigned char *sense, int timeout, int retries,
> u64 flags,
> +int *resid)
>  {
>   struct request *req;
>   int write = (data_direction == DMA_TO_DEVICE);
> @@ -227,6 +230,40 @@ int scsi_execute(struct scsi_device *sdev, const
> unsigned char *cmd,
>  
>   return ret;
>  }
> +
> +int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
> +  int data_direction, void *buffer, unsigned bufflen,
> +  unsigned char *sense, int timeout, int retries, u64
> flags,
> +  int *resid)
> +{
> + int result;
> + int retry = UNIT_ATTENTION_RETRIES;
> + bool priv_sense = false;
> +
> + if (!sense) {
> + sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
> + priv_sense = true;
> + if (!sense)
> + return DRIVER_ERROR << 24;
> + }
> +
> + while (retry--) {
> + result = __scsi_execute(sdev, cmd, data_direction,
> buffer,
> + bufflen, sense, timeout,
> retries,
> + flags, resid);

OK, so really this isn't what you want, because blk_execute_req may
have used several of your retries, so you now get a maximum possible
set of retries at UNIT_ATTENTION_RETRIES*retries.  You need to start
from the returned req->retries, which probably means this loop needs to
be inside __scsi_execute.

James


> +
> + if (!scsi_sense_unit_attention(sense))
> + break;
> +
> + if (retry)
> + memset(sense, 0, SCSI_SENSE_BUFFERSIZE);
> + }
> +
> + if (priv_sense)
> + kfree(sense);

[PATCH v2 04/16] scsi: Unify interfaces of fc_bsg_jobdone and bsg_job_done

2016-10-12 Thread Johannes Thumshirn
Unify the interfaces of fc_bsg_jobdone and bsg_job_done. This will reduce the
diff when moving from 'struct fc_bsg_job' to a plain 'struct bsg_job' later
on.

Signed-off-by: Johannes Thumshirn 
---
 drivers/s390/scsi/zfcp_fc.c  |  2 +-
 drivers/scsi/bfa/bfad_bsg.c  |  6 ++--
 drivers/scsi/ibmvscsi/ibmvfc.c   |  3 +-
 drivers/scsi/libfc/fc_lport.c|  6 ++--
 drivers/scsi/lpfc/lpfc_bsg.c | 68 +++-
 drivers/scsi/qla2xxx/qla_bsg.c   | 66 +-
 drivers/scsi/scsi_transport_fc.c | 22 +++--
 include/scsi/scsi_transport_fc.h |  3 +-
 8 files changed, 116 insertions(+), 60 deletions(-)

diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 40d8f06..87f6330 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -892,7 +892,7 @@ static void zfcp_fc_ct_els_job_handler(void *data)
jr->reply_payload_rcv_len = job->reply_payload.payload_len;
jr->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
jr->result = zfcp_ct_els->status ? -EIO : 0;
-   fc_bsg_jobdone(job);
+   fc_bsg_jobdone(job, jr->result, jr->reply_payload_rcv_len);
 }
 
 static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job)
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 25889b9..e49a6c8 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -3180,7 +3180,8 @@ bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len;
bsg_reply->result = rc;
 
-   fc_bsg_jobdone(job);
+   fc_bsg_jobdone(job, bsg_reply->result,
+  bsg_reply->reply_payload_rcv_len);
return rc;
 error:
/* free the command buffer */
@@ -3556,7 +3557,8 @@ out:
bsg_reply->result = rc;
 
if (rc == BFA_STATUS_OK)
-   fc_bsg_jobdone(job);
+   fc_bsg_jobdone(job, bsg_reply->result,
+  bsg_reply->reply_payload_rcv_len);
 
return rc;
 }
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 21c9d28..1001d4a 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1939,7 +1939,8 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job)
ibmvfc_free_event(evt);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
bsg_reply->result = rc;
-   fc_bsg_jobdone(job);
+   fc_bsg_jobdone(job, bsg_reply->result,
+  bsg_reply->reply_payload_rcv_len);
rc = 0;
 out:
dma_unmap_sg(vhost->dev, job->request_payload.sg_list,
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 8811fe0..4bed7ec 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1912,7 +1912,8 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct 
fc_frame *fp,
-ECONNABORTED : -ETIMEDOUT;
job->reply_len = sizeof(uint32_t);
job->state_flags |= FC_RQST_STATE_DONE;
-   fc_bsg_jobdone(job);
+   fc_bsg_jobdone(job, bsg_reply->result,
+  bsg_reply->reply_payload_rcv_len);
kfree(info);
return;
}
@@ -1947,7 +1948,8 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct 
fc_frame *fp,
job->reply_payload.payload_len;
bsg_reply->result = 0;
job->state_flags |= FC_RQST_STATE_DONE;
-   fc_bsg_jobdone(job);
+   fc_bsg_jobdone(job, bsg_reply->result,
+  bsg_reply->reply_payload_rcv_len);
kfree(info);
}
fc_frame_free(fp);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 1db9cca..447a7af 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -371,7 +371,8 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
 
if (job) {
bsg_reply->result = rc;
-   fc_bsg_jobdone(job);
+   fc_bsg_jobdone(job, bsg_reply->result,
+  bsg_reply->reply_payload_rcv_len);
}
return;
 }
@@ -644,7 +645,8 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
 
if (job) {
bsg_reply->result = rc;
-   fc_bsg_jobdone(job);
+   fc_bsg_jobdone(job, bsg_reply->result,
+  bsg_reply->reply_payload_rcv_len);
}
return;
 }
@@ -1136,7 +1138,8 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
job->dd_data = NULL;
/* complete the job back to userspace */
spin_unlock_irqrestore(>ct_ev_lock, flags);
-   fc_bsg_jobdone(job);
+  

[PATCH v2 09/16] block: add reference counting for struct bsg_job

2016-10-12 Thread Johannes Thumshirn
Add reference counting to 'struct bsg_job' so we can implement a reuqest
timeout handler for bsg_jobs, which is needed for Fibre Channel.

Signed-off-by: Johannes Thumshirn 
---
 block/bsg-lib.c | 7 +--
 include/linux/bsg-lib.h | 2 ++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 650f427..632fb40 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -32,8 +32,10 @@
  * bsg_destroy_job - routine to teardown/delete a bsg job
  * @job: bsg_job that is to be torn down
  */
-static void bsg_destroy_job(struct bsg_job *job)
+static void bsg_destroy_job(struct kref *kref)
 {
+   struct bsg_job *job = container_of(kref, struct bsg_job, kref);
+
put_device(job->dev);   /* release reference for the request */
 
kfree(job->request_payload.sg_list);
@@ -84,7 +86,7 @@ static void bsg_softirq_done(struct request *rq)
struct bsg_job *job = rq->special;
 
blk_end_request_all(rq, rq->errors);
-   bsg_destroy_job(job);
+   kref_put(>kref, bsg_destroy_job);
 }
 
 static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
@@ -142,6 +144,7 @@ static int bsg_create_job(struct device *dev, struct 
request *req)
job->dev = dev;
/* take a reference for the request */
get_device(job->dev);
+   kref_init(>kref);
return 0;
 
 failjob_rls_rqst_payload:
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
index a226652..58e0717 100644
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -40,6 +40,8 @@ struct bsg_job {
struct device *dev;
struct request *req;
 
+   struct kref kref;
+
/* Transport/driver specific request/reply structs */
void *request;
void *reply;
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 05/16] scsi: fc: provide fc_bsg_to_shost() helper

2016-10-12 Thread Johannes Thumshirn
Provide fc_bsg_to_shost() helper that will become handy when we're moving from
struct fc_bsg_job to a plain struct bsg_job. Also use this little helper in
the LLDDs.

Signed-off-by: Johannes Thumshirn 
---
 drivers/s390/scsi/zfcp_fc.c  |  4 +--
 drivers/scsi/bfa/bfad_bsg.c  |  6 ++---
 drivers/scsi/ibmvscsi/ibmvfc.c   |  4 +--
 drivers/scsi/libfc/fc_lport.c|  2 +-
 drivers/scsi/lpfc/lpfc_bsg.c | 32 
 drivers/scsi/qla2xxx/qla_bsg.c   | 54 
 drivers/scsi/scsi_transport_fc.c |  2 +-
 include/scsi/scsi_transport_fc.h |  5 
 8 files changed, 56 insertions(+), 53 deletions(-)

diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 87f6330..813c286 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -905,7 +905,7 @@ static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct 
fc_bsg_job *job)
preamble_word1 = bsg_request->rqst_data.r_ct.preamble_word1;
gs_type = (preamble_word1 & 0xff00) >> 24;
 
-   adapter = (struct zfcp_adapter *) job->shost->hostdata[0];
+   adapter = shost_priv(fc_bsg_to_shost(job));
 
switch (gs_type) {
case FC_FST_ALIAS:
@@ -987,7 +987,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
struct zfcp_fsf_ct_els *ct_els = job->dd_data;
struct fc_bsg_request *bsg_request = job->request;
 
-   shost = job->rport ? rport_to_shost(job->rport) : job->shost;
+   shost = job->rport ? rport_to_shost(job->rport) : fc_bsg_to_shost(job);
adapter = (struct zfcp_adapter *)shost->hostdata[0];
 
if (!(atomic_read(>status) & ZFCP_STATUS_COMMON_OPEN))
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index e49a6c8..d3094270 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -3135,8 +3135,7 @@ bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
struct fc_bsg_request *bsg_request = job->request;
struct fc_bsg_reply *bsg_reply = job->reply;
uint32_t vendor_cmd = bsg_request->rqst_data.h_vendor.vendor_cmd[0];
-   struct bfad_im_port_s *im_port =
-   (struct bfad_im_port_s *) job->shost->hostdata[0];
+   struct bfad_im_port_s *im_port = shost_priv(fc_bsg_to_shost(job));
struct bfad_s *bfad = im_port->bfad;
struct request_queue *request_q = job->req->q;
void *payload_kbuf;
@@ -3358,8 +3357,7 @@ int
 bfad_im_bsg_els_ct_request(struct fc_bsg_job *job)
 {
struct bfa_bsg_data *bsg_data;
-   struct bfad_im_port_s *im_port =
-   (struct bfad_im_port_s *) job->shost->hostdata[0];
+   struct bfad_im_port_s *im_port = shost_priv(fc_bsg_to_shost(job));
struct bfad_s *bfad = im_port->bfad;
bfa_bsg_fcpt_t *bsg_fcpt;
struct bfad_fcxp*drv_fcxp;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 1001d4a..f7b50af 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1702,7 +1702,7 @@ static void ibmvfc_bsg_timeout_done(struct ibmvfc_event 
*evt)
  **/
 static int ibmvfc_bsg_timeout(struct fc_bsg_job *job)
 {
-   struct ibmvfc_host *vhost = shost_priv(job->shost);
+   struct ibmvfc_host *vhost = shost_priv(fc_bsg_to_shost(job));
unsigned long port_id = (unsigned long)job->dd_data;
struct ibmvfc_event *evt;
struct ibmvfc_tmf *tmf;
@@ -1815,7 +1815,7 @@ unlock_out:
  **/
 static int ibmvfc_bsg_request(struct fc_bsg_job *job)
 {
-   struct ibmvfc_host *vhost = shost_priv(job->shost);
+   struct ibmvfc_host *vhost = shost_priv(fc_bsg_to_shost(job));
struct fc_rport *rport = job->rport;
struct ibmvfc_passthru_mad *mad;
struct ibmvfc_event *evt;
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 4bed7ec..c60fdb9 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -2087,7 +2087,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
struct fc_bsg_request *bsg_request = job->request;
struct fc_bsg_reply *bsg_reply = job->reply;
struct request *rsp = job->req->next_rq;
-   struct Scsi_Host *shost = job->shost;
+   struct Scsi_Host *shost = fc_bsg_to_shost(job);
struct fc_lport *lport = shost_priv(shost);
struct fc_rport *rport;
struct fc_rport_priv *rdata;
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 447a7af..bfcc37d 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -384,7 +384,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
 static int
 lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
 {
-   struct lpfc_vport *vport = (struct lpfc_vport *)job->shost->hostdata;
+   struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
struct lpfc_hba *phba = vport->phba;
struct lpfc_rport_data *rdata = 

[PATCH v2 10/16] scsi: change FC drivers to use 'struct bsg_job'

2016-10-12 Thread Johannes Thumshirn
Change FC drivers to use 'struct bsg_job' from bsg-lib.h instead of 'struct
fc_bsg_job' from scsi_transport_fc.h and remove 'struct fc_bsg_job'.

Signed-off-by: Johannes Thumshirn 
---
 drivers/s390/scsi/zfcp_ext.h |  4 +--
 drivers/s390/scsi/zfcp_fc.c  | 15 
 drivers/scsi/bfa/bfad_bsg.c  | 10 +++---
 drivers/scsi/bfa/bfad_im.h   |  4 +--
 drivers/scsi/ibmvscsi/ibmvfc.c   |  9 ++---
 drivers/scsi/libfc/fc_lport.c| 10 +++---
 drivers/scsi/lpfc/lpfc_bsg.c | 74 
 drivers/scsi/lpfc/lpfc_crtn.h|  4 +--
 drivers/scsi/qla2xxx/qla_bsg.c   | 61 +
 drivers/scsi/qla2xxx/qla_def.h   |  2 +-
 drivers/scsi/qla2xxx/qla_gbl.h   |  4 +--
 drivers/scsi/qla2xxx/qla_iocb.c  |  8 ++---
 drivers/scsi/qla2xxx/qla_isr.c   |  6 ++--
 drivers/scsi/qla2xxx/qla_mr.c|  5 +--
 drivers/scsi/scsi_transport_fc.c | 20 +--
 include/scsi/libfc.h |  2 +-
 include/scsi/scsi_transport_fc.h | 63 ++
 17 files changed, 138 insertions(+), 163 deletions(-)

diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 5b50065..ab163be 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -82,8 +82,8 @@ extern void zfcp_fc_link_test_work(struct work_struct *);
 extern void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *);
 extern int zfcp_fc_gs_setup(struct zfcp_adapter *);
 extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
-extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
-extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
+extern int zfcp_fc_exec_bsg_job(struct bsg_job *);
+extern int zfcp_fc_timeout_bsg_job(struct bsg_job *);
 extern void zfcp_fc_sym_name_update(struct work_struct *);
 extern unsigned int zfcp_fc_port_scan_backoff(void);
 extern void zfcp_fc_conditional_port_scan(struct zfcp_adapter *);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 1977a66..b1b4129 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include "zfcp_ext.h"
@@ -885,7 +886,7 @@ out_free:
 
 static void zfcp_fc_ct_els_job_handler(void *data)
 {
-   struct fc_bsg_job *job = data;
+   struct bsg_job *job = data;
struct zfcp_fsf_ct_els *zfcp_ct_els = job->dd_data;
struct fc_bsg_reply *jr = job->reply;
 
@@ -895,7 +896,7 @@ static void zfcp_fc_ct_els_job_handler(void *data)
fc_bsg_jobdone(job, jr->result, jr->reply_payload_rcv_len);
 }
 
-static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job)
+static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct bsg_job *job)
 {
u32 preamble_word1;
u8 gs_type;
@@ -925,7 +926,7 @@ static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct 
fc_bsg_job *job)
 
 static void zfcp_fc_ct_job_handler(void *data)
 {
-   struct fc_bsg_job *job = data;
+   struct bsg_job *job = data;
struct zfcp_fc_wka_port *wka_port;
 
wka_port = zfcp_fc_job_wka_port(job);
@@ -934,7 +935,7 @@ static void zfcp_fc_ct_job_handler(void *data)
zfcp_fc_ct_els_job_handler(data);
 }
 
-static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
+static int zfcp_fc_exec_els_job(struct bsg_job *job,
struct zfcp_adapter *adapter)
 {
struct zfcp_fsf_ct_els *els = job->dd_data;
@@ -957,7 +958,7 @@ static int zfcp_fc_exec_els_job(struct fc_bsg_job *job,
return zfcp_fsf_send_els(adapter, d_id, els, job->req->timeout / HZ);
 }
 
-static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job,
+static int zfcp_fc_exec_ct_job(struct bsg_job *job,
   struct zfcp_adapter *adapter)
 {
int ret;
@@ -980,7 +981,7 @@ static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job,
return ret;
 }
 
-int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
+int zfcp_fc_exec_bsg_job(struct bsg_job *job)
 {
struct Scsi_Host *shost;
struct zfcp_adapter *adapter;
@@ -1010,7 +1011,7 @@ int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job)
}
 }
 
-int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *job)
+int zfcp_fc_timeout_bsg_job(struct bsg_job *job)
 {
/* hardware tracks timeout, reset bsg timeout to not interfere */
return -EAGAIN;
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index d3094270..cdc25e6 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -3130,7 +3130,7 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, 
void *iocmd,
 }
 
 static int
-bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
+bfad_im_bsg_vendor_request(struct bsg_job *job)
 {
struct fc_bsg_request *bsg_request = job->request;
struct fc_bsg_reply *bsg_reply = job->reply;
@@ -3314,7 +3314,7 @@ bfad_fcxp_free_mem(struct bfad_s *bfad, struct 
bfad_buf_info 

[PATCH v2 03/16] scsi: fc: Export fc_bsg_jobdone and use it in FC drivers

2016-10-12 Thread Johannes Thumshirn
Export fc_bsg_jobdone so drivers can use it directly instead of doing
the round-trip via struct fc_bsg_job::job_done() and use it in the LLDDs.

As we've converted all LLDDs over to use fc_bsg_jobdone() directly,
we can remove the function pointer from struct fc_bsg_job as well.

Signed-off-by: Johannes Thumshirn 
---
 drivers/s390/scsi/zfcp_fc.c  |  2 +-
 drivers/scsi/bfa/bfad_bsg.c  |  4 ++--
 drivers/scsi/ibmvscsi/ibmvfc.c   |  2 +-
 drivers/scsi/libfc/fc_lport.c|  4 ++--
 drivers/scsi/lpfc/lpfc_bsg.c | 38 +-
 drivers/scsi/qla2xxx/qla_bsg.c   | 44 
 drivers/scsi/scsi_transport_fc.c |  5 ++---
 include/scsi/scsi_transport_fc.h |  2 +-
 8 files changed, 50 insertions(+), 51 deletions(-)

diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 4c4023f..40d8f06 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -892,7 +892,7 @@ static void zfcp_fc_ct_els_job_handler(void *data)
jr->reply_payload_rcv_len = job->reply_payload.payload_len;
jr->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
jr->result = zfcp_ct_els->status ? -EIO : 0;
-   job->job_done(job);
+   fc_bsg_jobdone(job);
 }
 
 static struct zfcp_fc_wka_port *zfcp_fc_job_wka_port(struct fc_bsg_job *job)
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 48366d8..25889b9 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -3180,7 +3180,7 @@ bfad_im_bsg_vendor_request(struct fc_bsg_job *job)
bsg_reply->reply_payload_rcv_len = job->reply_payload.payload_len;
bsg_reply->result = rc;
 
-   job->job_done(job);
+   fc_bsg_jobdone(job);
return rc;
 error:
/* free the command buffer */
@@ -3556,7 +3556,7 @@ out:
bsg_reply->result = rc;
 
if (rc == BFA_STATUS_OK)
-   job->job_done(job);
+   fc_bsg_jobdone(job);
 
return rc;
 }
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 8b55279..21c9d28 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1939,7 +1939,7 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job)
ibmvfc_free_event(evt);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
bsg_reply->result = rc;
-   job->job_done(job);
+   fc_bsg_jobdone(job);
rc = 0;
 out:
dma_unmap_sg(vhost->dev, job->request_payload.sg_list,
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index a1c12e7..8811fe0 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1912,7 +1912,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct 
fc_frame *fp,
-ECONNABORTED : -ETIMEDOUT;
job->reply_len = sizeof(uint32_t);
job->state_flags |= FC_RQST_STATE_DONE;
-   job->job_done(job);
+   fc_bsg_jobdone(job);
kfree(info);
return;
}
@@ -1947,7 +1947,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct 
fc_frame *fp,
job->reply_payload.payload_len;
bsg_reply->result = 0;
job->state_flags |= FC_RQST_STATE_DONE;
-   job->job_done(job);
+   fc_bsg_jobdone(job);
kfree(info);
}
fc_frame_free(fp);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 27b5930..1db9cca 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -371,7 +371,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
 
if (job) {
bsg_reply->result = rc;
-   job->job_done(job);
+   fc_bsg_jobdone(job);
}
return;
 }
@@ -644,7 +644,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
 
if (job) {
bsg_reply->result = rc;
-   job->job_done(job);
+   fc_bsg_jobdone(job);
}
return;
 }
@@ -1136,7 +1136,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct 
lpfc_sli_ring *pring,
job->dd_data = NULL;
/* complete the job back to userspace */
spin_unlock_irqrestore(>ct_ev_lock, flags);
-   job->job_done(job);
+   fc_bsg_jobdone(job);
spin_lock_irqsave(>ct_ev_lock, flags);
}
}
@@ -1361,7 +1361,7 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job)
spin_unlock_irqrestore(>ct_ev_lock, flags);
job->dd_data = NULL;
bsg_reply->result = 0;
-   job->job_done(job);
+   fc_bsg_jobdone(job);
return 0;
 
 job_error:
@@ -1458,7 +1458,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
 
if (job) {

[PATCH v2 08/16] scsi: fc: implement kref backed reference counting

2016-10-12 Thread Johannes Thumshirn
Implement kref backed reference counting instead of rolling our own. This
elimnates the need of the following fields in 'struct fc_bsg_job':
* ref_cnt
* state_flags
* job_lock
bringing us close to unification of 'struct fc_bsg_job' and 'struct bsg_job'.

Signed-off-by: Johannes Thumshirn 
---
 drivers/scsi/scsi_transport_fc.c | 38 +-
 include/scsi/scsi_transport_fc.h |  4 +---
 2 files changed, 10 insertions(+), 32 deletions(-)

diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 96b3a2e..b0e28af 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3560,16 +3560,9 @@ fc_vport_sched_delete(struct work_struct *work)
  * @job:   fc_bsg_job that is to be torn down
  */
 static void
-fc_destroy_bsgjob(struct fc_bsg_job *job)
+fc_destroy_bsgjob(struct kref *kref)
 {
-   unsigned long flags;
-
-   spin_lock_irqsave(>job_lock, flags);
-   if (job->ref_cnt) {
-   spin_unlock_irqrestore(>job_lock, flags);
-   return;
-   }
-   spin_unlock_irqrestore(>job_lock, flags);
+   struct fc_bsg_job *job = container_of(kref, struct fc_bsg_job, kref);
 
put_device(job->dev);   /* release reference for the request */
 
@@ -3620,15 +3613,9 @@ EXPORT_SYMBOL_GPL(fc_bsg_jobdone);
 static void fc_bsg_softirq_done(struct request *rq)
 {
struct fc_bsg_job *job = rq->special;
-   unsigned long flags;
-
-   spin_lock_irqsave(>job_lock, flags);
-   job->state_flags |= FC_RQST_STATE_DONE;
-   job->ref_cnt--;
-   spin_unlock_irqrestore(>job_lock, flags);
 
blk_end_request_all(rq, rq->errors);
-   fc_destroy_bsgjob(job);
+   kref_put(>kref, fc_destroy_bsgjob);
 }
 
 /**
@@ -3642,24 +3629,18 @@ fc_bsg_job_timeout(struct request *req)
struct Scsi_Host *shost = fc_bsg_to_shost(job);
struct fc_rport *rport = fc_bsg_to_rport(job);
struct fc_internal *i = to_fc_internal(shost->transportt);
-   unsigned long flags;
-   int err = 0, done = 0;
+   int err = 0, inflight = 0;
 
if (rport && rport->port_state == FC_PORTSTATE_BLOCKED)
return BLK_EH_RESET_TIMER;
 
-   spin_lock_irqsave(>job_lock, flags);
-   if (job->state_flags & FC_RQST_STATE_DONE)
-   done = 1;
-   else
-   job->ref_cnt++;
-   spin_unlock_irqrestore(>job_lock, flags);
+   inflight = kref_get_unless_zero(>kref);
 
-   if (!done && i->f->bsg_timeout) {
+   if (inflight && i->f->bsg_timeout) {
/* call LLDD to abort the i/o as it has timed out */
err = i->f->bsg_timeout(job);
if (err == -EAGAIN) {
-   job->ref_cnt--;
+   kref_put(>kref, fc_destroy_bsgjob);
return BLK_EH_RESET_TIMER;
} else if (err)
printk(KERN_ERR "ERROR: FC BSG request timeout - LLD "
@@ -3667,7 +3648,7 @@ fc_bsg_job_timeout(struct request *req)
}
 
/* the blk_end_sync_io() doesn't check the error */
-   if (done)
+   if (!inflight)
return BLK_EH_NOT_HANDLED;
else
return BLK_EH_HANDLED;
@@ -3730,7 +3711,6 @@ fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport 
*rport,
job->req = req;
if (i->f->dd_bsg_size)
job->dd_data = (void *)[1];
-   spin_lock_init(>job_lock);
bsg_request = (struct fc_bsg_request *)req->cmd;
job->request_len = req->cmd_len;
bsg_reply = req->sense;
@@ -3752,7 +3732,7 @@ fc_req_to_bsgjob(struct Scsi_Host *shost, struct fc_rport 
*rport,
job->dev = >shost_gendev;
get_device(job->dev);   /* take a reference for the request */
 
-   job->ref_cnt = 1;
+   kref_init(>kref);
 
return 0;
 
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 9f53fe3..8ae5680 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -634,9 +634,7 @@ struct fc_bsg_job {
struct fc_rport *rport;
struct device *dev;
struct request *req;
-   spinlock_t job_lock;
-   unsigned int state_flags;
-   unsigned int ref_cnt;
+   struct kref kref;
 
struct fc_bsg_request *request;
struct fc_bsg_reply *reply;
-- 
1.8.5.6

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [bug report] scsi: hisi_sas: add internal abort to hisi_sas_abort_task()

2016-10-12 Thread John Garry

On 12/10/2016 14:12, Dan Carpenter wrote:

Hello John Garry,

The patch dc8a49cabc73: "scsi: hisi_sas: add internal abort to
hisi_sas_abort_task()" from Aug 24, 2016, leads to the following
static checker warning:

drivers/scsi/hisi_sas/hisi_sas_main.c:848 hisi_sas_abort_task()
error: we previously assumed 'slot' could be null (see line 847)

drivers/scsi/hisi_sas/hisi_sas_main.c
809  spin_unlock_irqrestore(>task_state_lock, flags);
810  sas_dev->dev_status = HISI_SAS_DEV_EH;
811  if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
 ^^^
We assume that ->lldd_task can be NULL.

812  struct scsi_cmnd *cmnd = task->uldd_task;
813  struct hisi_sas_slot *slot = task->lldd_task;
814  u32 tag = slot->idx;
815
816  int_to_scsilun(cmnd->device->lun, );
817  tmf_task.tmf = TMF_ABORT_TASK;
818  tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
819
820  rc = hisi_sas_debug_issue_ssp_tmf(task->dev, 
lun.scsi_lun,
821_task);
822
823  /* if successful, clear the task and callback 
forwards.*/
824  if (rc == TMF_RESP_FUNC_COMPLETE) {
825  if (task->lldd_task) {
826  struct hisi_sas_slot *slot;
827
828  slot = _hba->slot_info
829  
[tmf_task.tag_of_task_to_be_managed];
830  spin_lock_irqsave(_hba->lock, 
flags);
831  hisi_hba->hw->slot_complete(hisi_hba, 
slot, 1);
832  
spin_unlock_irqrestore(_hba->lock, flags);
833  }
834  }
835
836  hisi_sas_internal_task_abort(hisi_hba, device,
837   HISI_SAS_INT_ABT_CMD, 
tag);
838  } else if (task->task_proto & SAS_PROTOCOL_SATA ||
839  task->task_proto & SAS_PROTOCOL_STP) {
840  if (task->dev->dev_type == SAS_SATA_DEV) {
841  hisi_sas_internal_task_abort(hisi_hba, device,
842   
HISI_SAS_INT_ABT_DEV, 0);
843  rc = TMF_RESP_FUNC_COMPLETE;
844  }
845  } else if (task->task_proto & SAS_PROTOCOL_SMP) {
846  /* SMP */
847  struct hisi_sas_slot *slot = task->lldd_task;

We assign it to slot.


I will check this.

Thanks,
John



848  u32 tag = slot->idx;
   ^
slot dereferenced without checking.

849
850  hisi_sas_internal_task_abort(hisi_hba, device,
851   HISI_SAS_INT_ABT_CMD, 
tag);
852  }



regards,
dan carpenter

.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/44] Convert FibreChannel bsg code to use bsg-lib

2016-10-12 Thread Johannes Thumshirn
On Tue, Oct 11, 2016 at 09:49:38AM -0700, Christoph Hellwig wrote:
> Hi Johannes,
> 
> this looks great to me.  But is there a chance to consolidate it into
> a more manageable set of patches?  E.g. all the patches to call
> export fc_bsg_jobdone, use it directly and remove the function pointer
> could go together, possibly even including the new calling convention.
> Similar all the patches about fc_bsg_to_shost could be merged into one,
> and if we add the bsg refcounting early, we could maybe skip a few
> steps of the conversion later on?

Sure, I think 44 patches is a bit huge. Especially given the 0day bot
fallout it generated. Let me see how I can slim it down.

Johannes

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 1/3] Synchronization of cmds during termination conditions

2016-10-12 Thread Greg KH
On Tue, Oct 11, 2016 at 05:58:03PM -0500, Michael Cyr wrote:
> Signed-off-by: Michael Cyr 

I almost never accept patches with no changelog information.  For a
patch that changes 1082 lines in a non-trivial way, you would think that
you could explain why you are doing this work...

Also, check the prefix of your subject, it give no clue as to where in
the kernel your patches touch :(

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[bug report] scsi: hisi_sas: add internal abort to hisi_sas_abort_task()

2016-10-12 Thread Dan Carpenter
Hello John Garry,

The patch dc8a49cabc73: "scsi: hisi_sas: add internal abort to
hisi_sas_abort_task()" from Aug 24, 2016, leads to the following
static checker warning:

drivers/scsi/hisi_sas/hisi_sas_main.c:848 hisi_sas_abort_task()
error: we previously assumed 'slot' could be null (see line 847)

drivers/scsi/hisi_sas/hisi_sas_main.c
   809  spin_unlock_irqrestore(>task_state_lock, flags);
   810  sas_dev->dev_status = HISI_SAS_DEV_EH;
   811  if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
^^^
We assume that ->lldd_task can be NULL.

   812  struct scsi_cmnd *cmnd = task->uldd_task;
   813  struct hisi_sas_slot *slot = task->lldd_task;
   814  u32 tag = slot->idx;
   815  
   816  int_to_scsilun(cmnd->device->lun, );
   817  tmf_task.tmf = TMF_ABORT_TASK;
   818  tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
   819  
   820  rc = hisi_sas_debug_issue_ssp_tmf(task->dev, 
lun.scsi_lun,
   821_task);
   822  
   823  /* if successful, clear the task and callback 
forwards.*/
   824  if (rc == TMF_RESP_FUNC_COMPLETE) {
   825  if (task->lldd_task) {
   826  struct hisi_sas_slot *slot;
   827  
   828  slot = _hba->slot_info
   829  
[tmf_task.tag_of_task_to_be_managed];
   830  spin_lock_irqsave(_hba->lock, 
flags);
   831  hisi_hba->hw->slot_complete(hisi_hba, 
slot, 1);
   832  spin_unlock_irqrestore(_hba->lock, 
flags);
   833  }
   834  }
   835  
   836  hisi_sas_internal_task_abort(hisi_hba, device,
   837   HISI_SAS_INT_ABT_CMD, tag);
   838  } else if (task->task_proto & SAS_PROTOCOL_SATA ||
   839  task->task_proto & SAS_PROTOCOL_STP) {
   840  if (task->dev->dev_type == SAS_SATA_DEV) {
   841  hisi_sas_internal_task_abort(hisi_hba, device,
   842   
HISI_SAS_INT_ABT_DEV, 0);
   843  rc = TMF_RESP_FUNC_COMPLETE;
   844  }
   845  } else if (task->task_proto & SAS_PROTOCOL_SMP) {
   846  /* SMP */
   847  struct hisi_sas_slot *slot = task->lldd_task;

We assign it to slot.

   848  u32 tag = slot->idx;
  ^
slot dereferenced without checking.

   849  
   850  hisi_sas_internal_task_abort(hisi_hba, device,
   851   HISI_SAS_INT_ABT_CMD, tag);
   852  }



regards,
dan carpenter
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html