Skip to content

Commit

Permalink
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/rdma/rdma

Pull rdma fixes from Doug Ledford:
 "This is probably our last -rc pull request. We don't have anything
  else outstanding at the moment anyway, and with the summer months on
  us and people taking trips, I expect the next weeks leading up to the
  merge window to be pretty calm and sedate.

  This has two simple, no brainer fixes for the EFA driver.

  Then it has ten not quite so simple fixes for the hfi1 driver. The
  problem with them is that they aren't simply one liner typo fixes.
  They're still fixes, but they're more complex issues like livelock
  under heavy load where the answer was to change work queue usage and
  spinlock usage to resolve the problem, or issues with orphaned
  requests during certain types of failures like link down which
  required some more complex work to fix too. They all look like
  legitimate fixes to me, they just aren't small like I wish they were.

  Summary:

   - 2 minor EFA fixes

   - 10 hfi1 fixes related to scaling issues"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/efa: Handle mmap insertions overflow
  RDMA/efa: Fix success return value in case of error
  IB/hfi1: Handle port down properly in pio
  IB/hfi1: Handle wakeup of orphaned QPs for pio
  IB/hfi1: Wakeup QPs orphaned on wait list after flush
  IB/hfi1: Use aborts to trigger RC throttling
  IB/hfi1: Create inline to get extended headers
  IB/hfi1: Silence txreq allocation warnings
  IB/hfi1: Avoid hardlockup with flushlist_lock
  IB/hfi1: Correct tid qp rcd to match verbs context
  IB/hfi1: Close PSM sdma_progress sleep window
  IB/hfi1: Validate fault injection opcode user input
  • Loading branch information
Linus Torvalds committed Jun 21, 2019
2 parents c036f7d + 7a5834e commit 121bddf
Show file tree
Hide file tree
Showing 17 changed files with 174 additions and 62 deletions.
24 changes: 18 additions & 6 deletions drivers/infiniband/hw/efa/efa_com_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,11 @@ int efa_com_destroy_qp(struct efa_com_dev *edev,
sizeof(qp_cmd),
(struct efa_admin_acq_entry *)&cmd_completion,
sizeof(cmd_completion));
if (err)
if (err) {
ibdev_err(edev->efa_dev, "Failed to destroy qp-%u [%d]\n",
qp_cmd.qp_handle, err);
return err;
}

return 0;
}
Expand Down Expand Up @@ -199,9 +201,11 @@ int efa_com_destroy_cq(struct efa_com_dev *edev,
(struct efa_admin_acq_entry *)&destroy_resp,
sizeof(destroy_resp));

if (err)
if (err) {
ibdev_err(edev->efa_dev, "Failed to destroy CQ-%u [%d]\n",
params->cq_idx, err);
return err;
}

return 0;
}
Expand Down Expand Up @@ -273,10 +277,12 @@ int efa_com_dereg_mr(struct efa_com_dev *edev,
sizeof(mr_cmd),
(struct efa_admin_acq_entry *)&cmd_completion,
sizeof(cmd_completion));
if (err)
if (err) {
ibdev_err(edev->efa_dev,
"Failed to de-register mr(lkey-%u) [%d]\n",
mr_cmd.l_key, err);
return err;
}

return 0;
}
Expand Down Expand Up @@ -327,9 +333,11 @@ int efa_com_destroy_ah(struct efa_com_dev *edev,
sizeof(ah_cmd),
(struct efa_admin_acq_entry *)&cmd_completion,
sizeof(cmd_completion));
if (err)
if (err) {
ibdev_err(edev->efa_dev, "Failed to destroy ah-%d pd-%d [%d]\n",
ah_cmd.ah, ah_cmd.pd, err);
return err;
}

return 0;
}
Expand Down Expand Up @@ -387,10 +395,12 @@ static int efa_com_get_feature_ex(struct efa_com_dev *edev,
get_resp,
sizeof(*get_resp));

if (err)
if (err) {
ibdev_err(edev->efa_dev,
"Failed to submit get_feature command %d [%d]\n",
feature_id, err);
return err;
}

return 0;
}
Expand Down Expand Up @@ -534,10 +544,12 @@ static int efa_com_set_feature_ex(struct efa_com_dev *edev,
(struct efa_admin_acq_entry *)set_resp,
sizeof(*set_resp));

if (err)
if (err) {
ibdev_err(edev->efa_dev,
"Failed to submit set_feature command %d error: %d\n",
feature_id, err);
return err;
}

return 0;
}
Expand Down
21 changes: 16 additions & 5 deletions drivers/infiniband/hw/efa/efa_verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ static u64 mmap_entry_insert(struct efa_dev *dev, struct efa_ucontext *ucontext,
void *obj, u64 address, u64 length, u8 mmap_flag)
{
struct efa_mmap_entry *entry;
u32 next_mmap_page;
int err;

entry = kmalloc(sizeof(*entry), GFP_KERNEL);
Expand All @@ -216,22 +217,32 @@ static u64 mmap_entry_insert(struct efa_dev *dev, struct efa_ucontext *ucontext,
entry->mmap_flag = mmap_flag;

xa_lock(&ucontext->mmap_xa);
if (check_add_overflow(ucontext->mmap_xa_page,
(u32)(length >> PAGE_SHIFT),
&next_mmap_page))
goto err_unlock;

entry->mmap_page = ucontext->mmap_xa_page;
ucontext->mmap_xa_page += DIV_ROUND_UP(length, PAGE_SIZE);
ucontext->mmap_xa_page = next_mmap_page;
err = __xa_insert(&ucontext->mmap_xa, entry->mmap_page, entry,
GFP_KERNEL);
if (err)
goto err_unlock;

xa_unlock(&ucontext->mmap_xa);
if (err){
kfree(entry);
return EFA_MMAP_INVALID;
}

ibdev_dbg(
&dev->ibdev,
"mmap: obj[0x%p] addr[%#llx], len[%#llx], key[%#llx] inserted\n",
entry->obj, entry->address, entry->length, get_mmap_key(entry));

return get_mmap_key(entry);

err_unlock:
xa_unlock(&ucontext->mmap_xa);
kfree(entry);
return EFA_MMAP_INVALID;

}

int efa_query_device(struct ib_device *ibdev,
Expand Down
13 changes: 13 additions & 0 deletions drivers/infiniband/hw/hfi1/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -14031,6 +14031,19 @@ static void init_kdeth_qp(struct hfi1_devdata *dd)
RCV_BTH_QP_KDETH_QP_SHIFT);
}

/**
* hfi1_get_qp_map
* @dd: device data
* @idx: index to read
*/
u8 hfi1_get_qp_map(struct hfi1_devdata *dd, u8 idx)
{
u64 reg = read_csr(dd, RCV_QP_MAP_TABLE + (idx / 8) * 8);

reg >>= (idx % 8) * 8;
return reg;
}

/**
* init_qpmap_table
* @dd - device data
Expand Down
1 change: 1 addition & 0 deletions drivers/infiniband/hw/hfi1/chip.h
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,7 @@ void clear_all_interrupts(struct hfi1_devdata *dd);
void remap_intr(struct hfi1_devdata *dd, int isrc, int msix_intr);
void remap_sdma_interrupts(struct hfi1_devdata *dd, int engine, int msix_intr);
void reset_interrupts(struct hfi1_devdata *dd);
u8 hfi1_get_qp_map(struct hfi1_devdata *dd, u8 idx);

/*
* Interrupt source table.
Expand Down
5 changes: 5 additions & 0 deletions drivers/infiniband/hw/hfi1/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
char *dash;
unsigned long range_start, range_end, i;
bool remove = false;
unsigned long bound = 1U << BITS_PER_BYTE;

end = strchr(ptr, ',');
if (end)
Expand All @@ -178,6 +179,10 @@ static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
BITS_PER_BYTE);
break;
}
/* Check the inputs */
if (range_start >= bound || range_end >= bound)
break;

for (i = range_start; i <= range_end; i++) {
if (remove)
clear_bit(i, fault->opcodes);
Expand Down
31 changes: 31 additions & 0 deletions drivers/infiniband/hw/hfi1/hfi.h
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,37 @@ static inline void hfi1_16B_set_qpn(struct opa_16b_mgmt *mgmt,
mgmt->src_qpn = cpu_to_be32(src_qp & OPA_16B_MGMT_QPN_MASK);
}

/**
* hfi1_get_rc_ohdr - get extended header
* @opah - the opaheader
*/
static inline struct ib_other_headers *
hfi1_get_rc_ohdr(struct hfi1_opa_header *opah)
{
struct ib_other_headers *ohdr;
struct ib_header *hdr = NULL;
struct hfi1_16b_header *hdr_16b = NULL;

/* Find out where the BTH is */
if (opah->hdr_type == HFI1_PKT_TYPE_9B) {
hdr = &opah->ibh;
if (ib_get_lnh(hdr) == HFI1_LRH_BTH)
ohdr = &hdr->u.oth;
else
ohdr = &hdr->u.l.oth;
} else {
u8 l4;

hdr_16b = &opah->opah;
l4 = hfi1_16B_get_l4(hdr_16b);
if (l4 == OPA_16B_L4_IB_LOCAL)
ohdr = &hdr_16b->u.oth;
else
ohdr = &hdr_16b->u.l.oth;
}
return ohdr;
}

struct rvt_sge_state;

/*
Expand Down
21 changes: 19 additions & 2 deletions drivers/infiniband/hw/hfi1/pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,22 @@ void sc_disable(struct send_context *sc)
}
}
spin_unlock(&sc->release_lock);

write_seqlock(&sc->waitlock);
while (!list_empty(&sc->piowait)) {
struct iowait *wait;
struct rvt_qp *qp;
struct hfi1_qp_priv *priv;

wait = list_first_entry(&sc->piowait, struct iowait, list);
qp = iowait_to_qp(wait);
priv = qp->priv;
list_del_init(&priv->s_iowait.list);
priv->s_iowait.lock = NULL;
hfi1_qp_wakeup(qp, RVT_S_WAIT_PIO | HFI1_S_WAIT_PIO_DRAIN);
}
write_sequnlock(&sc->waitlock);

spin_unlock_irq(&sc->alloc_lock);
}

Expand Down Expand Up @@ -1427,7 +1443,8 @@ void sc_stop(struct send_context *sc, int flag)
* @cb: optional callback to call when the buffer is finished sending
* @arg: argument for cb
*
* Return a pointer to a PIO buffer if successful, NULL if not enough room.
* Return a pointer to a PIO buffer, NULL if not enough room, -ECOMM
* when link is down.
*/
struct pio_buf *sc_buffer_alloc(struct send_context *sc, u32 dw_len,
pio_release_cb cb, void *arg)
Expand All @@ -1443,7 +1460,7 @@ struct pio_buf *sc_buffer_alloc(struct send_context *sc, u32 dw_len,
spin_lock_irqsave(&sc->alloc_lock, flags);
if (!(sc->flags & SCF_ENABLED)) {
spin_unlock_irqrestore(&sc->alloc_lock, flags);
goto done;
return ERR_PTR(-ECOMM);
}

retry:
Expand Down
53 changes: 32 additions & 21 deletions drivers/infiniband/hw/hfi1/rc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,7 @@ void hfi1_send_rc_ack(struct hfi1_packet *packet, bool is_fecn)
pbc = create_pbc(ppd, pbc_flags, qp->srate_mbps,
sc_to_vlt(ppd->dd, sc5), plen);
pbuf = sc_buffer_alloc(rcd->sc, plen, NULL, NULL);
if (!pbuf) {
if (IS_ERR_OR_NULL(pbuf)) {
/*
* We have no room to send at the moment. Pass
* responsibility for sending the ACK to the send engine
Expand Down Expand Up @@ -1701,6 +1701,36 @@ static void reset_sending_psn(struct rvt_qp *qp, u32 psn)
}
}

/**
* hfi1_rc_verbs_aborted - handle abort status
* @qp: the QP
* @opah: the opa header
*
* This code modifies both ACK bit in BTH[2]
* and the s_flags to go into send one mode.
*
* This serves to throttle the send engine to only
* send a single packet in the likely case the
* a link has gone down.
*/
void hfi1_rc_verbs_aborted(struct rvt_qp *qp, struct hfi1_opa_header *opah)
{
struct ib_other_headers *ohdr = hfi1_get_rc_ohdr(opah);
u8 opcode = ib_bth_get_opcode(ohdr);
u32 psn;

/* ignore responses */
if ((opcode >= OP(RDMA_READ_RESPONSE_FIRST) &&
opcode <= OP(ATOMIC_ACKNOWLEDGE)) ||
opcode == TID_OP(READ_RESP) ||
opcode == TID_OP(WRITE_RESP))
return;

psn = ib_bth_get_psn(ohdr) | IB_BTH_REQ_ACK;
ohdr->bth[2] = cpu_to_be32(psn);
qp->s_flags |= RVT_S_SEND_ONE;
}

/*
* This should be called with the QP s_lock held and interrupts disabled.
*/
Expand All @@ -1709,8 +1739,6 @@ void hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_opa_header *opah)
struct ib_other_headers *ohdr;
struct hfi1_qp_priv *priv = qp->priv;
struct rvt_swqe *wqe;
struct ib_header *hdr = NULL;
struct hfi1_16b_header *hdr_16b = NULL;
u32 opcode, head, tail;
u32 psn;
struct tid_rdma_request *req;
Expand All @@ -1719,24 +1747,7 @@ void hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_opa_header *opah)
if (!(ib_rvt_state_ops[qp->state] & RVT_SEND_OR_FLUSH_OR_RECV_OK))
return;

/* Find out where the BTH is */
if (priv->hdr_type == HFI1_PKT_TYPE_9B) {
hdr = &opah->ibh;
if (ib_get_lnh(hdr) == HFI1_LRH_BTH)
ohdr = &hdr->u.oth;
else
ohdr = &hdr->u.l.oth;
} else {
u8 l4;

hdr_16b = &opah->opah;
l4 = hfi1_16B_get_l4(hdr_16b);
if (l4 == OPA_16B_L4_IB_LOCAL)
ohdr = &hdr_16b->u.oth;
else
ohdr = &hdr_16b->u.l.oth;
}

ohdr = hfi1_get_rc_ohdr(opah);
opcode = ib_bth_get_opcode(ohdr);
if ((opcode >= OP(RDMA_READ_RESPONSE_FIRST) &&
opcode <= OP(ATOMIC_ACKNOWLEDGE)) ||
Expand Down
26 changes: 20 additions & 6 deletions drivers/infiniband/hw/hfi1/sdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,19 +405,33 @@ static void sdma_flush(struct sdma_engine *sde)
struct sdma_txreq *txp, *txp_next;
LIST_HEAD(flushlist);
unsigned long flags;
uint seq;

/* flush from head to tail */
sdma_flush_descq(sde);
spin_lock_irqsave(&sde->flushlist_lock, flags);
/* copy flush list */
list_for_each_entry_safe(txp, txp_next, &sde->flushlist, list) {
list_del_init(&txp->list);
list_add_tail(&txp->list, &flushlist);
}
list_splice_init(&sde->flushlist, &flushlist);
spin_unlock_irqrestore(&sde->flushlist_lock, flags);
/* flush from flush list */
list_for_each_entry_safe(txp, txp_next, &flushlist, list)
complete_tx(sde, txp, SDMA_TXREQ_S_ABORTED);
/* wakeup QPs orphaned on the dmawait list */
do {
struct iowait *w, *nw;

seq = read_seqbegin(&sde->waitlock);
if (!list_empty(&sde->dmawait)) {
write_seqlock(&sde->waitlock);
list_for_each_entry_safe(w, nw, &sde->dmawait, list) {
if (w->wakeup) {
w->wakeup(w, SDMA_AVAIL_REASON);
list_del_init(&w->list);
}
}
write_sequnlock(&sde->waitlock);
}
} while (read_seqretry(&sde->waitlock, seq));
}

/*
Expand Down Expand Up @@ -2413,7 +2427,7 @@ int sdma_send_txreq(struct sdma_engine *sde,
list_add_tail(&tx->list, &sde->flushlist);
spin_unlock(&sde->flushlist_lock);
iowait_inc_wait_count(wait, tx->num_desc);
schedule_work(&sde->flush_worker);
queue_work_on(sde->cpu, system_highpri_wq, &sde->flush_worker);
ret = -ECOMM;
goto unlock;
nodesc:
Expand Down Expand Up @@ -2511,7 +2525,7 @@ int sdma_send_txlist(struct sdma_engine *sde, struct iowait_work *wait,
iowait_inc_wait_count(wait, tx->num_desc);
}
spin_unlock(&sde->flushlist_lock);
schedule_work(&sde->flush_worker);
queue_work_on(sde->cpu, system_highpri_wq, &sde->flush_worker);
ret = -ECOMM;
goto update_tail;
nodesc:
Expand Down
Loading

0 comments on commit 121bddf

Please sign in to comment.