Commit 0b115ef1 authored by Harish Chegondi's avatar Harish Chegondi Committed by Doug Ledford

IB/hfi1: Fix the count of user packets submitted to an SDMA engine

Each user SDMA request coming into the driver may contain multiple packets.
Each user packet may use multiple SDMA descriptors to fill the send buffer.
The field seqsubmitted in struct user_sdma_request counts the number of
user packets submitted to an SDMA engine. Sometimes, the intermediate count
may not be updated properly. However, once all the packets' descriptors
are successfully submitted to the SDMA engine, the final count is updated
correctly. But, if only some of the packets are submitted to the engine due
to an error, the intermediate count doesn't reflect the partial number of
packets submitted to the SDMA engine. This can cause a hang later in the
code as the count of packets submitted to the SDMA engine doesn't match the
the count of packets processed by the SDMA engine.
Reviewed-by: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarHarish Chegondi <harish.chegondi@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 0db9dec2
...@@ -2086,6 +2086,11 @@ int sdma_send_txreq(struct sdma_engine *sde, ...@@ -2086,6 +2086,11 @@ int sdma_send_txreq(struct sdma_engine *sde,
* @sde: sdma engine to use * @sde: sdma engine to use
* @wait: wait structure to use when full (may be NULL) * @wait: wait structure to use when full (may be NULL)
* @tx_list: list of sdma_txreqs to submit * @tx_list: list of sdma_txreqs to submit
* @count: pointer to a u32 which, after return will contain the total number of
* sdma_txreqs removed from the tx_list. This will include sdma_txreqs
* whose SDMA descriptors are submitted to the ring and the sdma_txreqs
* which are added to SDMA engine flush list if the SDMA engine state is
* not running.
* *
* The call submits the list into the ring. * The call submits the list into the ring.
* *
...@@ -2100,18 +2105,18 @@ int sdma_send_txreq(struct sdma_engine *sde, ...@@ -2100,18 +2105,18 @@ int sdma_send_txreq(struct sdma_engine *sde,
* side locking. * side locking.
* *
* Return: * Return:
* > 0 - Success (value is number of sdma_txreq's submitted), * 0 - Success,
* -EINVAL - sdma_txreq incomplete, -EBUSY - no space in ring (wait == NULL) * -EINVAL - sdma_txreq incomplete, -EBUSY - no space in ring (wait == NULL)
* -EIOCBQUEUED - tx queued to iowait, -ECOMM bad sdma state * -EIOCBQUEUED - tx queued to iowait, -ECOMM bad sdma state
*/ */
int sdma_send_txlist(struct sdma_engine *sde, struct iowait *wait, int sdma_send_txlist(struct sdma_engine *sde, struct iowait *wait,
struct list_head *tx_list) struct list_head *tx_list, u32 *count_out)
{ {
struct sdma_txreq *tx, *tx_next; struct sdma_txreq *tx, *tx_next;
int ret = 0; int ret = 0;
unsigned long flags; unsigned long flags;
u16 tail = INVALID_TAIL; u16 tail = INVALID_TAIL;
int count = 0; u32 submit_count = 0, flush_count = 0, total_count;
spin_lock_irqsave(&sde->tail_lock, flags); spin_lock_irqsave(&sde->tail_lock, flags);
retry: retry:
...@@ -2127,33 +2132,34 @@ int sdma_send_txlist(struct sdma_engine *sde, struct iowait *wait, ...@@ -2127,33 +2132,34 @@ int sdma_send_txlist(struct sdma_engine *sde, struct iowait *wait,
} }
list_del_init(&tx->list); list_del_init(&tx->list);
tail = submit_tx(sde, tx); tail = submit_tx(sde, tx);
count++; submit_count++;
if (tail != INVALID_TAIL && if (tail != INVALID_TAIL &&
(count & SDMA_TAIL_UPDATE_THRESH) == 0) { (submit_count & SDMA_TAIL_UPDATE_THRESH) == 0) {
sdma_update_tail(sde, tail); sdma_update_tail(sde, tail);
tail = INVALID_TAIL; tail = INVALID_TAIL;
} }
} }
update_tail: update_tail:
total_count = submit_count + flush_count;
if (wait) if (wait)
iowait_sdma_add(wait, count); iowait_sdma_add(wait, total_count);
if (tail != INVALID_TAIL) if (tail != INVALID_TAIL)
sdma_update_tail(sde, tail); sdma_update_tail(sde, tail);
spin_unlock_irqrestore(&sde->tail_lock, flags); spin_unlock_irqrestore(&sde->tail_lock, flags);
return ret == 0 ? count : ret; *count_out = total_count;
return ret;
unlock_noconn: unlock_noconn:
spin_lock(&sde->flushlist_lock); spin_lock(&sde->flushlist_lock);
list_for_each_entry_safe(tx, tx_next, tx_list, list) { list_for_each_entry_safe(tx, tx_next, tx_list, list) {
tx->wait = wait; tx->wait = wait;
list_del_init(&tx->list); list_del_init(&tx->list);
if (wait)
iowait_sdma_inc(wait);
tx->next_descq_idx = 0; tx->next_descq_idx = 0;
#ifdef CONFIG_HFI1_DEBUG_SDMA_ORDER #ifdef CONFIG_HFI1_DEBUG_SDMA_ORDER
tx->sn = sde->tail_sn++; tx->sn = sde->tail_sn++;
trace_hfi1_sdma_in_sn(sde, tx->sn); trace_hfi1_sdma_in_sn(sde, tx->sn);
#endif #endif
list_add_tail(&tx->list, &sde->flushlist); list_add_tail(&tx->list, &sde->flushlist);
flush_count++;
if (wait) { if (wait) {
wait->tx_count++; wait->tx_count++;
wait->count += tx->num_desc; wait->count += tx->num_desc;
......
...@@ -847,7 +847,8 @@ int sdma_send_txreq(struct sdma_engine *sde, ...@@ -847,7 +847,8 @@ int sdma_send_txreq(struct sdma_engine *sde,
struct sdma_txreq *tx); struct sdma_txreq *tx);
int sdma_send_txlist(struct sdma_engine *sde, int sdma_send_txlist(struct sdma_engine *sde,
struct iowait *wait, struct iowait *wait,
struct list_head *tx_list); struct list_head *tx_list,
u32 *count);
int sdma_ahg_alloc(struct sdma_engine *sde); int sdma_ahg_alloc(struct sdma_engine *sde);
void sdma_ahg_free(struct sdma_engine *sde, int ahg_index); void sdma_ahg_free(struct sdma_engine *sde, int ahg_index);
......
...@@ -894,7 +894,7 @@ static inline u32 get_lrh_len(struct hfi1_pkt_header hdr, u32 len) ...@@ -894,7 +894,7 @@ static inline u32 get_lrh_len(struct hfi1_pkt_header hdr, u32 len)
static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts) static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
{ {
int ret = 0; int ret = 0, count;
unsigned npkts = 0; unsigned npkts = 0;
struct user_sdma_txreq *tx = NULL; struct user_sdma_txreq *tx = NULL;
struct hfi1_user_sdma_pkt_q *pq = NULL; struct hfi1_user_sdma_pkt_q *pq = NULL;
...@@ -1090,23 +1090,18 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts) ...@@ -1090,23 +1090,18 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
npkts++; npkts++;
} }
dosend: dosend:
ret = sdma_send_txlist(req->sde, &pq->busy, &req->txps); ret = sdma_send_txlist(req->sde, &pq->busy, &req->txps, &count);
if (list_empty(&req->txps)) { req->seqsubmitted += count;
req->seqsubmitted = req->seqnum; if (req->seqsubmitted == req->info.npkts) {
if (req->seqnum == req->info.npkts) { set_bit(SDMA_REQ_SEND_DONE, &req->flags);
set_bit(SDMA_REQ_SEND_DONE, &req->flags); /*
/* * The txreq has already been submitted to the HW queue
* The txreq has already been submitted to the HW queue * so we can free the AHG entry now. Corruption will not
* so we can free the AHG entry now. Corruption will not * happen due to the sequential manner in which
* happen due to the sequential manner in which * descriptors are processed.
* descriptors are processed. */
*/ if (test_bit(SDMA_REQ_HAVE_AHG, &req->flags))
if (test_bit(SDMA_REQ_HAVE_AHG, &req->flags)) sdma_ahg_free(req->sde, req->ahg_idx);
sdma_ahg_free(req->sde, req->ahg_idx);
}
} else if (ret > 0) {
req->seqsubmitted += ret;
ret = 0;
} }
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment