summaryrefslogtreecommitdiffstats
path: root/drivers/block/aoe/aoecmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/aoe/aoecmd.c')
-rw-r--r--drivers/block/aoe/aoecmd.c75
1 files changed, 53 insertions, 22 deletions
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index a99220ad626..d9bc6ff56f4 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -352,6 +352,7 @@ aoecmd_ata_rw(struct aoedev *d)
fhash(f);
t->nout++;
f->waited = 0;
+ f->waited_total = 0;
f->buf = buf;
f->bcnt = bcnt;
f->lba = buf->sector;
@@ -556,46 +557,69 @@ ejectif(struct aoetgt *t, struct aoeif *ifp)
dev_put(nd);
}
+static struct frame *
+reassign_frame(struct list_head *pos)
+{
+ struct frame *f;
+ struct frame *nf;
+ struct sk_buff *skb;
+
+ f = list_entry(pos, struct frame, head);
+ nf = newframe(f->t->d);
+ if (!nf)
+ return NULL;
+
+ list_del(pos);
+
+ skb = nf->skb;
+ nf->skb = f->skb;
+ nf->buf = f->buf;
+ nf->bcnt = f->bcnt;
+ nf->lba = f->lba;
+ nf->bv = f->bv;
+ nf->bv_off = f->bv_off;
+ nf->waited = 0;
+ nf->waited_total = f->waited_total;
+ nf->sent = f->sent;
+ f->skb = skb;
+ aoe_freetframe(f);
+ f->t->nout--;
+ nf->t->nout++;
+
+ return nf;
+}
+
static int
sthtith(struct aoedev *d)
{
struct frame *f, *nf;
struct list_head *nx, *pos, *head;
- struct sk_buff *skb;
struct aoetgt *ht = d->htgt;
int i;
+ /* look through the active and pending retransmit frames */
for (i = 0; i < NFACTIVE; i++) {
head = &d->factive[i];
list_for_each_safe(pos, nx, head) {
f = list_entry(pos, struct frame, head);
if (f->t != ht)
continue;
-
- nf = newframe(d);
+ nf = reassign_frame(pos);
if (!nf)
return 0;
-
- /* remove frame from active list */
- list_del(pos);
-
- /* reassign all pertinent bits to new outbound frame */
- skb = nf->skb;
- nf->skb = f->skb;
- nf->buf = f->buf;
- nf->bcnt = f->bcnt;
- nf->lba = f->lba;
- nf->bv = f->bv;
- nf->bv_off = f->bv_off;
- nf->waited = 0;
- nf->sent_jiffs = f->sent_jiffs;
- f->skb = skb;
- aoe_freetframe(f);
- ht->nout--;
- nf->t->nout++;
resend(d, nf);
}
}
+ head = &d->rexmitq;
+ list_for_each_safe(pos, nx, head) {
+ f = list_entry(pos, struct frame, head);
+ if (f->t != ht)
+ continue;
+ nf = reassign_frame(pos);
+ if (!nf)
+ return 0;
+ resend(d, nf);
+ }
/* We've cleaned up the outstanding so take away his
* interfaces so he won't be used. We should remove him from
* the target array here, but cleaning up a target is
@@ -612,6 +636,7 @@ rexmit_deferred(struct aoedev *d)
struct aoetgt *t;
struct frame *f;
struct list_head *pos, *nx, *head;
+ int since;
head = &d->rexmitq;
list_for_each_safe(pos, nx, head) {
@@ -621,6 +646,9 @@ rexmit_deferred(struct aoedev *d)
continue;
list_del(pos);
t->nout++;
+ since = tsince_hr(f);
+ f->waited += since;
+ f->waited_total += since;
resend(d, f);
}
}
@@ -637,6 +665,7 @@ rexmit_timer(ulong vp)
register long timeout;
ulong flags, n;
int i;
+ int since;
d = (struct aoedev *) vp;
@@ -669,7 +698,8 @@ rexmit_timer(ulong vp)
while (!list_empty(&flist)) {
pos = flist.next;
f = list_entry(pos, struct frame, head);
- n = f->waited += tsince_hr(f);
+ since = tsince_hr(f);
+ n = f->waited_total + since;
n /= USEC_PER_SEC;
if (n > aoe_deadsecs) {
/* Waited too long. Device failure.
@@ -1301,6 +1331,7 @@ aoecmd_ata_id(struct aoedev *d)
fhash(f);
t->nout++;
f->waited = 0;
+ f->waited_total = 0;
/* set up ata header */
ah->scnt = 1;