IB/ipath: simplify IB timer usage
Signed-off-by: Bryan O'Sullivan <bos@pathscale.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
committed by
Roland Dreier
parent
76f0dd141b
commit
9b2017f1e1
@@ -449,7 +449,6 @@ static void ipath_ib_timer(void *arg)
|
|||||||
{
|
{
|
||||||
struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
|
struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
|
||||||
struct ipath_qp *resend = NULL;
|
struct ipath_qp *resend = NULL;
|
||||||
struct ipath_qp *rnr = NULL;
|
|
||||||
struct list_head *last;
|
struct list_head *last;
|
||||||
struct ipath_qp *qp;
|
struct ipath_qp *qp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@@ -465,32 +464,18 @@ static void ipath_ib_timer(void *arg)
|
|||||||
last = &dev->pending[dev->pending_index];
|
last = &dev->pending[dev->pending_index];
|
||||||
while (!list_empty(last)) {
|
while (!list_empty(last)) {
|
||||||
qp = list_entry(last->next, struct ipath_qp, timerwait);
|
qp = list_entry(last->next, struct ipath_qp, timerwait);
|
||||||
if (last->next == LIST_POISON1 ||
|
list_del(&qp->timerwait);
|
||||||
last->next != &qp->timerwait ||
|
qp->timer_next = resend;
|
||||||
qp->timerwait.prev != last) {
|
resend = qp;
|
||||||
INIT_LIST_HEAD(last);
|
atomic_inc(&qp->refcount);
|
||||||
} else {
|
|
||||||
list_del(&qp->timerwait);
|
|
||||||
qp->timerwait.prev = (struct list_head *) resend;
|
|
||||||
resend = qp;
|
|
||||||
atomic_inc(&qp->refcount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
last = &dev->rnrwait;
|
last = &dev->rnrwait;
|
||||||
if (!list_empty(last)) {
|
if (!list_empty(last)) {
|
||||||
qp = list_entry(last->next, struct ipath_qp, timerwait);
|
qp = list_entry(last->next, struct ipath_qp, timerwait);
|
||||||
if (--qp->s_rnr_timeout == 0) {
|
if (--qp->s_rnr_timeout == 0) {
|
||||||
do {
|
do {
|
||||||
if (last->next == LIST_POISON1 ||
|
|
||||||
last->next != &qp->timerwait ||
|
|
||||||
qp->timerwait.prev != last) {
|
|
||||||
INIT_LIST_HEAD(last);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
list_del(&qp->timerwait);
|
list_del(&qp->timerwait);
|
||||||
qp->timerwait.prev =
|
tasklet_hi_schedule(&qp->s_task);
|
||||||
(struct list_head *) rnr;
|
|
||||||
rnr = qp;
|
|
||||||
if (list_empty(last))
|
if (list_empty(last))
|
||||||
break;
|
break;
|
||||||
qp = list_entry(last->next, struct ipath_qp,
|
qp = list_entry(last->next, struct ipath_qp,
|
||||||
@@ -530,8 +515,7 @@ static void ipath_ib_timer(void *arg)
|
|||||||
spin_unlock_irqrestore(&dev->pending_lock, flags);
|
spin_unlock_irqrestore(&dev->pending_lock, flags);
|
||||||
|
|
||||||
/* XXX What if timer fires again while this is running? */
|
/* XXX What if timer fires again while this is running? */
|
||||||
for (qp = resend; qp != NULL;
|
for (qp = resend; qp != NULL; qp = qp->timer_next) {
|
||||||
qp = (struct ipath_qp *) qp->timerwait.prev) {
|
|
||||||
struct ib_wc wc;
|
struct ib_wc wc;
|
||||||
|
|
||||||
spin_lock_irqsave(&qp->s_lock, flags);
|
spin_lock_irqsave(&qp->s_lock, flags);
|
||||||
@@ -545,9 +529,6 @@ static void ipath_ib_timer(void *arg)
|
|||||||
if (atomic_dec_and_test(&qp->refcount))
|
if (atomic_dec_and_test(&qp->refcount))
|
||||||
wake_up(&qp->wait);
|
wake_up(&qp->wait);
|
||||||
}
|
}
|
||||||
for (qp = rnr; qp != NULL;
|
|
||||||
qp = (struct ipath_qp *) qp->timerwait.prev)
|
|
||||||
tasklet_hi_schedule(&qp->s_task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -556,9 +537,9 @@ static void ipath_ib_timer(void *arg)
|
|||||||
*
|
*
|
||||||
* This is called from ipath_intr() at interrupt level when a PIO buffer is
|
* This is called from ipath_intr() at interrupt level when a PIO buffer is
|
||||||
* available after ipath_verbs_send() returned an error that no buffers were
|
* available after ipath_verbs_send() returned an error that no buffers were
|
||||||
* available. Return 0 if we consumed all the PIO buffers and we still have
|
* available. Return 1 if we consumed all the PIO buffers and we still have
|
||||||
* QPs waiting for buffers (for now, just do a tasklet_hi_schedule and
|
* QPs waiting for buffers (for now, just do a tasklet_hi_schedule and
|
||||||
* return one).
|
* return zero).
|
||||||
*/
|
*/
|
||||||
static int ipath_ib_piobufavail(void *arg)
|
static int ipath_ib_piobufavail(void *arg)
|
||||||
{
|
{
|
||||||
@@ -579,7 +560,7 @@ static int ipath_ib_piobufavail(void *arg)
|
|||||||
spin_unlock_irqrestore(&dev->pending_lock, flags);
|
spin_unlock_irqrestore(&dev->pending_lock, flags);
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipath_query_device(struct ib_device *ibdev,
|
static int ipath_query_device(struct ib_device *ibdev,
|
||||||
@@ -1159,7 +1140,7 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
|
|||||||
|
|
||||||
len = sprintf(buf,
|
len = sprintf(buf,
|
||||||
"RC resends %d\n"
|
"RC resends %d\n"
|
||||||
"RC QACKs %d\n"
|
"RC no QACK %d\n"
|
||||||
"RC ACKs %d\n"
|
"RC ACKs %d\n"
|
||||||
"RC SEQ NAKs %d\n"
|
"RC SEQ NAKs %d\n"
|
||||||
"RC RDMA seq %d\n"
|
"RC RDMA seq %d\n"
|
||||||
|
@@ -282,7 +282,8 @@ struct ipath_srq {
|
|||||||
*/
|
*/
|
||||||
struct ipath_qp {
|
struct ipath_qp {
|
||||||
struct ib_qp ibqp;
|
struct ib_qp ibqp;
|
||||||
struct ipath_qp *next; /* link list for QPN hash table */
|
struct ipath_qp *next; /* link list for QPN hash table */
|
||||||
|
struct ipath_qp *timer_next; /* link list for ipath_ib_timer() */
|
||||||
struct list_head piowait; /* link for wait PIO buf */
|
struct list_head piowait; /* link for wait PIO buf */
|
||||||
struct list_head timerwait; /* link for waiting for timeouts */
|
struct list_head timerwait; /* link for waiting for timeouts */
|
||||||
struct ib_ah_attr remote_ah_attr;
|
struct ib_ah_attr remote_ah_attr;
|
||||||
|
Reference in New Issue
Block a user