aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJag Raman <jag.raman@oracle.com>2017-06-09 12:29:30 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-10 17:10:55 -0400
commitfc43b978a02985aad7540d77de6b3aa0579a678c (patch)
tree704de1a839c167b30e9d2d94fed8b6fb425343c7
parent29693e75a823131a789b519150027e2d69fecab7 (diff)
sparc64: ensure LDC channel is ready before communication
Ensure that LDC channel is up before writing to it, in RAW mode. Generate event to bring the LDC channel up, if it's not up already. Signed-off-by: Jagannathan Raman <jag.raman@oracle.com> Reviewed-by: Aaron Young <aaron.young@oracle.com> Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> Reviewed-by: Bijan Mottahedeh <bijan.mottahedeh@oracle.com> Reviewed-by: Liam Merwick <liam.merwick@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc/kernel/ldc.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index 902cbf4fa007..639da7b53e83 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -813,9 +813,14 @@ static irqreturn_t ldc_rx(int irq, void *dev_id)
813 lp->hs_state = LDC_HS_COMPLETE; 813 lp->hs_state = LDC_HS_COMPLETE;
814 ldc_set_state(lp, LDC_STATE_CONNECTED); 814 ldc_set_state(lp, LDC_STATE_CONNECTED);
815 815
816 event_mask |= LDC_EVENT_UP; 816 /*
817 817 * Generate an LDC_EVENT_UP event if the channel
818 orig_state = lp->chan_state; 818 * was not already up.
819 */
820 if (orig_state != LDC_CHANNEL_UP) {
821 event_mask |= LDC_EVENT_UP;
822 orig_state = lp->chan_state;
823 }
819 } 824 }
820 825
821 /* If we are in reset state, flush the RX queue and ignore 826 /* If we are in reset state, flush the RX queue and ignore
@@ -929,7 +934,14 @@ static irqreturn_t ldc_tx(int irq, void *dev_id)
929 lp->hs_state = LDC_HS_COMPLETE; 934 lp->hs_state = LDC_HS_COMPLETE;
930 ldc_set_state(lp, LDC_STATE_CONNECTED); 935 ldc_set_state(lp, LDC_STATE_CONNECTED);
931 936
932 event_mask |= LDC_EVENT_UP; 937 /*
938 * Generate an LDC_EVENT_UP event if the channel
939 * was not already up.
940 */
941 if (orig_state != LDC_CHANNEL_UP) {
942 event_mask |= LDC_EVENT_UP;
943 orig_state = lp->chan_state;
944 }
933 } 945 }
934 946
935 spin_unlock_irqrestore(&lp->lock, flags); 947 spin_unlock_irqrestore(&lp->lock, flags);
@@ -1475,9 +1487,17 @@ void __ldc_print(struct ldc_channel *lp, const char *caller)
1475static int write_raw(struct ldc_channel *lp, const void *buf, unsigned int size) 1487static int write_raw(struct ldc_channel *lp, const void *buf, unsigned int size)
1476{ 1488{
1477 struct ldc_packet *p; 1489 struct ldc_packet *p;
1478 unsigned long new_tail; 1490 unsigned long new_tail, hv_err;
1479 int err; 1491 int err;
1480 1492
1493 hv_err = sun4v_ldc_tx_get_state(lp->id, &lp->tx_head, &lp->tx_tail,
1494 &lp->chan_state);
1495 if (unlikely(hv_err))
1496 return -EBUSY;
1497
1498 if (unlikely(lp->chan_state != LDC_CHANNEL_UP))
1499 return LDC_ABORT(lp);
1500
1481 if (size > LDC_PACKET_SIZE) 1501 if (size > LDC_PACKET_SIZE)
1482 return -EMSGSIZE; 1502 return -EMSGSIZE;
1483 1503