提交 d060e0f6 编写于 作者: L Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma

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
...@@ -106,7 +106,6 @@ struct mcast_group { ...@@ -106,7 +106,6 @@ struct mcast_group {
atomic_t refcount; atomic_t refcount;
enum mcast_group_state state; enum mcast_group_state state;
struct ib_sa_query *query; struct ib_sa_query *query;
int query_id;
u16 pkey_index; u16 pkey_index;
u8 leave_state; u8 leave_state;
int retries; int retries;
...@@ -340,11 +339,7 @@ static int send_join(struct mcast_group *group, struct mcast_member *member) ...@@ -340,11 +339,7 @@ static int send_join(struct mcast_group *group, struct mcast_member *member)
member->multicast.comp_mask, member->multicast.comp_mask,
3000, GFP_KERNEL, join_handler, group, 3000, GFP_KERNEL, join_handler, group,
&group->query); &group->query);
if (ret >= 0) { return (ret > 0) ? 0 : ret;
group->query_id = ret;
ret = 0;
}
return ret;
} }
static int send_leave(struct mcast_group *group, u8 leave_state) 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) ...@@ -364,11 +359,7 @@ static int send_leave(struct mcast_group *group, u8 leave_state)
IB_SA_MCMEMBER_REC_JOIN_STATE, IB_SA_MCMEMBER_REC_JOIN_STATE,
3000, GFP_KERNEL, leave_handler, 3000, GFP_KERNEL, leave_handler,
group, &group->query); group, &group->query);
if (ret >= 0) { return (ret > 0) ? 0 : ret;
group->query_id = ret;
ret = 0;
}
return ret;
} }
static void join_group(struct mcast_group *group, struct mcast_member *member, static void join_group(struct mcast_group *group, struct mcast_member *member,
......
...@@ -683,7 +683,7 @@ static int build_inv_stag(union t4_wr *wqe, struct ib_send_wr *wr, ...@@ -683,7 +683,7 @@ static int build_inv_stag(union t4_wr *wqe, struct ib_send_wr *wr,
return 0; return 0;
} }
void _free_qp(struct kref *kref) static void _free_qp(struct kref *kref)
{ {
struct c4iw_qp *qhp; struct c4iw_qp *qhp;
......
...@@ -9490,6 +9490,78 @@ static void init_lcb(struct hfi1_devdata *dd) ...@@ -9490,6 +9490,78 @@ static void init_lcb(struct hfi1_devdata *dd)
write_csr(dd, DC_LCB_CFG_TX_FIFOS_RESET, 0x00); 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) int bringup_serdes(struct hfi1_pportdata *ppd)
{ {
struct hfi1_devdata *dd = ppd->dd; struct hfi1_devdata *dd = ppd->dd;
...@@ -9525,14 +9597,8 @@ int bringup_serdes(struct hfi1_pportdata *ppd) ...@@ -9525,14 +9597,8 @@ int bringup_serdes(struct hfi1_pportdata *ppd)
set_qsfp_int_n(ppd, 1); set_qsfp_int_n(ppd, 1);
} }
/* try_start_link(ppd);
* Tune the SerDes to a ballpark setting for return 0;
* optimal signal and bit error rate
* Needs to be done before starting the link
*/
tune_serdes(ppd);
return start_link(ppd);
} }
void hfi1_quiet_serdes(struct hfi1_pportdata *ppd) void hfi1_quiet_serdes(struct hfi1_pportdata *ppd)
...@@ -9549,6 +9615,10 @@ 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->driver_link_ready = 0;
ppd->link_enabled = 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 = ppd->offline_disabled_reason =
HFI1_ODR_MASK(OPA_LINKDOWN_REASON_SMA_DISABLED); HFI1_ODR_MASK(OPA_LINKDOWN_REASON_SMA_DISABLED);
set_link_down_reason(ppd, OPA_LINKDOWN_REASON_SMA_DISABLED, 0, set_link_down_reason(ppd, OPA_LINKDOWN_REASON_SMA_DISABLED, 0,
...@@ -12865,7 +12935,7 @@ static int set_up_interrupts(struct hfi1_devdata *dd) ...@@ -12865,7 +12935,7 @@ static int set_up_interrupts(struct hfi1_devdata *dd)
*/ */
static int set_up_context_variables(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 total_contexts;
int ret; int ret;
unsigned ngroups; unsigned ngroups;
...@@ -12894,9 +12964,9 @@ static int set_up_context_variables(struct hfi1_devdata *dd) ...@@ -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)) { if (num_kernel_contexts > (dd->chip_send_contexts - num_vls - 1)) {
dd_dev_err(dd, 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)(dd->chip_send_contexts - num_vls - 1),
(int)num_kernel_contexts); num_kernel_contexts);
num_kernel_contexts = dd->chip_send_contexts - num_vls - 1; num_kernel_contexts = dd->chip_send_contexts - num_vls - 1;
} }
/* /*
......
...@@ -706,6 +706,7 @@ void handle_link_up(struct work_struct *work); ...@@ -706,6 +706,7 @@ void handle_link_up(struct work_struct *work);
void handle_link_down(struct work_struct *work); void handle_link_down(struct work_struct *work);
void handle_link_downgrade(struct work_struct *work); void handle_link_downgrade(struct work_struct *work);
void handle_link_bounce(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 handle_sma_message(struct work_struct *work);
void reset_qsfp(struct hfi1_pportdata *ppd); void reset_qsfp(struct hfi1_pportdata *ppd);
void qsfp_event(struct work_struct *work); void qsfp_event(struct work_struct *work);
......
...@@ -59,6 +59,40 @@ ...@@ -59,6 +59,40 @@
static struct dentry *hfi1_dbg_root; 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 private2dd(file) (file_inode(file)->i_private)
#define private2ppd(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) \ ...@@ -87,8 +121,8 @@ static int _##name##_open(struct inode *inode, struct file *s) \
static const struct file_operations _##name##_file_ops = { \ static const struct file_operations _##name##_file_ops = { \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.open = _##name##_open, \ .open = _##name##_open, \
.read = seq_read, \ .read = hfi1_seq_read, \
.llseek = seq_lseek, \ .llseek = hfi1_seq_lseek, \
.release = seq_release \ .release = seq_release \
} }
...@@ -105,11 +139,9 @@ do { \ ...@@ -105,11 +139,9 @@ do { \
DEBUGFS_FILE_CREATE(#name, parent, data, &_##name##_file_ops, S_IRUGO) DEBUGFS_FILE_CREATE(#name, parent, data, &_##name##_file_ops, S_IRUGO)
static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos) static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos)
__acquires(RCU)
{ {
struct hfi1_opcode_stats_perctx *opstats; struct hfi1_opcode_stats_perctx *opstats;
rcu_read_lock();
if (*pos >= ARRAY_SIZE(opstats->stats)) if (*pos >= ARRAY_SIZE(opstats->stats))
return NULL; return NULL;
return pos; return pos;
...@@ -126,9 +158,7 @@ static void *_opcode_stats_seq_next(struct seq_file *s, void *v, loff_t *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) 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) static int _opcode_stats_seq_show(struct seq_file *s, void *v)
...@@ -285,12 +315,10 @@ DEBUGFS_SEQ_FILE_OPEN(qp_stats) ...@@ -285,12 +315,10 @@ DEBUGFS_SEQ_FILE_OPEN(qp_stats)
DEBUGFS_FILE_OPS(qp_stats); DEBUGFS_FILE_OPS(qp_stats);
static void *_sdes_seq_start(struct seq_file *s, loff_t *pos) static void *_sdes_seq_start(struct seq_file *s, loff_t *pos)
__acquires(RCU)
{ {
struct hfi1_ibdev *ibd; struct hfi1_ibdev *ibd;
struct hfi1_devdata *dd; struct hfi1_devdata *dd;
rcu_read_lock();
ibd = (struct hfi1_ibdev *)s->private; ibd = (struct hfi1_ibdev *)s->private;
dd = dd_from_dev(ibd); dd = dd_from_dev(ibd);
if (!dd->per_sdma || *pos >= dd->num_sdma) 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) ...@@ -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) 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) 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, ...@@ -339,11 +365,9 @@ static ssize_t dev_counters_read(struct file *file, char __user *buf,
struct hfi1_devdata *dd; struct hfi1_devdata *dd;
ssize_t rval; ssize_t rval;
rcu_read_lock();
dd = private2dd(file); dd = private2dd(file);
avail = hfi1_read_cntrs(dd, NULL, &counters); avail = hfi1_read_cntrs(dd, NULL, &counters);
rval = simple_read_from_buffer(buf, count, ppos, counters, avail); rval = simple_read_from_buffer(buf, count, ppos, counters, avail);
rcu_read_unlock();
return rval; return rval;
} }
...@@ -356,11 +380,9 @@ static ssize_t dev_names_read(struct file *file, char __user *buf, ...@@ -356,11 +380,9 @@ static ssize_t dev_names_read(struct file *file, char __user *buf,
struct hfi1_devdata *dd; struct hfi1_devdata *dd;
ssize_t rval; ssize_t rval;
rcu_read_lock();
dd = private2dd(file); dd = private2dd(file);
avail = hfi1_read_cntrs(dd, &names, NULL); avail = hfi1_read_cntrs(dd, &names, NULL);
rval = simple_read_from_buffer(buf, count, ppos, names, avail); rval = simple_read_from_buffer(buf, count, ppos, names, avail);
rcu_read_unlock();
return rval; return rval;
} }
...@@ -383,11 +405,9 @@ static ssize_t portnames_read(struct file *file, char __user *buf, ...@@ -383,11 +405,9 @@ static ssize_t portnames_read(struct file *file, char __user *buf,
struct hfi1_devdata *dd; struct hfi1_devdata *dd;
ssize_t rval; ssize_t rval;
rcu_read_lock();
dd = private2dd(file); dd = private2dd(file);
avail = hfi1_read_portcntrs(dd->pport, &names, NULL); avail = hfi1_read_portcntrs(dd->pport, &names, NULL);
rval = simple_read_from_buffer(buf, count, ppos, names, avail); rval = simple_read_from_buffer(buf, count, ppos, names, avail);
rcu_read_unlock();
return rval; return rval;
} }
...@@ -400,11 +420,9 @@ static ssize_t portcntrs_debugfs_read(struct file *file, char __user *buf, ...@@ -400,11 +420,9 @@ static ssize_t portcntrs_debugfs_read(struct file *file, char __user *buf,
struct hfi1_pportdata *ppd; struct hfi1_pportdata *ppd;
ssize_t rval; ssize_t rval;
rcu_read_lock();
ppd = private2ppd(file); ppd = private2ppd(file);
avail = hfi1_read_portcntrs(ppd, NULL, &counters); avail = hfi1_read_portcntrs(ppd, NULL, &counters);
rval = simple_read_from_buffer(buf, count, ppos, counters, avail); rval = simple_read_from_buffer(buf, count, ppos, counters, avail);
rcu_read_unlock();
return rval; return rval;
} }
...@@ -434,16 +452,13 @@ static ssize_t asic_flags_read(struct file *file, char __user *buf, ...@@ -434,16 +452,13 @@ static ssize_t asic_flags_read(struct file *file, char __user *buf,
int used; int used;
int i; int i;
rcu_read_lock();
ppd = private2ppd(file); ppd = private2ppd(file);
dd = ppd->dd; dd = ppd->dd;
size = PAGE_SIZE; size = PAGE_SIZE;
used = 0; used = 0;
tmp = kmalloc(size, GFP_KERNEL); tmp = kmalloc(size, GFP_KERNEL);
if (!tmp) { if (!tmp)
rcu_read_unlock();
return -ENOMEM; return -ENOMEM;
}
scratch0 = read_csr(dd, ASIC_CFG_SCRATCH); scratch0 = read_csr(dd, ASIC_CFG_SCRATCH);
used += scnprintf(tmp + used, size - used, used += scnprintf(tmp + used, size - used,
...@@ -470,7 +485,6 @@ static ssize_t asic_flags_read(struct file *file, char __user *buf, ...@@ -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"); used += scnprintf(tmp + used, size - used, "Write bits to clear\n");
ret = simple_read_from_buffer(buf, count, ppos, tmp, used); ret = simple_read_from_buffer(buf, count, ppos, tmp, used);
rcu_read_unlock();
kfree(tmp); kfree(tmp);
return ret; return ret;
} }
...@@ -486,15 +500,12 @@ static ssize_t asic_flags_write(struct file *file, const char __user *buf, ...@@ -486,15 +500,12 @@ static ssize_t asic_flags_write(struct file *file, const char __user *buf,
u64 scratch0; u64 scratch0;
u64 clear; u64 clear;
rcu_read_lock();
ppd = private2ppd(file); ppd = private2ppd(file);
dd = ppd->dd; dd = ppd->dd;
buff = kmalloc(count + 1, GFP_KERNEL); buff = kmalloc(count + 1, GFP_KERNEL);
if (!buff) { if (!buff)
ret = -ENOMEM; return -ENOMEM;
goto do_return;
}
ret = copy_from_user(buff, buf, count); ret = copy_from_user(buff, buf, count);
if (ret > 0) { if (ret > 0) {
...@@ -527,8 +538,6 @@ static ssize_t asic_flags_write(struct file *file, const char __user *buf, ...@@ -527,8 +538,6 @@ static ssize_t asic_flags_write(struct file *file, const char __user *buf,
do_free: do_free:
kfree(buff); kfree(buff);
do_return:
rcu_read_unlock();
return ret; return ret;
} }
...@@ -542,18 +551,14 @@ static ssize_t qsfp_debugfs_dump(struct file *file, char __user *buf, ...@@ -542,18 +551,14 @@ static ssize_t qsfp_debugfs_dump(struct file *file, char __user *buf,
char *tmp; char *tmp;
int ret; int ret;
rcu_read_lock();
ppd = private2ppd(file); ppd = private2ppd(file);
tmp = kmalloc(PAGE_SIZE, GFP_KERNEL); tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!tmp) { if (!tmp)
rcu_read_unlock();
return -ENOMEM; return -ENOMEM;
}
ret = qsfp_dump(ppd, tmp, PAGE_SIZE); ret = qsfp_dump(ppd, tmp, PAGE_SIZE);
if (ret > 0) if (ret > 0)
ret = simple_read_from_buffer(buf, count, ppos, tmp, ret); ret = simple_read_from_buffer(buf, count, ppos, tmp, ret);
rcu_read_unlock();
kfree(tmp); kfree(tmp);
return ret; return ret;
} }
...@@ -569,7 +574,6 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf, ...@@ -569,7 +574,6 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf,
int offset; int offset;
int total_written; int total_written;
rcu_read_lock();
ppd = private2ppd(file); ppd = private2ppd(file);
/* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */ /* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */
...@@ -577,16 +581,12 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf, ...@@ -577,16 +581,12 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf,
offset = *ppos & 0xffff; offset = *ppos & 0xffff;
/* explicitly reject invalid address 0 to catch cp and cat */ /* explicitly reject invalid address 0 to catch cp and cat */
if (i2c_addr == 0) { if (i2c_addr == 0)
ret = -EINVAL; return -EINVAL;
goto _return;
}
buff = kmalloc(count, GFP_KERNEL); buff = kmalloc(count, GFP_KERNEL);
if (!buff) { if (!buff)
ret = -ENOMEM; return -ENOMEM;
goto _return;
}
ret = copy_from_user(buff, buf, count); ret = copy_from_user(buff, buf, count);
if (ret > 0) { if (ret > 0) {
...@@ -606,8 +606,6 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf, ...@@ -606,8 +606,6 @@ static ssize_t __i2c_debugfs_write(struct file *file, const char __user *buf,
_free: _free:
kfree(buff); kfree(buff);
_return:
rcu_read_unlock();
return ret; return ret;
} }
...@@ -636,7 +634,6 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf, ...@@ -636,7 +634,6 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf,
int offset; int offset;
int total_read; int total_read;
rcu_read_lock();
ppd = private2ppd(file); ppd = private2ppd(file);
/* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */ /* byte offset format: [offsetSize][i2cAddr][offsetHigh][offsetLow] */
...@@ -644,16 +641,12 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf, ...@@ -644,16 +641,12 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf,
offset = *ppos & 0xffff; offset = *ppos & 0xffff;
/* explicitly reject invalid address 0 to catch cp and cat */ /* explicitly reject invalid address 0 to catch cp and cat */
if (i2c_addr == 0) { if (i2c_addr == 0)
ret = -EINVAL; return -EINVAL;
goto _return;
}
buff = kmalloc(count, GFP_KERNEL); buff = kmalloc(count, GFP_KERNEL);
if (!buff) { if (!buff)
ret = -ENOMEM; return -ENOMEM;
goto _return;
}
total_read = i2c_read(ppd, target, i2c_addr, offset, buff, count); total_read = i2c_read(ppd, target, i2c_addr, offset, buff, count);
if (total_read < 0) { if (total_read < 0) {
...@@ -673,8 +666,6 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf, ...@@ -673,8 +666,6 @@ static ssize_t __i2c_debugfs_read(struct file *file, char __user *buf,
_free: _free:
kfree(buff); kfree(buff);
_return:
rcu_read_unlock();
return ret; return ret;
} }
...@@ -701,26 +692,20 @@ static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf, ...@@ -701,26 +692,20 @@ static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf,
int ret; int ret;
int total_written; int total_written;
rcu_read_lock(); if (*ppos + count > QSFP_PAGESIZE * 4) /* base page + page00-page03 */
if (*ppos + count > QSFP_PAGESIZE * 4) { /* base page + page00-page03 */ return -EINVAL;
ret = -EINVAL;
goto _return;
}
ppd = private2ppd(file); ppd = private2ppd(file);
buff = kmalloc(count, GFP_KERNEL); buff = kmalloc(count, GFP_KERNEL);
if (!buff) { if (!buff)
ret = -ENOMEM; return -ENOMEM;
goto _return;
}
ret = copy_from_user(buff, buf, count); ret = copy_from_user(buff, buf, count);
if (ret > 0) { if (ret > 0) {
ret = -EFAULT; ret = -EFAULT;
goto _free; goto _free;
} }
total_written = qsfp_write(ppd, target, *ppos, buff, count); total_written = qsfp_write(ppd, target, *ppos, buff, count);
if (total_written < 0) { if (total_written < 0) {
ret = total_written; ret = total_written;
...@@ -733,8 +718,6 @@ static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf, ...@@ -733,8 +718,6 @@ static ssize_t __qsfp_debugfs_write(struct file *file, const char __user *buf,
_free: _free:
kfree(buff); kfree(buff);
_return:
rcu_read_unlock();
return ret; return ret;
} }
...@@ -761,7 +744,6 @@ static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf, ...@@ -761,7 +744,6 @@ static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf,
int ret; int ret;
int total_read; int total_read;
rcu_read_lock();
if (*ppos + count > QSFP_PAGESIZE * 4) { /* base page + page00-page03 */ if (*ppos + count > QSFP_PAGESIZE * 4) { /* base page + page00-page03 */
ret = -EINVAL; ret = -EINVAL;
goto _return; goto _return;
...@@ -794,7 +776,6 @@ static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf, ...@@ -794,7 +776,6 @@ static ssize_t __qsfp_debugfs_read(struct file *file, char __user *buf,
_free: _free:
kfree(buff); kfree(buff);
_return: _return:
rcu_read_unlock();
return ret; return ret;
} }
...@@ -1010,7 +991,6 @@ void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd) ...@@ -1010,7 +991,6 @@ void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd)
debugfs_remove_recursive(ibd->hfi1_ibdev_dbg); debugfs_remove_recursive(ibd->hfi1_ibdev_dbg);
out: out:
ibd->hfi1_ibdev_dbg = NULL; ibd->hfi1_ibdev_dbg = NULL;
synchronize_rcu();
} }
/* /*
...@@ -1035,9 +1015,7 @@ static const char * const hfi1_statnames[] = { ...@@ -1035,9 +1015,7 @@ static const char * const hfi1_statnames[] = {
}; };
static void *_driver_stats_names_seq_start(struct seq_file *s, loff_t *pos) 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)) if (*pos >= ARRAY_SIZE(hfi1_statnames))
return NULL; return NULL;
return pos; return pos;
...@@ -1055,9 +1033,7 @@ static void *_driver_stats_names_seq_next( ...@@ -1055,9 +1033,7 @@ static void *_driver_stats_names_seq_next(
} }
static void _driver_stats_names_seq_stop(struct seq_file *s, void *v) 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) static int _driver_stats_names_seq_show(struct seq_file *s, void *v)
...@@ -1073,9 +1049,7 @@ DEBUGFS_SEQ_FILE_OPEN(driver_stats_names) ...@@ -1073,9 +1049,7 @@ DEBUGFS_SEQ_FILE_OPEN(driver_stats_names)
DEBUGFS_FILE_OPS(driver_stats_names); DEBUGFS_FILE_OPS(driver_stats_names);
static void *_driver_stats_seq_start(struct seq_file *s, loff_t *pos) static void *_driver_stats_seq_start(struct seq_file *s, loff_t *pos)
__acquires(RCU)
{ {
rcu_read_lock();
if (*pos >= ARRAY_SIZE(hfi1_statnames)) if (*pos >= ARRAY_SIZE(hfi1_statnames))
return NULL; return NULL;
return pos; return pos;
...@@ -1090,9 +1064,7 @@ static void *_driver_stats_seq_next(struct seq_file *s, void *v, loff_t *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) static void _driver_stats_seq_stop(struct seq_file *s, void *v)
__releases(RCU)
{ {
rcu_read_unlock();
} }
static u64 hfi1_sps_ints(void) static u64 hfi1_sps_ints(void)
......
...@@ -605,6 +605,7 @@ struct hfi1_pportdata { ...@@ -605,6 +605,7 @@ struct hfi1_pportdata {
struct work_struct freeze_work; struct work_struct freeze_work;
struct work_struct link_downgrade_work; struct work_struct link_downgrade_work;
struct work_struct link_bounce_work; struct work_struct link_bounce_work;
struct delayed_work start_link_work;
/* host link state variables */ /* host link state variables */
struct mutex hls_lock; struct mutex hls_lock;
u32 host_link_state; u32 host_link_state;
...@@ -659,6 +660,7 @@ struct hfi1_pportdata { ...@@ -659,6 +660,7 @@ struct hfi1_pportdata {
u8 linkinit_reason; u8 linkinit_reason;
u8 local_tx_rate; /* rate given to 8051 firmware */ u8 local_tx_rate; /* rate given to 8051 firmware */
u8 last_pstate; /* info only */ u8 last_pstate; /* info only */
u8 qsfp_retry_count;
/* placeholders for IB MAD packet settings */ /* placeholders for IB MAD packet settings */
u8 overrun_threshold; u8 overrun_threshold;
...@@ -1804,7 +1806,7 @@ extern unsigned int hfi1_max_mtu; ...@@ -1804,7 +1806,7 @@ extern unsigned int hfi1_max_mtu;
extern unsigned int hfi1_cu; extern unsigned int hfi1_cu;
extern unsigned int user_credit_return_threshold; extern unsigned int user_credit_return_threshold;
extern int num_user_contexts; extern int num_user_contexts;
extern unsigned n_krcvqs; extern unsigned long n_krcvqs;
extern uint krcvqs[]; extern uint krcvqs[];
extern int krcvqsset; extern int krcvqsset;
extern uint kdeth_qp; extern uint kdeth_qp;
......
...@@ -94,7 +94,7 @@ module_param_array(krcvqs, uint, &krcvqsset, S_IRUGO); ...@@ -94,7 +94,7 @@ module_param_array(krcvqs, uint, &krcvqsset, S_IRUGO);
MODULE_PARM_DESC(krcvqs, "Array of the number of non-control kernel receive queues by VL"); MODULE_PARM_DESC(krcvqs, "Array of the number of non-control kernel receive queues by VL");
/* computed based on above array */ /* computed based on above array */
unsigned n_krcvqs; unsigned long n_krcvqs;
static unsigned hfi1_rcvarr_split = 25; static unsigned hfi1_rcvarr_split = 25;
module_param_named(rcvarr_split, hfi1_rcvarr_split, uint, S_IRUGO); module_param_named(rcvarr_split, hfi1_rcvarr_split, uint, S_IRUGO);
...@@ -500,6 +500,7 @@ void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd, ...@@ -500,6 +500,7 @@ void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd,
INIT_WORK(&ppd->link_downgrade_work, handle_link_downgrade); INIT_WORK(&ppd->link_downgrade_work, handle_link_downgrade);
INIT_WORK(&ppd->sma_message_work, handle_sma_message); INIT_WORK(&ppd->sma_message_work, handle_sma_message);
INIT_WORK(&ppd->link_bounce_work, handle_link_bounce); INIT_WORK(&ppd->link_bounce_work, handle_link_bounce);
INIT_DELAYED_WORK(&ppd->start_link_work, handle_start_link);
INIT_WORK(&ppd->linkstate_active_work, receive_interrupt_work); INIT_WORK(&ppd->linkstate_active_work, receive_interrupt_work);
INIT_WORK(&ppd->qsfp_info.qsfp_work, qsfp_event); INIT_WORK(&ppd->qsfp_info.qsfp_work, qsfp_event);
......
...@@ -2604,7 +2604,7 @@ static int pma_get_opa_datacounters(struct opa_pma_mad *pmp, ...@@ -2604,7 +2604,7 @@ static int pma_get_opa_datacounters(struct opa_pma_mad *pmp,
u8 lq, num_vls; u8 lq, num_vls;
u8 res_lli, res_ler; u8 res_lli, res_ler;
u64 port_mask; u64 port_mask;
unsigned long port_num; u8 port_num;
unsigned long vl; unsigned long vl;
u32 vl_select_mask; u32 vl_select_mask;
int vfi; int vfi;
...@@ -2638,9 +2638,9 @@ static int pma_get_opa_datacounters(struct opa_pma_mad *pmp, ...@@ -2638,9 +2638,9 @@ static int pma_get_opa_datacounters(struct opa_pma_mad *pmp,
*/ */
port_mask = be64_to_cpu(req->port_select_mask[3]); port_mask = be64_to_cpu(req->port_select_mask[3]);
port_num = find_first_bit((unsigned long *)&port_mask, port_num = find_first_bit((unsigned long *)&port_mask,
sizeof(port_mask)); sizeof(port_mask) * 8);
if ((u8)port_num != port) { if (port_num != port) {
pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
return reply((struct ib_mad_hdr *)pmp); return reply((struct ib_mad_hdr *)pmp);
} }
...@@ -2842,7 +2842,7 @@ static int pma_get_opa_porterrors(struct opa_pma_mad *pmp, ...@@ -2842,7 +2842,7 @@ static int pma_get_opa_porterrors(struct opa_pma_mad *pmp,
*/ */
port_mask = be64_to_cpu(req->port_select_mask[3]); port_mask = be64_to_cpu(req->port_select_mask[3]);
port_num = find_first_bit((unsigned long *)&port_mask, port_num = find_first_bit((unsigned long *)&port_mask,
sizeof(port_mask)); sizeof(port_mask) * 8);
if (port_num != port) { if (port_num != port) {
pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
...@@ -3015,7 +3015,7 @@ static int pma_get_opa_errorinfo(struct opa_pma_mad *pmp, ...@@ -3015,7 +3015,7 @@ static int pma_get_opa_errorinfo(struct opa_pma_mad *pmp,
*/ */
port_mask = be64_to_cpu(req->port_select_mask[3]); port_mask = be64_to_cpu(req->port_select_mask[3]);
port_num = find_first_bit((unsigned long *)&port_mask, port_num = find_first_bit((unsigned long *)&port_mask,
sizeof(port_mask)); sizeof(port_mask) * 8);
if (port_num != port) { if (port_num != port) {
pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
...@@ -3252,7 +3252,7 @@ static int pma_set_opa_errorinfo(struct opa_pma_mad *pmp, ...@@ -3252,7 +3252,7 @@ static int pma_set_opa_errorinfo(struct opa_pma_mad *pmp,
*/ */
port_mask = be64_to_cpu(req->port_select_mask[3]); port_mask = be64_to_cpu(req->port_select_mask[3]);
port_num = find_first_bit((unsigned long *)&port_mask, port_num = find_first_bit((unsigned long *)&port_mask,
sizeof(port_mask)); sizeof(port_mask) * 8);
if (port_num != port) { if (port_num != port) {
pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD; pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
......
...@@ -771,6 +771,9 @@ void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes) ...@@ -771,6 +771,9 @@ void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes)
read_extra_bytes(pbuf, from, to_fill); read_extra_bytes(pbuf, from, to_fill);
from += to_fill; from += to_fill;
nbytes -= to_fill; nbytes -= to_fill;
/* may not be enough valid bytes left to align */
if (extra > nbytes)
extra = nbytes;
/* ...now write carry */ /* ...now write carry */
dest = pbuf->start + (pbuf->qw_written * sizeof(u64)); dest = pbuf->start + (pbuf->qw_written * sizeof(u64));
...@@ -798,6 +801,15 @@ void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes) ...@@ -798,6 +801,15 @@ void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes)
read_low_bytes(pbuf, from, extra); read_low_bytes(pbuf, from, extra);
from += extra; from += extra;
nbytes -= extra; nbytes -= extra;
/*
* If no bytes are left, return early - we are done.
* NOTE: This short-circuit is *required* because
* "extra" may have been reduced in size and "from"
* is not aligned, as required when leaving this
* if block.
*/
if (nbytes == 0)
return;
} }
/* at this point, from is QW aligned */ /* at this point, from is QW aligned */
......
...@@ -114,6 +114,8 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12 ...@@ -114,6 +114,8 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12
#define KDETH_HCRC_LOWER_SHIFT 24 #define KDETH_HCRC_LOWER_SHIFT 24
#define KDETH_HCRC_LOWER_MASK 0xff #define KDETH_HCRC_LOWER_MASK 0xff
#define AHG_KDETH_INTR_SHIFT 12
#define PBC2LRH(x) ((((x) & 0xfff) << 2) - 4) #define PBC2LRH(x) ((((x) & 0xfff) << 2) - 4)
#define LRH2PBC(x) ((((x) >> 2) + 1) & 0xfff) #define LRH2PBC(x) ((((x) >> 2) + 1) & 0xfff)
...@@ -1480,7 +1482,8 @@ static int set_txreq_header_ahg(struct user_sdma_request *req, ...@@ -1480,7 +1482,8 @@ static int set_txreq_header_ahg(struct user_sdma_request *req,
/* Clear KDETH.SH on last packet */ /* Clear KDETH.SH on last packet */
if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT)) { if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT)) {
val |= cpu_to_le16(KDETH_GET(hdr->kdeth.ver_tid_offset, val |= cpu_to_le16(KDETH_GET(hdr->kdeth.ver_tid_offset,
INTR) >> 16); INTR) <<
AHG_KDETH_INTR_SHIFT);
val &= cpu_to_le16(~(1U << 13)); val &= cpu_to_le16(~(1U << 13));
AHG_HEADER_SET(req->ahg, diff, 7, 16, 14, val); AHG_HEADER_SET(req->ahg, diff, 7, 16, 14, val);
} else { } else {
......
...@@ -265,6 +265,7 @@ void i40iw_next_iw_state(struct i40iw_qp *iwqp, ...@@ -265,6 +265,7 @@ void i40iw_next_iw_state(struct i40iw_qp *iwqp,
info.dont_send_fin = false; info.dont_send_fin = false;
if (iwqp->sc_qp.term_flags && (state == I40IW_QP_STATE_ERROR)) if (iwqp->sc_qp.term_flags && (state == I40IW_QP_STATE_ERROR))
info.reset_tcp_conn = true; info.reset_tcp_conn = true;
iwqp->hw_iwarp_state = state;
i40iw_hw_modify_qp(iwqp->iwdev, iwqp, &info, 0); i40iw_hw_modify_qp(iwqp->iwdev, iwqp, &info, 0);
} }
......
...@@ -100,7 +100,7 @@ static struct notifier_block i40iw_net_notifier = { ...@@ -100,7 +100,7 @@ static struct notifier_block i40iw_net_notifier = {
.notifier_call = i40iw_net_event .notifier_call = i40iw_net_event
}; };
static int i40iw_notifiers_registered; static atomic_t i40iw_notifiers_registered;
/** /**
* i40iw_find_i40e_handler - find a handler given a client info * i40iw_find_i40e_handler - find a handler given a client info
...@@ -1342,12 +1342,11 @@ static enum i40iw_status_code i40iw_initialize_dev(struct i40iw_device *iwdev, ...@@ -1342,12 +1342,11 @@ static enum i40iw_status_code i40iw_initialize_dev(struct i40iw_device *iwdev,
*/ */
static void i40iw_register_notifiers(void) static void i40iw_register_notifiers(void)
{ {
if (!i40iw_notifiers_registered) { if (atomic_inc_return(&i40iw_notifiers_registered) == 1) {
register_inetaddr_notifier(&i40iw_inetaddr_notifier); register_inetaddr_notifier(&i40iw_inetaddr_notifier);
register_inet6addr_notifier(&i40iw_inetaddr6_notifier); register_inet6addr_notifier(&i40iw_inetaddr6_notifier);
register_netevent_notifier(&i40iw_net_notifier); register_netevent_notifier(&i40iw_net_notifier);
} }
i40iw_notifiers_registered++;
} }
/** /**
...@@ -1429,8 +1428,7 @@ static void i40iw_deinit_device(struct i40iw_device *iwdev, bool reset, bool del ...@@ -1429,8 +1428,7 @@ static void i40iw_deinit_device(struct i40iw_device *iwdev, bool reset, bool del
i40iw_del_macip_entry(iwdev, (u8)iwdev->mac_ip_table_idx); i40iw_del_macip_entry(iwdev, (u8)iwdev->mac_ip_table_idx);
/* fallthrough */ /* fallthrough */
case INET_NOTIFIER: case INET_NOTIFIER:
if (i40iw_notifiers_registered > 0) { if (!atomic_dec_return(&i40iw_notifiers_registered)) {
i40iw_notifiers_registered--;
unregister_netevent_notifier(&i40iw_net_notifier); unregister_netevent_notifier(&i40iw_net_notifier);
unregister_inetaddr_notifier(&i40iw_inetaddr_notifier); unregister_inetaddr_notifier(&i40iw_inetaddr_notifier);
unregister_inet6addr_notifier(&i40iw_inetaddr6_notifier); unregister_inet6addr_notifier(&i40iw_inetaddr6_notifier);
......
...@@ -687,12 +687,6 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq, ...@@ -687,12 +687,6 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
is_error = (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == is_error = (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
MLX4_CQE_OPCODE_ERROR; MLX4_CQE_OPCODE_ERROR;
if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == MLX4_OPCODE_NOP &&
is_send)) {
pr_warn("Completion for NOP opcode detected!\n");
return -EAGAIN;
}
/* Resize CQ in progress */ /* Resize CQ in progress */
if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == MLX4_CQE_OPCODE_RESIZE)) { if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == MLX4_CQE_OPCODE_RESIZE)) {
if (cq->resize_buf) { if (cq->resize_buf) {
...@@ -718,12 +712,6 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq, ...@@ -718,12 +712,6 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
*/ */
mqp = __mlx4_qp_lookup(to_mdev(cq->ibcq.device)->dev, mqp = __mlx4_qp_lookup(to_mdev(cq->ibcq.device)->dev,
be32_to_cpu(cqe->vlan_my_qpn)); be32_to_cpu(cqe->vlan_my_qpn));
if (unlikely(!mqp)) {
pr_warn("CQ %06x with entry for unknown QPN %06x\n",
cq->mcq.cqn, be32_to_cpu(cqe->vlan_my_qpn) & MLX4_CQE_QPN_MASK);
return -EAGAIN;
}
*cur_qp = to_mibqp(mqp); *cur_qp = to_mibqp(mqp);
} }
...@@ -736,11 +724,6 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq, ...@@ -736,11 +724,6 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
/* SRQ is also in the radix tree */ /* SRQ is also in the radix tree */
msrq = mlx4_srq_lookup(to_mdev(cq->ibcq.device)->dev, msrq = mlx4_srq_lookup(to_mdev(cq->ibcq.device)->dev,
srq_num); srq_num);
if (unlikely(!msrq)) {
pr_warn("CQ %06x with entry for unknown SRQN %06x\n",
cq->mcq.cqn, srq_num);
return -EAGAIN;
}
} }
if (is_send) { if (is_send) {
...@@ -891,7 +874,6 @@ int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) ...@@ -891,7 +874,6 @@ int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
struct mlx4_ib_qp *cur_qp = NULL; struct mlx4_ib_qp *cur_qp = NULL;
unsigned long flags; unsigned long flags;
int npolled; int npolled;
int err = 0;
struct mlx4_ib_dev *mdev = to_mdev(cq->ibcq.device); struct mlx4_ib_dev *mdev = to_mdev(cq->ibcq.device);
spin_lock_irqsave(&cq->lock, flags); spin_lock_irqsave(&cq->lock, flags);
...@@ -901,8 +883,7 @@ int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) ...@@ -901,8 +883,7 @@ int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
} }
for (npolled = 0; npolled < num_entries; ++npolled) { for (npolled = 0; npolled < num_entries; ++npolled) {
err = mlx4_ib_poll_one(cq, &cur_qp, wc + npolled); if (mlx4_ib_poll_one(cq, &cur_qp, wc + npolled))
if (err)
break; break;
} }
...@@ -911,10 +892,7 @@ int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) ...@@ -911,10 +892,7 @@ int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
out: out:
spin_unlock_irqrestore(&cq->lock, flags); spin_unlock_irqrestore(&cq->lock, flags);
if (err == 0 || err == -EAGAIN) return npolled;
return npolled;
else
return err;
} }
int mlx4_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) int mlx4_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
......
...@@ -553,12 +553,6 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq, ...@@ -553,12 +553,6 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq,
* from the table. * from the table.
*/ */
mqp = __mlx5_qp_lookup(dev->mdev, qpn); mqp = __mlx5_qp_lookup(dev->mdev, qpn);
if (unlikely(!mqp)) {
mlx5_ib_warn(dev, "CQE@CQ %06x for unknown QPN %6x\n",
cq->mcq.cqn, qpn);
return -EINVAL;
}
*cur_qp = to_mibqp(mqp); *cur_qp = to_mibqp(mqp);
} }
...@@ -619,13 +613,6 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq, ...@@ -619,13 +613,6 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq,
read_lock(&dev->mdev->priv.mkey_table.lock); read_lock(&dev->mdev->priv.mkey_table.lock);
mmkey = __mlx5_mr_lookup(dev->mdev, mmkey = __mlx5_mr_lookup(dev->mdev,
mlx5_base_mkey(be32_to_cpu(sig_err_cqe->mkey))); mlx5_base_mkey(be32_to_cpu(sig_err_cqe->mkey)));
if (unlikely(!mmkey)) {
read_unlock(&dev->mdev->priv.mkey_table.lock);
mlx5_ib_warn(dev, "CQE@CQ %06x for unknown MR %6x\n",
cq->mcq.cqn, be32_to_cpu(sig_err_cqe->mkey));
return -EINVAL;
}
mr = to_mibmr(mmkey); mr = to_mibmr(mmkey);
get_sig_err_item(sig_err_cqe, &mr->sig->err_item); get_sig_err_item(sig_err_cqe, &mr->sig->err_item);
mr->sig->sig_err_exists = true; mr->sig->sig_err_exists = true;
...@@ -676,7 +663,6 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) ...@@ -676,7 +663,6 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
unsigned long flags; unsigned long flags;
int soft_polled = 0; int soft_polled = 0;
int npolled; int npolled;
int err = 0;
spin_lock_irqsave(&cq->lock, flags); spin_lock_irqsave(&cq->lock, flags);
if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
...@@ -688,8 +674,7 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) ...@@ -688,8 +674,7 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
soft_polled = poll_soft_wc(cq, num_entries, wc); soft_polled = poll_soft_wc(cq, num_entries, wc);
for (npolled = 0; npolled < num_entries - soft_polled; npolled++) { for (npolled = 0; npolled < num_entries - soft_polled; npolled++) {
err = mlx5_poll_one(cq, &cur_qp, wc + soft_polled + npolled); if (mlx5_poll_one(cq, &cur_qp, wc + soft_polled + npolled))
if (err)
break; break;
} }
...@@ -698,10 +683,7 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) ...@@ -698,10 +683,7 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
out: out:
spin_unlock_irqrestore(&cq->lock, flags); spin_unlock_irqrestore(&cq->lock, flags);
if (err == 0 || err == -EAGAIN) return soft_polled + npolled;
return soft_polled + npolled;
else
return err;
} }
int mlx5_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) int mlx5_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
......
...@@ -1849,6 +1849,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp, ...@@ -1849,6 +1849,7 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
int domain) int domain)
{ {
struct mlx5_ib_dev *dev = to_mdev(qp->device); struct mlx5_ib_dev *dev = to_mdev(qp->device);
struct mlx5_ib_qp *mqp = to_mqp(qp);
struct mlx5_ib_flow_handler *handler = NULL; struct mlx5_ib_flow_handler *handler = NULL;
struct mlx5_flow_destination *dst = NULL; struct mlx5_flow_destination *dst = NULL;
struct mlx5_ib_flow_prio *ft_prio; struct mlx5_ib_flow_prio *ft_prio;
...@@ -1875,7 +1876,10 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp, ...@@ -1875,7 +1876,10 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
} }
dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR; dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dst->tir_num = to_mqp(qp)->raw_packet_qp.rq.tirn; if (mqp->flags & MLX5_IB_QP_RSS)
dst->tir_num = mqp->rss_qp.tirn;
else
dst->tir_num = mqp->raw_packet_qp.rq.tirn;
if (flow_attr->type == IB_FLOW_ATTR_NORMAL) { if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) { if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) {
......
...@@ -71,7 +71,7 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift, ...@@ -71,7 +71,7 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift,
addr = addr >> page_shift; addr = addr >> page_shift;
tmp = (unsigned long)addr; tmp = (unsigned long)addr;
m = find_first_bit(&tmp, sizeof(tmp)); m = find_first_bit(&tmp, BITS_PER_LONG);
skip = 1 << m; skip = 1 << m;
mask = skip - 1; mask = skip - 1;
i = 0; i = 0;
...@@ -81,7 +81,7 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift, ...@@ -81,7 +81,7 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift,
for (k = 0; k < len; k++) { for (k = 0; k < len; k++) {
if (!(i & mask)) { if (!(i & mask)) {
tmp = (unsigned long)pfn; tmp = (unsigned long)pfn;
m = min_t(unsigned long, m, find_first_bit(&tmp, sizeof(tmp))); m = min_t(unsigned long, m, find_first_bit(&tmp, BITS_PER_LONG));
skip = 1 << m; skip = 1 << m;
mask = skip - 1; mask = skip - 1;
base = pfn; base = pfn;
...@@ -89,7 +89,7 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift, ...@@ -89,7 +89,7 @@ void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift,
} else { } else {
if (base + p != pfn) { if (base + p != pfn) {
tmp = (unsigned long)p; tmp = (unsigned long)p;
m = find_first_bit(&tmp, sizeof(tmp)); m = find_first_bit(&tmp, BITS_PER_LONG);
skip = 1 << m; skip = 1 << m;
mask = skip - 1; mask = skip - 1;
base = pfn; base = pfn;
......
...@@ -402,6 +402,7 @@ enum mlx5_ib_qp_flags { ...@@ -402,6 +402,7 @@ enum mlx5_ib_qp_flags {
/* QP uses 1 as its source QP number */ /* QP uses 1 as its source QP number */
MLX5_IB_QP_SQPN_QP1 = 1 << 6, MLX5_IB_QP_SQPN_QP1 = 1 << 6,
MLX5_IB_QP_CAP_SCATTER_FCS = 1 << 7, MLX5_IB_QP_CAP_SCATTER_FCS = 1 << 7,
MLX5_IB_QP_RSS = 1 << 8,
}; };
struct mlx5_umr_wr { struct mlx5_umr_wr {
......
...@@ -1449,6 +1449,7 @@ static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp, ...@@ -1449,6 +1449,7 @@ static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
kvfree(in); kvfree(in);
/* qpn is reserved for that QP */ /* qpn is reserved for that QP */
qp->trans_qp.base.mqp.qpn = 0; qp->trans_qp.base.mqp.qpn = 0;
qp->flags |= MLX5_IB_QP_RSS;
return 0; return 0;
err: err:
...@@ -3658,12 +3659,8 @@ static int begin_wqe(struct mlx5_ib_qp *qp, void **seg, ...@@ -3658,12 +3659,8 @@ static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
struct ib_send_wr *wr, unsigned *idx, struct ib_send_wr *wr, unsigned *idx,
int *size, int nreq) int *size, int nreq)
{ {
int err = 0; if (unlikely(mlx5_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)))
return -ENOMEM;
if (unlikely(mlx5_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq))) {
err = -ENOMEM;
return err;
}
*idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1); *idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1);
*seg = mlx5_get_send_wqe(qp, *idx); *seg = mlx5_get_send_wqe(qp, *idx);
...@@ -3679,7 +3676,7 @@ static int begin_wqe(struct mlx5_ib_qp *qp, void **seg, ...@@ -3679,7 +3676,7 @@ static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
*seg += sizeof(**ctrl); *seg += sizeof(**ctrl);
*size = sizeof(**ctrl) / 16; *size = sizeof(**ctrl) / 16;
return err; return 0;
} }
static void finish_wqe(struct mlx5_ib_qp *qp, static void finish_wqe(struct mlx5_ib_qp *qp,
...@@ -3758,7 +3755,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, ...@@ -3758,7 +3755,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
num_sge = wr->num_sge; num_sge = wr->num_sge;
if (unlikely(num_sge > qp->sq.max_gs)) { if (unlikely(num_sge > qp->sq.max_gs)) {
mlx5_ib_warn(dev, "\n"); mlx5_ib_warn(dev, "\n");
err = -ENOMEM; err = -EINVAL;
*bad_wr = wr; *bad_wr = wr;
goto out; goto out;
} }
......
...@@ -478,6 +478,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, ...@@ -478,6 +478,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
struct ipoib_ah *address, u32 qpn); struct ipoib_ah *address, u32 qpn);
void ipoib_reap_ah(struct work_struct *work); void ipoib_reap_ah(struct work_struct *work);
struct ipoib_path *__path_find(struct net_device *dev, void *gid);
void ipoib_mark_paths_invalid(struct net_device *dev); void ipoib_mark_paths_invalid(struct net_device *dev);
void ipoib_flush_paths(struct net_device *dev); void ipoib_flush_paths(struct net_device *dev);
int ipoib_check_sm_sendonly_fullmember_support(struct ipoib_dev_priv *priv); int ipoib_check_sm_sendonly_fullmember_support(struct ipoib_dev_priv *priv);
......
...@@ -1318,6 +1318,8 @@ void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx) ...@@ -1318,6 +1318,8 @@ void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx)
} }
} }
#define QPN_AND_OPTIONS_OFFSET 4
static void ipoib_cm_tx_start(struct work_struct *work) static void ipoib_cm_tx_start(struct work_struct *work)
{ {
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
...@@ -1326,6 +1328,7 @@ static void ipoib_cm_tx_start(struct work_struct *work) ...@@ -1326,6 +1328,7 @@ static void ipoib_cm_tx_start(struct work_struct *work)
struct ipoib_neigh *neigh; struct ipoib_neigh *neigh;
struct ipoib_cm_tx *p; struct ipoib_cm_tx *p;
unsigned long flags; unsigned long flags;
struct ipoib_path *path;
int ret; int ret;
struct ib_sa_path_rec pathrec; struct ib_sa_path_rec pathrec;
...@@ -1338,7 +1341,19 @@ static void ipoib_cm_tx_start(struct work_struct *work) ...@@ -1338,7 +1341,19 @@ static void ipoib_cm_tx_start(struct work_struct *work)
p = list_entry(priv->cm.start_list.next, typeof(*p), list); p = list_entry(priv->cm.start_list.next, typeof(*p), list);
list_del_init(&p->list); list_del_init(&p->list);
neigh = p->neigh; neigh = p->neigh;
qpn = IPOIB_QPN(neigh->daddr); qpn = IPOIB_QPN(neigh->daddr);
/*
* As long as the search is with these 2 locks,
* path existence indicates its validity.
*/
path = __path_find(dev, neigh->daddr + QPN_AND_OPTIONS_OFFSET);
if (!path) {
pr_info("%s ignore not valid path %pI6\n",
__func__,
neigh->daddr + QPN_AND_OPTIONS_OFFSET);
goto free_neigh;
}
memcpy(&pathrec, &p->path->pathrec, sizeof pathrec); memcpy(&pathrec, &p->path->pathrec, sizeof pathrec);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
...@@ -1350,6 +1365,7 @@ static void ipoib_cm_tx_start(struct work_struct *work) ...@@ -1350,6 +1365,7 @@ static void ipoib_cm_tx_start(struct work_struct *work)
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (ret) { if (ret) {
free_neigh:
neigh = p->neigh; neigh = p->neigh;
if (neigh) { if (neigh) {
neigh->cm = NULL; neigh->cm = NULL;
......
...@@ -485,7 +485,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf) ...@@ -485,7 +485,7 @@ int ipoib_set_mode(struct net_device *dev, const char *buf)
return -EINVAL; return -EINVAL;
} }
static struct ipoib_path *__path_find(struct net_device *dev, void *gid) struct ipoib_path *__path_find(struct net_device *dev, void *gid)
{ {
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = netdev_priv(dev);
struct rb_node *n = priv->path_tree.rb_node; struct rb_node *n = priv->path_tree.rb_node;
......
...@@ -403,6 +403,7 @@ isert_init_conn(struct isert_conn *isert_conn) ...@@ -403,6 +403,7 @@ isert_init_conn(struct isert_conn *isert_conn)
INIT_LIST_HEAD(&isert_conn->node); INIT_LIST_HEAD(&isert_conn->node);
init_completion(&isert_conn->login_comp); init_completion(&isert_conn->login_comp);
init_completion(&isert_conn->login_req_comp); init_completion(&isert_conn->login_req_comp);
init_waitqueue_head(&isert_conn->rem_wait);
kref_init(&isert_conn->kref); kref_init(&isert_conn->kref);
mutex_init(&isert_conn->mutex); mutex_init(&isert_conn->mutex);
INIT_WORK(&isert_conn->release_work, isert_release_work); INIT_WORK(&isert_conn->release_work, isert_release_work);
...@@ -578,7 +579,8 @@ isert_connect_release(struct isert_conn *isert_conn) ...@@ -578,7 +579,8 @@ isert_connect_release(struct isert_conn *isert_conn)
BUG_ON(!device); BUG_ON(!device);
isert_free_rx_descriptors(isert_conn); isert_free_rx_descriptors(isert_conn);
if (isert_conn->cm_id) if (isert_conn->cm_id &&
!isert_conn->dev_removed)
rdma_destroy_id(isert_conn->cm_id); rdma_destroy_id(isert_conn->cm_id);
if (isert_conn->qp) { if (isert_conn->qp) {
...@@ -593,7 +595,10 @@ isert_connect_release(struct isert_conn *isert_conn) ...@@ -593,7 +595,10 @@ isert_connect_release(struct isert_conn *isert_conn)
isert_device_put(device); isert_device_put(device);
kfree(isert_conn); if (isert_conn->dev_removed)
wake_up_interruptible(&isert_conn->rem_wait);
else
kfree(isert_conn);
} }
static void static void
...@@ -753,6 +758,7 @@ static int ...@@ -753,6 +758,7 @@ static int
isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
{ {
struct isert_np *isert_np = cma_id->context; struct isert_np *isert_np = cma_id->context;
struct isert_conn *isert_conn;
int ret = 0; int ret = 0;
isert_info("%s (%d): status %d id %p np %p\n", isert_info("%s (%d): status %d id %p np %p\n",
...@@ -773,10 +779,21 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) ...@@ -773,10 +779,21 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
break; break;
case RDMA_CM_EVENT_ADDR_CHANGE: /* FALLTHRU */ case RDMA_CM_EVENT_ADDR_CHANGE: /* FALLTHRU */
case RDMA_CM_EVENT_DISCONNECTED: /* FALLTHRU */ case RDMA_CM_EVENT_DISCONNECTED: /* FALLTHRU */
case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */
case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */ case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */
ret = isert_disconnected_handler(cma_id, event->event); ret = isert_disconnected_handler(cma_id, event->event);
break; break;
case RDMA_CM_EVENT_DEVICE_REMOVAL:
isert_conn = cma_id->qp->qp_context;
isert_conn->dev_removed = true;
isert_disconnected_handler(cma_id, event->event);
wait_event_interruptible(isert_conn->rem_wait,
isert_conn->state == ISER_CONN_DOWN);
kfree(isert_conn);
/*
* return non-zero from the callback to destroy
* the rdma cm id
*/
return 1;
case RDMA_CM_EVENT_REJECTED: /* FALLTHRU */ case RDMA_CM_EVENT_REJECTED: /* FALLTHRU */
case RDMA_CM_EVENT_UNREACHABLE: /* FALLTHRU */ case RDMA_CM_EVENT_UNREACHABLE: /* FALLTHRU */
case RDMA_CM_EVENT_CONNECT_ERROR: case RDMA_CM_EVENT_CONNECT_ERROR:
......
...@@ -158,6 +158,8 @@ struct isert_conn { ...@@ -158,6 +158,8 @@ struct isert_conn {
struct work_struct release_work; struct work_struct release_work;
bool logout_posted; bool logout_posted;
bool snd_w_inv; bool snd_w_inv;
wait_queue_head_t rem_wait;
bool dev_removed;
}; };
#define ISERT_MAX_CQ 64 #define ISERT_MAX_CQ 64
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册