summaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/ldc.c
diff options
context:
space:
mode:
authorJag Raman <jag.raman@oracle.com>2017-06-09 18:29:30 +0200
committerDavid S. Miller <davem@davemloft.net>2017-06-10 23:10:55 +0200
commitfc43b978a02985aad7540d77de6b3aa0579a678c (patch)
tree704de1a839c167b30e9d2d94fed8b6fb425343c7 /arch/sparc/kernel/ldc.c
parentsparc64: enhance ldc_abort to print message (diff)
downloadlinux-fc43b978a02985aad7540d77de6b3aa0579a678c.tar.xz
linux-fc43b978a02985aad7540d77de6b3aa0579a678c.zip
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>
Diffstat (limited to 'arch/sparc/kernel/ldc.c')
-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)
lp->hs_state = LDC_HS_COMPLETE;
ldc_set_state(lp, LDC_STATE_CONNECTED);
- event_mask |= LDC_EVENT_UP;
-
- orig_state = lp->chan_state;
+ /*
+ * Generate an LDC_EVENT_UP event if the channel
+ * was not already up.
+ */
+ if (orig_state != LDC_CHANNEL_UP) {
+ event_mask |= LDC_EVENT_UP;
+ orig_state = lp->chan_state;
+ }
}
/* 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)
lp->hs_state = LDC_HS_COMPLETE;
ldc_set_state(lp, LDC_STATE_CONNECTED);
- event_mask |= LDC_EVENT_UP;
+ /*
+ * Generate an LDC_EVENT_UP event if the channel
+ * was not already up.
+ */
+ if (orig_state != LDC_CHANNEL_UP) {
+ event_mask |= LDC_EVENT_UP;
+ orig_state = lp->chan_state;
+ }
}
spin_unlock_irqrestore(&lp->lock, flags);
@@ -1475,9 +1487,17 @@ void __ldc_print(struct ldc_channel *lp, const char *caller)
static int write_raw(struct ldc_channel *lp, const void *buf, unsigned int size)
{
struct ldc_packet *p;
- unsigned long new_tail;
+ unsigned long new_tail, hv_err;
int err;
+ hv_err = sun4v_ldc_tx_get_state(lp->id, &lp->tx_head, &lp->tx_tail,
+ &lp->chan_state);
+ if (unlikely(hv_err))
+ return -EBUSY;
+
+ if (unlikely(lp->chan_state != LDC_CHANNEL_UP))
+ return LDC_ABORT(lp);
+
if (size > LDC_PACKET_SIZE)
return -EMSGSIZE;