Revision c0cf4512a31eb3cec70b066bc36ed55f7d05b8c0 authored by Bart Van Assche on 23 June 2016, 07:35:48 UTC, committed by Doug Ledford on 23 June 2016, 16:04:09 UTC
The memory needed for the send and receive queues associated with a QP is proportional to the max_sge parameter. The current value of that parameter is such that with an mlx4 HCA the QP buffer size is 8 MB. Since DMA is used for communication between HCA and CPU that buffer either has to be allocated coherently or map_single() must succeed for that buffer. Since large contiguous allocations are fragile and since the maximum segment size for e.g. swiotlb is 256 KB, reduce the max_sge parameter. This patch avoids that the following text appears on the console after SRP logout and relogin on a system equipped with multiple IB HCAs: mlx4_core 0000:05:00.0: swiotlb buffer is full (sz: 8388608 bytes) swiotlb: coherent allocation failed for device 0000:05:00.0 size=8388608 CPU: 11 PID: 148 Comm: kworker/11:1 Not tainted 4.7.0-rc4-dbg+ #1 Call Trace: [<ffffffff812c6d35>] dump_stack+0x67/0x92 [<ffffffff812efe71>] swiotlb_alloc_coherent+0x141/0x150 [<ffffffff810458be>] x86_swiotlb_alloc_coherent+0x3e/0x50 [<ffffffffa03861fa>] mlx4_buf_direct_alloc.isra.5+0x9a/0x120 [mlx4_core] [<ffffffffa0386545>] mlx4_buf_alloc+0x165/0x1a0 [mlx4_core] [<ffffffffa035053d>] create_qp_common.isra.29+0x57d/0xff0 [mlx4_ib] [<ffffffffa03510da>] mlx4_ib_create_qp+0x12a/0x3f0 [mlx4_ib] [<ffffffffa031154a>] ib_create_qp+0x3a/0x250 [ib_core] [<ffffffffa055dd4b>] srpt_cm_handler+0x4bb/0xcad [ib_srpt] [<ffffffffa02c1ab0>] cm_process_work+0x20/0xf0 [ib_cm] [<ffffffffa02c3640>] cm_work_handler+0x1ac0/0x2059 [ib_cm] [<ffffffff810737ed>] process_one_work+0x19d/0x490 [<ffffffff81073b29>] worker_thread+0x49/0x490 [<ffffffff8107a0ea>] kthread+0xea/0x100 [<ffffffff815b25af>] ret_from_fork+0x1f/0x40 Fixes: b99f8e4d7bcd ("IB/srpt: convert to the generic RDMA READ/WRITE API") Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com> Cc: Laurence Oberman <loberman@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Doug Ledford <dledford@redhat.com>
1 parent 37e07cd
syscall.c
#include <linux/ptrace.h>
#include <linux/sched.h>
#include <linux/export.h>
#include <asm/syscall.h>
static int collect_syscall(struct task_struct *target, long *callno,
unsigned long args[6], unsigned int maxargs,
unsigned long *sp, unsigned long *pc)
{
struct pt_regs *regs = task_pt_regs(target);
if (unlikely(!regs))
return -EAGAIN;
*sp = user_stack_pointer(regs);
*pc = instruction_pointer(regs);
*callno = syscall_get_nr(target, regs);
if (*callno != -1L && maxargs > 0)
syscall_get_arguments(target, regs, 0, maxargs, args);
return 0;
}
/**
* task_current_syscall - Discover what a blocked task is doing.
* @target: thread to examine
* @callno: filled with system call number or -1
* @args: filled with @maxargs system call arguments
* @maxargs: number of elements in @args to fill
* @sp: filled with user stack pointer
* @pc: filled with user PC
*
* If @target is blocked in a system call, returns zero with *@callno
* set to the the call's number and @args filled in with its arguments.
* Registers not used for system call arguments may not be available and
* it is not kosher to use &struct user_regset calls while the system
* call is still in progress. Note we may get this result if @target
* has finished its system call but not yet returned to user mode, such
* as when it's stopped for signal handling or syscall exit tracing.
*
* If @target is blocked in the kernel during a fault or exception,
* returns zero with *@callno set to -1 and does not fill in @args.
* If so, it's now safe to examine @target using &struct user_regset
* get() calls as long as we're sure @target won't return to user mode.
*
* Returns -%EAGAIN if @target does not remain blocked.
*
* Returns -%EINVAL if @maxargs is too large (maximum is six).
*/
int task_current_syscall(struct task_struct *target, long *callno,
unsigned long args[6], unsigned int maxargs,
unsigned long *sp, unsigned long *pc)
{
long state;
unsigned long ncsw;
if (unlikely(maxargs > 6))
return -EINVAL;
if (target == current)
return collect_syscall(target, callno, args, maxargs, sp, pc);
state = target->state;
if (unlikely(!state))
return -EAGAIN;
ncsw = wait_task_inactive(target, state);
if (unlikely(!ncsw) ||
unlikely(collect_syscall(target, callno, args, maxargs, sp, pc)) ||
unlikely(wait_task_inactive(target, state) != ncsw))
return -EAGAIN;
return 0;
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...