Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d060e0f6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Doug Ledford:
 "This is the second pull request for the rdma subsystem.  Most of the
  patches are small and obvious.  I took two patches in that are larger
  than I wanted this late in the cycle.

  The first is the hfi1 patch that implements a work queue to test the
  QSFP read state.  I originally rejected the first patch for this
  (which would have place up to 20 seconds worth of udelays in their
  probe routine).  They then rewrote it the way I wanted (use delayed
  work tasks to wait asynchronously up to 20 seconds for the QSFP to
  come alive), so I can't really complain about the size of getting what
  I asked for :-/.

  The second is large because it switches the rcu locking in the debugfs
  code.  Since a locking change like this is done all at once, the size
  it what it is.  It resolves a litany of debug messages from the
  kernel, so I pulled it in for -rc.

  The rest are all typical -rc worthy patches I think.

  There will still be a third -rc pull request from the rdma subsystem
  this release.  I hope to have that one ready to go by the end of this
  week or early next.

  Summary:

   - a smattering of small fixes across the core, ipoib, i40iw, isert,
     cxgb4, and mlx4

   - a slightly larger group of fixes to each of mlx5 and hfi1"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma:
  IB/hfi1: Rework debugfs to use SRCU
  IB/hfi1: Make n_krcvqs be an unsigned long integer
  IB/hfi1: Add QSFP sanity pre-check
  IB/hfi1: Fix AHG KDETH Intr shift
  IB/hfi1: Fix SGE length for misaligned PIO copy
  IB/mlx5: Don't return errors from poll_cq
  IB/mlx5: Use TIR number based on selector
  IB/mlx5: Simplify code by removing return variable
  IB/mlx5: Return EINVAL when caller specifies too many SGEs
  IB/mlx4: Don't return errors from poll_cq
  Revert "IB/mlx4: Return EAGAIN for any error in mlx4_ib_poll_one"
  IB/ipoib: Fix memory corruption in ipoib cm mode connect flow
  IB/core: Fix use after free in send_leave function
  IB/cxgb4: Make _free_qp static to silence build warning
  IB/isert: Properly release resources on DEVICE_REMOVAL
  IB/hfi1: Fix the size parameter to find_first_bit
  IB/mlx5: Fix the size parameter to find_first_bit
  IB/hfi1: Clean up type used and casting
  i40iw: Receive notification events correctly
  i40iw: Update hw_iwarp_state
parents 46738ab3 16170d9c
Loading
Loading
Loading
Loading
+2 −11
Original line number Diff line number Diff line
@@ -106,7 +106,6 @@ struct mcast_group {
	atomic_t		refcount;
	enum mcast_group_state	state;
	struct ib_sa_query	*query;
	int			query_id;
	u16			pkey_index;
	u8			leave_state;
	int			retries;
@@ -340,11 +339,7 @@ static int send_join(struct mcast_group *group, struct mcast_member *member)
				       member->multicast.comp_mask,
				       3000, GFP_KERNEL, join_handler, group,
				       &group->query);
	if (ret >= 0) {
		group->query_id = ret;
		ret = 0;
	}
	return ret;
	return (ret > 0) ? 0 : ret;
}

static int send_leave(struct mcast_group *group, u8 leave_state)
@@ -364,11 +359,7 @@ static int send_leave(struct mcast_group *group, u8 leave_state)
				       IB_SA_MCMEMBER_REC_JOIN_STATE,
				       3000, GFP_KERNEL, leave_handler,
				       group, &group->query);
	if (ret >= 0) {
		group->query_id = ret;
		ret = 0;
	}
	return ret;
	return (ret > 0) ? 0 : ret;
}

static void join_group(struct mcast_group *group, struct mcast_member *member,
+1 −1
Original line number Diff line number Diff line
@@ -683,7 +683,7 @@ static int build_inv_stag(union t4_wr *wqe, struct ib_send_wr *wr,
	return 0;
}

void _free_qp(struct kref *kref)
static void _free_qp(struct kref *kref)
{
	struct c4iw_qp *qhp;

+81 −11
Original line number Diff line number Diff line
@@ -9490,6 +9490,78 @@ static void init_lcb(struct hfi1_devdata *dd)
	write_csr(dd, DC_LCB_CFG_TX_FIFOS_RESET, 0x00);
}

/*
 * Perform a test read on the QSFP.  Return 0 on success, -ERRNO
 * on error.
 */
static int test_qsfp_read(struct hfi1_pportdata *ppd)
{
	int ret;
	u8 status;

	/* report success if not a QSFP */
	if (ppd->port_type != PORT_TYPE_QSFP)
		return 0;

	/* read byte 2, the status byte */
	ret = one_qsfp_read(ppd, ppd->dd->hfi1_id, 2, &status, 1);
	if (ret < 0)
		return ret;
	if (ret != 1)
		return -EIO;

	return 0; /* success */
}

/*
 * Values for QSFP retry.
 *
 * Give up after 10s (20 x 500ms).  The overall timeout was empirically
 * arrived at from experience on a large cluster.
 */
#define MAX_QSFP_RETRIES 20
#define QSFP_RETRY_WAIT 500 /* msec */

/*
 * Try a QSFP read.  If it fails, schedule a retry for later.
 * Called on first link activation after driver load.
 */
static void try_start_link(struct hfi1_pportdata *ppd)
{
	if (test_qsfp_read(ppd)) {
		/* read failed */
		if (ppd->qsfp_retry_count >= MAX_QSFP_RETRIES) {
			dd_dev_err(ppd->dd, "QSFP not responding, giving up\n");
			return;
		}
		dd_dev_info(ppd->dd,
			    "QSFP not responding, waiting and retrying %d\n",
			    (int)ppd->qsfp_retry_count);
		ppd->qsfp_retry_count++;
		queue_delayed_work(ppd->hfi1_wq, &ppd->start_link_work,
				   msecs_to_jiffies(QSFP_RETRY_WAIT));
		return;
	}
	ppd->qsfp_retry_count = 0;

	/*
	 * Tune the SerDes to a ballpark setting for optimal signal and bit
	 * error rate.  Needs to be done before starting the link.
	 */
	tune_serdes(ppd);
	start_link(ppd);
}

/*
 * Workqueue function to start the link after a delay.
 */
void handle_start_link(struct work_struct *work)
{
	struct hfi1_pportdata *ppd = container_of(work, struct hfi1_pportdata,
						  start_link_work.work);
	try_start_link(ppd);
}

int bringup_serdes(struct hfi1_pportdata *ppd)
{
	struct hfi1_devdata *dd = ppd->dd;
@@ -9525,14 +9597,8 @@ int bringup_serdes(struct hfi1_pportdata *ppd)
		set_qsfp_int_n(ppd, 1);
	}

	/*
	 * Tune the SerDes to a ballpark setting for
	 * optimal signal and bit error rate
	 * Needs to be done before starting the link
	 */
	tune_serdes(ppd);

	return start_link(ppd);
	try_start_link(ppd);
	return 0;
}

void hfi1_quiet_serdes(struct hfi1_pportdata *ppd)
@@ -9549,6 +9615,10 @@ void hfi1_quiet_serdes(struct hfi1_pportdata *ppd)
	ppd->driver_link_ready = 0;
	ppd->link_enabled = 0;

	ppd->qsfp_retry_count = MAX_QSFP_RETRIES; /* prevent more retries */
	flush_delayed_work(&ppd->start_link_work);
	cancel_delayed_work_sync(&ppd->start_link_work);

	ppd->offline_disabled_reason =
			HFI1_ODR_MASK(OPA_LINKDOWN_REASON_SMA_DISABLED);
	set_link_down_reason(ppd, OPA_LINKDOWN_REASON_SMA_DISABLED, 0,
@@ -12865,7 +12935,7 @@ static int set_up_interrupts(struct hfi1_devdata *dd)
 */
static int set_up_context_variables(struct hfi1_devdata *dd)
{
	int num_kernel_contexts;
	unsigned long num_kernel_contexts;
	int total_contexts;
	int ret;
	unsigned ngroups;
@@ -12894,9 +12964,9 @@ static int set_up_context_variables(struct hfi1_devdata *dd)
	 */
	if (num_kernel_contexts > (dd->chip_send_contexts - num_vls - 1)) {
		dd_dev_err(dd,
			   "Reducing # kernel rcv contexts to: %d, from %d\n",
			   "Reducing # kernel rcv contexts to: %d, from %lu\n",
			   (int)(dd->chip_send_contexts - num_vls - 1),
			   (int)num_kernel_contexts);
			   num_kernel_contexts);
		num_kernel_contexts = dd->chip_send_contexts - num_vls - 1;
	}
	/*
+1 −0
Original line number Diff line number Diff line
@@ -706,6 +706,7 @@ void handle_link_up(struct work_struct *work);
void handle_link_down(struct work_struct *work);
void handle_link_downgrade(struct work_struct *work);
void handle_link_bounce(struct work_struct *work);
void handle_start_link(struct work_struct *work);
void handle_sma_message(struct work_struct *work);
void reset_qsfp(struct hfi1_pportdata *ppd);
void qsfp_event(struct work_struct *work);
+52 −80
Original line number Diff line number Diff line
@@ -59,6 +59,40 @@

static struct dentry *hfi1_dbg_root;

/* wrappers to enforce srcu in seq file */
static ssize_t hfi1_seq_read(
	struct file *file,
	char __user *buf,
	size_t size,
	loff_t *ppos)
{
	struct dentry *d = file->f_path.dentry;
	int srcu_idx;
	ssize_t r;

	r = debugfs_use_file_start(d, &srcu_idx);
	if (likely(!r))
		r = seq_read(file, buf, size, ppos);
	debugfs_use_file_finish(srcu_idx);
	return r;
}

static loff_t hfi1_seq_lseek(
	struct file *file,
	loff_t offset,
	int whence)
{
	struct dentry *d = file->f_path.dentry;
	int srcu_idx;
	loff_t r;

	r = debugfs_use_file_start(d, &srcu_idx);
	if (likely(!r))
		r = seq_lseek(file, offset, whence);
	debugfs_use_file_finish(srcu_idx);
	return r;
}

#define private2dd(file) (file_inode(file)->i_private)
#define private2ppd(file) (file_inode(file)->i_private)

@@ -87,8 +121,8 @@ static int _##name##_open(struct inode *inode, struct file *s) \
static const struct file_operations _##name##_file_ops = { \
	.owner   = THIS_MODULE, \
	.open    = _##name##_open, \
	.read    = seq_read, \
	.llseek  = seq_lseek, \
	.read    = hfi1_seq_read, \
	.llseek  = hfi1_seq_lseek, \
	.release = seq_release \
}

@@ -105,11 +139,9 @@ do { \
	DEBUGFS_FILE_CREATE(#name, parent, data, &_##name##_file_ops, S_IRUGO)

static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos)
__acquires(RCU)
{
	struct hfi1_opcode_stats_perctx *opstats;

	rcu_read_lock();
	if (*pos >= ARRAY_SIZE(opstats->stats))
		return NULL;
	return pos;
@@ -126,9 +158,7 @@ static void *_opcode_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
}

static void _opcode_stats_seq_stop(struct seq_file *s, void *v)
__releases(RCU)
{
	rcu_read_unlock();
}

static int _opcode_stats_seq_show(struct seq_file *s, void *v)
@@ -285,12 +315,10 @@ DEBUGFS_SEQ_FILE_OPEN(qp_stats)
DEBUGFS_FILE_OPS(qp_stats);

static void *_sdes_seq_start(struct seq_file *s, loff_t *pos)
__acquires(RCU)
{
	struct hfi1_ibdev *ibd;
	struct hfi1_devdata *dd;

	rcu_read_lock();
	ibd = (struct hfi1_ibdev *)s->private;
	dd = dd_from_dev(ibd);
	if (!dd->per_sdma || *pos >= dd->num_sdma)
@@ -310,9 +338,7 @@ static void *_sdes_seq_next(struct seq_file *s, void *v, loff_t *pos)
}

static void _sdes_seq_stop(struct seq_file *s, void *v)
__releases(RCU)
{
	rcu_read_unlock();
}

static int _sdes_seq_show(struct seq_file *s, void *v)
@@ -339,11 +365,9 @@ static ssize_t dev_counters_read(struct file *file, char __user *buf,
	struct hfi1_devdata *dd;
	ssize_t rval;

	rcu_read_lock();
	dd = private2dd(file);
	avail = hfi1_read_cntrs(dd, NULL, &counters);
	rval =  simple_read_from_buffer(buf, count, ppos, counters, avail);
	rcu_read_unlock();
	return rval;
}

@@ -356,11 +380,9 @@ static ssize_t dev_names_read(struct file *file, char __user *buf,
	struct hfi1_devdata *dd;
	ssize_t rval;

	rcu_read_lock();
	dd = private2dd(file);
	avail = hfi1_read_cntrs(dd, &names, NULL);
	rval =  simple_read_from_buffer(buf, count, ppos, names, avail);
	rcu_read_unlock();
	return rval;
}

@@ -383,11 +405,9 @@ static ssize_t portnames_read(struct file *file, char __user *buf,
	struct hfi1_devdata *dd;
	ssize_t rval;

	rcu_read_lock();
	dd = private2dd(file);
	avail = hfi1_read_portcntrs(dd->pport, &names, NULL);
	rval = simple_read_from_buffer(buf, count, ppos, names, avail);
	rcu_read_unlock();
	return rval;
}

@@ -400,11 +420,9 @@ static ssize_t portcntrs_debugfs_read(struct file *file, char __user *buf,
	struct hfi1_pportdata *ppd;
	ssize_t rval;

	rcu_read_lock();
	ppd = private2ppd(file);
	avail = hfi1_read_portcntrs(ppd, NULL, &counters);
	rval = simple_read_from_buffer(buf, count, ppos, counters, avail);
	rcu_read_unlock();
	return rval;
}

@@ -434,16 +452,13 @@ static ssize_t asic_flags_read(struct file *file, char __user *buf,
	int used;
	int i;

	rcu_read_lock();
	ppd = private2ppd(file);
	dd = ppd->dd;
	size = PAGE_SIZE;
	used = 0;
	tmp = kmalloc(size, GFP_KERNEL);
	if (!tmp) {
		rcu_read_unlock();
	if (!tmp)
		return -ENOMEM;
	}

	scratch0 = read_csr(dd, ASIC_CFG_SCRATCH);
	used += scnprintf(tmp + used, size - used,
@@ -470,7 +485,6 @@ static ssize_t asic_flags_read(struct file *file, char __user *buf,
	used += scnprintf(tmp + used, size - used, "Write bits to clear\n");

	ret = simple_read_from_buffer(buf, count, ppos, tmp, used);
	rcu_read_unlock();
	kfree(tmp);
	return ret;
}
@@ -486,15 +500,12 @@ static ssize_t asic_flags_write(struct file *file, const char __user *buf,
	u64 scratch0;
	u64 clear;

	rcu_read_lock();
	ppd = private2ppd(file);
	dd = ppd->dd;

	buff = kmalloc(count + 1, GFP_KERNEL);
	if (!buff) {
		ret = -ENOMEM;
		goto do_return;
	}
	if (!buff)
		return -ENOMEM;

	ret = copy_from_user(buff, buf, count);
	if (ret > 0) {
@@ -527,8 +538,6 @@ static ssize_t asic_flags_write(struct file *file, const char __user *buf,

 do_free:
	kfree(buff);
 do_return:
	rcu_read_unlock();
	return ret;
}

@@ -542,18 +551,14 @@ static ssize_t qsfp_debugfs_dump(struct file *file, char __user *buf,
	char *tmp;
	int ret;

	rcu_read_lock();
	ppd = private2ppd(file);
	tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (!tmp) {
		rcu_read_unlock();
	if (!tmp)
		return -ENOMEM;
	}

	ret = qsfp_dump(ppd, tmp, PAGE_SIZE);
	if (ret > 0)
		ret = simple_read_from_buffer(buf, count, ppos, tmp, ret);
	rcu_read_unlock();
	kfree(tmp);
	return ret;
}
@@ -569,7 +574,6 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf,
	int offset;
	int total_written;

	rcu_read_lock();
	ppd = private2ppd(file);

	/* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */
@@ -577,16 +581,12 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf,
	offset = *ppos & 0xffff;

	/* explicitly reject invalid address 0 to catch cp and cat */
	if (i2c_addr == 0) {
		ret = -EINVAL;
		goto _return;
	}
	if (i2c_addr == 0)
		return -EINVAL;

	buff = kmalloc(count, GFP_KERNEL);
	if (!buff) {
		ret = -ENOMEM;
		goto _return;
	}
	if (!buff)
		return -ENOMEM;

	ret = copy_from_user(buff, buf, count);
	if (ret > 0) {
@@ -606,8 +606,6 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf,

 _free:
	kfree(buff);
 _return:
	rcu_read_unlock();
	return ret;
}

@@ -636,7 +634,6 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf,
	int offset;
	int total_read;

	rcu_read_lock();
	ppd = private2ppd(file);

	/* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */
@@ -644,16 +641,12 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf,
	offset = *ppos & 0xffff;

	/* explicitly reject invalid address 0 to catch cp and cat */
	if (i2c_addr == 0) {
		ret = -EINVAL;
		goto _return;
	}
	if (i2c_addr == 0)
		return -EINVAL;

	buff = kmalloc(count, GFP_KERNEL);
	if (!buff) {
		ret = -ENOMEM;
		goto _return;
	}
	if (!buff)
		return -ENOMEM;

	total_read = i2c_read(ppd, target, i2c_addr, offset, buff, count);
	if (total_read < 0) {
@@ -673,8 +666,6 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf,

 _free:
	kfree(buff);
 _return:
	rcu_read_unlock();
	return ret;
}

@@ -701,26 +692,20 @@ static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf,
	int ret;
	int total_written;

	rcu_read_lock();
	if (*ppos + count > QSFP_PAGESIZE * 4) { /* base page + page00-page03 */
		ret = -EINVAL;
		goto _return;
	}
	if (*ppos + count > QSFP_PAGESIZE * 4) /* base page + page00-page03 */
		return -EINVAL;

	ppd = private2ppd(file);

	buff = kmalloc(count, GFP_KERNEL);
	if (!buff) {
		ret = -ENOMEM;
		goto _return;
	}
	if (!buff)
		return -ENOMEM;

	ret = copy_from_user(buff, buf, count);
	if (ret > 0) {
		ret = -EFAULT;
		goto _free;
	}

	total_written = qsfp_write(ppd, target, *ppos, buff, count);
	if (total_written < 0) {
		ret = total_written;
@@ -733,8 +718,6 @@ static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf,

 _free:
	kfree(buff);
 _return:
	rcu_read_unlock();
	return ret;
}

@@ -761,7 +744,6 @@ static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf,
	int ret;
	int total_read;

	rcu_read_lock();
	if (*ppos + count > QSFP_PAGESIZE * 4) { /* base page + page00-page03 */
		ret = -EINVAL;
		goto _return;
@@ -794,7 +776,6 @@ static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf,
 _free:
	kfree(buff);
 _return:
	rcu_read_unlock();
	return ret;
}

@@ -1010,7 +991,6 @@ void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd)
	debugfs_remove_recursive(ibd->hfi1_ibdev_dbg);
out:
	ibd->hfi1_ibdev_dbg = NULL;
	synchronize_rcu();
}

/*
@@ -1035,9 +1015,7 @@ static const char * const hfi1_statnames[] = {
};

static void *_driver_stats_names_seq_start(struct seq_file *s, loff_t *pos)
__acquires(RCU)
{
	rcu_read_lock();
	if (*pos >= ARRAY_SIZE(hfi1_statnames))
		return NULL;
	return pos;
@@ -1055,9 +1033,7 @@ static void *_driver_stats_names_seq_next(
}

static void _driver_stats_names_seq_stop(struct seq_file *s, void *v)
__releases(RCU)
{
	rcu_read_unlock();
}

static int _driver_stats_names_seq_show(struct seq_file *s, void *v)
@@ -1073,9 +1049,7 @@ DEBUGFS_SEQ_FILE_OPEN(driver_stats_names)
DEBUGFS_FILE_OPS(driver_stats_names);

static void *_driver_stats_seq_start(struct seq_file *s, loff_t *pos)
__acquires(RCU)
{
	rcu_read_lock();
	if (*pos >= ARRAY_SIZE(hfi1_statnames))
		return NULL;
	return pos;
@@ -1090,9 +1064,7 @@ static void *_driver_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
}

static void _driver_stats_seq_stop(struct seq_file *s, void *v)
__releases(RCU)
{
	rcu_read_unlock();
}

static u64 hfi1_sps_ints(void)
Loading