From cb4812358423e7ea47d2b6471918d65238452cc5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 11 Jul 2007 18:14:41 -0700 Subject: [PATCH] [SPARC64]: Assorted LDC bug cures. 1) LDC_MODE_RELIABLE is deprecated an unused by anything, plus it and LDC_MODE_STREAM were mis-numbered. 2) read_stream() should try to read as much as possible into the per-LDC stream buffer area, so do not trim the read_nonraw() length by the caller's size parameter. 3) Send data ACKs when necessary in read_nonraw(). 4) In read_nonraw() when we get a pure ACK, advance the RX head unconditionally past it. 5) Provide the ACKID field in the ldcdgb() packet dump in read_nonraw(). This helps debugging stream mode LDC channel problems. 6) Decrease verbosity of rx_data_wait() so that it is more useful. A debugging message each loop iteration is too much. 7) In process_data_ack() stop the loop checking when we hit lp->tx_tail not lp->tx_head. 8) Set the seqid field properly in send_data_nack(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/ldc.c | 56 ++++++++++++++++++++++++++------------- include/asm-sparc64/ldc.h | 3 +-- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c index 0fa04d6f97..4cba286859 100644 --- a/arch/sparc64/kernel/ldc.c +++ b/arch/sparc64/kernel/ldc.c @@ -239,8 +239,7 @@ static struct ldc_packet *handshake_get_tx_packet(struct ldc_channel *lp, */ static unsigned long head_for_data(struct ldc_channel *lp) { - if (lp->cfg.mode == LDC_MODE_RELIABLE || - lp->cfg.mode == LDC_MODE_STREAM) + if (lp->cfg.mode == LDC_MODE_STREAM) return lp->tx_acked; return lp->tx_head; } @@ -494,7 +493,7 @@ static int send_data_nack(struct ldc_channel *lp, struct ldc_packet *data_pkt) p->type = data_pkt->type; p->stype = LDC_NACK; p->ctrl = data_pkt->ctrl & LDC_CTRL_MSK; - p->seqid = lp->snd_nxt; + p->seqid = lp->snd_nxt + 1; p->u.r.ackid = lp->rcv_nxt; ldcdbg(HS, "SEND DATA NACK type[0x%x] ctl[0x%x] seq[0x%x] ack[0x%x]\n", @@ -765,7 +764,7 @@ static int process_data_ack(struct ldc_channel *lp, lp->tx_acked = head; return 0; } - if (head == lp->tx_head) + if (head == lp->tx_tail) return ldc_abort(lp); } @@ -1093,11 +1092,6 @@ struct ldc_channel *ldc_alloc(unsigned long id, mss = LDC_PACKET_SIZE - 8; break; - case LDC_MODE_RELIABLE: - mops = &nonraw_ops; - mss = LDC_PACKET_SIZE - 8 - 8; - break; - case LDC_MODE_STREAM: mops = &stream_ops; mss = LDC_PACKET_SIZE - 8 - 8; @@ -1579,15 +1573,14 @@ static int rx_data_wait(struct ldc_channel *lp, unsigned long cur_head) if (hv_err) return ldc_abort(lp); - ldcdbg(DATA, "REREAD head[%lx] tail[%lx] chan_state[%lx]\n", - dummy, lp->rx_tail, lp->chan_state); - if (lp->chan_state == LDC_CHANNEL_DOWN || lp->chan_state == LDC_CHANNEL_RESETTING) return -ECONNRESET; if (cur_head != lp->rx_tail) { - ldcdbg(DATA, "DATA WAIT DONE\n"); + ldcdbg(DATA, "DATA WAIT DONE " + "head[%lx] tail[%lx] chan_state[%lx]\n", + dummy, lp->rx_tail, lp->chan_state); return 0; } @@ -1607,6 +1600,28 @@ static int rx_set_head(struct ldc_channel *lp, unsigned long head) return 0; } +static void send_data_ack(struct ldc_channel *lp) +{ + unsigned long new_tail; + struct ldc_packet *p; + + p = data_get_tx_packet(lp, &new_tail); + if (likely(p)) { + int err; + + memset(p, 0, sizeof(*p)); + p->type = LDC_DATA; + p->stype = LDC_ACK; + p->ctrl = 0; + p->seqid = lp->snd_nxt + 1; + p->u.r.ackid = lp->rcv_nxt; + + err = send_tx_packet(lp, p, new_tail); + if (!err) + lp->snd_nxt++; + } +} + static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size) { struct ldc_packet *first_frag; @@ -1637,13 +1652,14 @@ static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size) BUG_ON(new == lp->rx_tail); p = lp->rx_base + (new / LDC_PACKET_SIZE); - ldcdbg(RX, "RX read pkt[%02x:%02x:%02x:%02x:%08x] " + ldcdbg(RX, "RX read pkt[%02x:%02x:%02x:%02x:%08x:%08x] " "rcv_nxt[%08x]\n", p->type, p->stype, p->ctrl, p->env, p->seqid, + p->u.r.ackid, lp->rcv_nxt); if (unlikely(!rx_seq_ok(lp, p->seqid))) { @@ -1672,6 +1688,9 @@ static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size) } if (!(p->stype & LDC_INFO)) { new = rx_advance(lp, new); + err = rx_set_head(lp, new); + if (err) + break; goto no_data; } @@ -1748,8 +1767,11 @@ no_data: if (err && first_frag) lp->rcv_nxt = first_frag->seqid - 1; - if (!err) + if (!err) { err = copied; + if (err > 0 && lp->cfg.mode != LDC_MODE_UNRELIABLE) + send_data_ack(lp); + } return err; } @@ -1770,9 +1792,7 @@ static int write_stream(struct ldc_channel *lp, const void *buf, static int read_stream(struct ldc_channel *lp, void *buf, unsigned int size) { if (!lp->mssbuf_len) { - int err = read_nonraw(lp, lp->mssbuf, - (size > lp->cfg.mtu ? - lp->cfg.mtu : size)); + int err = read_nonraw(lp, lp->mssbuf, lp->cfg.mtu); if (err < 0) return err; diff --git a/include/asm-sparc64/ldc.h b/include/asm-sparc64/ldc.h index 24fd2367d3..1c13738f13 100644 --- a/include/asm-sparc64/ldc.h +++ b/include/asm-sparc64/ldc.h @@ -25,8 +25,7 @@ struct ldc_channel_config { #define LDC_MODE_RAW 0x00 #define LDC_MODE_UNRELIABLE 0x01 #define LDC_MODE_RESERVED 0x02 -#define LDC_MODE_RELIABLE 0x03 -#define LDC_MODE_STREAM 0x04 +#define LDC_MODE_STREAM 0x03 u8 debug; #define LDC_DEBUG_HS 0x01 -- 2.39.5