Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb481235 authored by David S. Miller's avatar David S. Miller
Browse files

[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: default avatarDavid S. Miller <davem@davemloft.net>
parent 5a606b72
Loading
Loading
Loading
Loading
+38 −18
Original line number Diff line number Diff line
@@ -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 @@ static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size)
	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;

+1 −2
Original line number Diff line number Diff line
@@ -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