diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 21:14:41 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-16 07:04:09 -0400 |
commit | cb4812358423e7ea47d2b6471918d65238452cc5 (patch) | |
tree | baa325ecdec9ee88542a5e2350ecf48c3dc88d05 /arch/sparc64/kernel/ldc.c | |
parent | 5a606b72a4309a656cd1a19ad137dc5557c4b8ea (diff) |
[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 <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/ldc.c')
-rw-r--r-- | arch/sparc64/kernel/ldc.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c index 0fa04d6f978d..4cba28685967 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, | |||
239 | */ | 239 | */ |
240 | static unsigned long head_for_data(struct ldc_channel *lp) | 240 | static unsigned long head_for_data(struct ldc_channel *lp) |
241 | { | 241 | { |
242 | if (lp->cfg.mode == LDC_MODE_RELIABLE || | 242 | if (lp->cfg.mode == LDC_MODE_STREAM) |
243 | lp->cfg.mode == LDC_MODE_STREAM) | ||
244 | return lp->tx_acked; | 243 | return lp->tx_acked; |
245 | return lp->tx_head; | 244 | return lp->tx_head; |
246 | } | 245 | } |
@@ -494,7 +493,7 @@ static int send_data_nack(struct ldc_channel *lp, struct ldc_packet *data_pkt) | |||
494 | p->type = data_pkt->type; | 493 | p->type = data_pkt->type; |
495 | p->stype = LDC_NACK; | 494 | p->stype = LDC_NACK; |
496 | p->ctrl = data_pkt->ctrl & LDC_CTRL_MSK; | 495 | p->ctrl = data_pkt->ctrl & LDC_CTRL_MSK; |
497 | p->seqid = lp->snd_nxt; | 496 | p->seqid = lp->snd_nxt + 1; |
498 | p->u.r.ackid = lp->rcv_nxt; | 497 | p->u.r.ackid = lp->rcv_nxt; |
499 | 498 | ||
500 | ldcdbg(HS, "SEND DATA NACK type[0x%x] ctl[0x%x] seq[0x%x] ack[0x%x]\n", | 499 | 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, | |||
765 | lp->tx_acked = head; | 764 | lp->tx_acked = head; |
766 | return 0; | 765 | return 0; |
767 | } | 766 | } |
768 | if (head == lp->tx_head) | 767 | if (head == lp->tx_tail) |
769 | return ldc_abort(lp); | 768 | return ldc_abort(lp); |
770 | } | 769 | } |
771 | 770 | ||
@@ -1093,11 +1092,6 @@ struct ldc_channel *ldc_alloc(unsigned long id, | |||
1093 | mss = LDC_PACKET_SIZE - 8; | 1092 | mss = LDC_PACKET_SIZE - 8; |
1094 | break; | 1093 | break; |
1095 | 1094 | ||
1096 | case LDC_MODE_RELIABLE: | ||
1097 | mops = &nonraw_ops; | ||
1098 | mss = LDC_PACKET_SIZE - 8 - 8; | ||
1099 | break; | ||
1100 | |||
1101 | case LDC_MODE_STREAM: | 1095 | case LDC_MODE_STREAM: |
1102 | mops = &stream_ops; | 1096 | mops = &stream_ops; |
1103 | mss = LDC_PACKET_SIZE - 8 - 8; | 1097 | mss = LDC_PACKET_SIZE - 8 - 8; |
@@ -1579,15 +1573,14 @@ static int rx_data_wait(struct ldc_channel *lp, unsigned long cur_head) | |||
1579 | if (hv_err) | 1573 | if (hv_err) |
1580 | return ldc_abort(lp); | 1574 | return ldc_abort(lp); |
1581 | 1575 | ||
1582 | ldcdbg(DATA, "REREAD head[%lx] tail[%lx] chan_state[%lx]\n", | ||
1583 | dummy, lp->rx_tail, lp->chan_state); | ||
1584 | |||
1585 | if (lp->chan_state == LDC_CHANNEL_DOWN || | 1576 | if (lp->chan_state == LDC_CHANNEL_DOWN || |
1586 | lp->chan_state == LDC_CHANNEL_RESETTING) | 1577 | lp->chan_state == LDC_CHANNEL_RESETTING) |
1587 | return -ECONNRESET; | 1578 | return -ECONNRESET; |
1588 | 1579 | ||
1589 | if (cur_head != lp->rx_tail) { | 1580 | if (cur_head != lp->rx_tail) { |
1590 | ldcdbg(DATA, "DATA WAIT DONE\n"); | 1581 | ldcdbg(DATA, "DATA WAIT DONE " |
1582 | "head[%lx] tail[%lx] chan_state[%lx]\n", | ||
1583 | dummy, lp->rx_tail, lp->chan_state); | ||
1591 | return 0; | 1584 | return 0; |
1592 | } | 1585 | } |
1593 | 1586 | ||
@@ -1607,6 +1600,28 @@ static int rx_set_head(struct ldc_channel *lp, unsigned long head) | |||
1607 | return 0; | 1600 | return 0; |
1608 | } | 1601 | } |
1609 | 1602 | ||
1603 | static void send_data_ack(struct ldc_channel *lp) | ||
1604 | { | ||
1605 | unsigned long new_tail; | ||
1606 | struct ldc_packet *p; | ||
1607 | |||
1608 | p = data_get_tx_packet(lp, &new_tail); | ||
1609 | if (likely(p)) { | ||
1610 | int err; | ||
1611 | |||
1612 | memset(p, 0, sizeof(*p)); | ||
1613 | p->type = LDC_DATA; | ||
1614 | p->stype = LDC_ACK; | ||
1615 | p->ctrl = 0; | ||
1616 | p->seqid = lp->snd_nxt + 1; | ||
1617 | p->u.r.ackid = lp->rcv_nxt; | ||
1618 | |||
1619 | err = send_tx_packet(lp, p, new_tail); | ||
1620 | if (!err) | ||
1621 | lp->snd_nxt++; | ||
1622 | } | ||
1623 | } | ||
1624 | |||
1610 | static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size) | 1625 | static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size) |
1611 | { | 1626 | { |
1612 | struct ldc_packet *first_frag; | 1627 | struct ldc_packet *first_frag; |
@@ -1637,13 +1652,14 @@ static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size) | |||
1637 | BUG_ON(new == lp->rx_tail); | 1652 | BUG_ON(new == lp->rx_tail); |
1638 | p = lp->rx_base + (new / LDC_PACKET_SIZE); | 1653 | p = lp->rx_base + (new / LDC_PACKET_SIZE); |
1639 | 1654 | ||
1640 | ldcdbg(RX, "RX read pkt[%02x:%02x:%02x:%02x:%08x] " | 1655 | ldcdbg(RX, "RX read pkt[%02x:%02x:%02x:%02x:%08x:%08x] " |
1641 | "rcv_nxt[%08x]\n", | 1656 | "rcv_nxt[%08x]\n", |
1642 | p->type, | 1657 | p->type, |
1643 | p->stype, | 1658 | p->stype, |
1644 | p->ctrl, | 1659 | p->ctrl, |
1645 | p->env, | 1660 | p->env, |
1646 | p->seqid, | 1661 | p->seqid, |
1662 | p->u.r.ackid, | ||
1647 | lp->rcv_nxt); | 1663 | lp->rcv_nxt); |
1648 | 1664 | ||
1649 | if (unlikely(!rx_seq_ok(lp, p->seqid))) { | 1665 | 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) | |||
1672 | } | 1688 | } |
1673 | if (!(p->stype & LDC_INFO)) { | 1689 | if (!(p->stype & LDC_INFO)) { |
1674 | new = rx_advance(lp, new); | 1690 | new = rx_advance(lp, new); |
1691 | err = rx_set_head(lp, new); | ||
1692 | if (err) | ||
1693 | break; | ||
1675 | goto no_data; | 1694 | goto no_data; |
1676 | } | 1695 | } |
1677 | 1696 | ||
@@ -1748,8 +1767,11 @@ no_data: | |||
1748 | if (err && first_frag) | 1767 | if (err && first_frag) |
1749 | lp->rcv_nxt = first_frag->seqid - 1; | 1768 | lp->rcv_nxt = first_frag->seqid - 1; |
1750 | 1769 | ||
1751 | if (!err) | 1770 | if (!err) { |
1752 | err = copied; | 1771 | err = copied; |
1772 | if (err > 0 && lp->cfg.mode != LDC_MODE_UNRELIABLE) | ||
1773 | send_data_ack(lp); | ||
1774 | } | ||
1753 | 1775 | ||
1754 | return err; | 1776 | return err; |
1755 | } | 1777 | } |
@@ -1770,9 +1792,7 @@ static int write_stream(struct ldc_channel *lp, const void *buf, | |||
1770 | static int read_stream(struct ldc_channel *lp, void *buf, unsigned int size) | 1792 | static int read_stream(struct ldc_channel *lp, void *buf, unsigned int size) |
1771 | { | 1793 | { |
1772 | if (!lp->mssbuf_len) { | 1794 | if (!lp->mssbuf_len) { |
1773 | int err = read_nonraw(lp, lp->mssbuf, | 1795 | int err = read_nonraw(lp, lp->mssbuf, lp->cfg.mtu); |
1774 | (size > lp->cfg.mtu ? | ||
1775 | lp->cfg.mtu : size)); | ||
1776 | if (err < 0) | 1796 | if (err < 0) |
1777 | return err; | 1797 | return err; |
1778 | 1798 | ||