[PATCH 10/10] mm: replace access_process_vm() write parameter with gup_flags
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
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
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
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
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
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
- 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()
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
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()
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
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
Revise strings with full lpfc parameter name Signed-off-by: Dick KennedySigned-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
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 KennedySigned-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
Fix lost target in pt-to-pt connect Change reject code to something that allows a retry Signed-off-by: Dick KennedySigned-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
Code cleanup for lpfc_sriov_nr_virtfn parameter Signed-off-by: Dick KennedySigned-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
lpfc version changed to 11.2.0.2 Signed-off-by: Dick KennedySigned-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
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 KennedySigned-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
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 KennedySigned-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
Code cleanup for lpfc_max_scsicmpl_time parameter Signed-off-by: Dick KennedySigned-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
Code clean up for lpfc_iocb_cnt parameter Signed-off-by: Dick KennedySigned-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
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 KennedySigned-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
Code cleanup for lpfc_enable_rrq parameter Signed-off-by: Dick KennedySigned-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
Code cleanup for lpfc_topology parameter Signed-off-by: Dick KennedySigned-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
Code cleanup for lpfc_aer_support parameter Signed-off-by: Dick KennedySigned-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
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
Make lpfc_prot_mask and lpfc_prot_guard per hba parameters Signed-off-by: Dick KennedySigned-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
Set driver environment data on adapter Signed-off-by: Dick KennedySigned-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
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 KennedySigned-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
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
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
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 DevDate: 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
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 DevDate: 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
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()
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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'
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
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
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()
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
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
On Tue, Oct 11, 2016 at 05:58:03PM -0500, Michael Cyr wrote: > Signed-off-by: Michael CyrI 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()
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