From 85762a65c1106daa0930bc2ed0d7792511647168 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 9 Jun 2017 12:29:28 -0400 Subject: [PATCH 1/5] sparc64: expand LDC interface Add the following LDC APIs which are planned to be used by LDC clients in the future: - ldc_set_state: Sets given LDC channel to given state - ldc_mode: Returns the mode of given LDC channel - ldc_print: Prints info about given LDC channel - ldc_rx_reset: Reset the RX queue of given LDC channel Signed-off-by: Jagannathan Raman Reviewed-by: Aaron Young Reviewed-by: Alexandre Chartre Reviewed-by: Bijan Mottahedeh Reviewed-by: Liam Merwick Signed-off-by: David S. Miller --- arch/sparc/include/asm/ldc.h | 8 +++++++ arch/sparc/kernel/ldc.c | 46 ++++++++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/arch/sparc/include/asm/ldc.h b/arch/sparc/include/asm/ldc.h index 6e9004aa6f25..698738a10414 100644 --- a/arch/sparc/include/asm/ldc.h +++ b/arch/sparc/include/asm/ldc.h @@ -48,6 +48,8 @@ struct ldc_channel_config { #define LDC_STATE_READY 0x03 #define LDC_STATE_CONNECTED 0x04 +#define LDC_PACKET_SIZE 64 + struct ldc_channel; /* Allocate state for a channel. */ @@ -72,6 +74,12 @@ int ldc_connect(struct ldc_channel *lp); int ldc_disconnect(struct ldc_channel *lp); int ldc_state(struct ldc_channel *lp); +void ldc_set_state(struct ldc_channel *lp, u8 state); +int ldc_mode(struct ldc_channel *lp); +void __ldc_print(struct ldc_channel *lp, const char *caller); +int ldc_rx_reset(struct ldc_channel *lp); + +#define ldc_print(chan) __ldc_print(chan, __func__) /* Read and write operations. Only valid when the link is up. */ int ldc_write(struct ldc_channel *lp, const void *buf, diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index 59d503866431..77c34b00eccc 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -34,7 +34,6 @@ static char version[] = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; -#define LDC_PACKET_SIZE 64 /* Packet header layout for unreliable and reliable mode frames. * When in RAW mode, packets are simply straight 64-byte payloads @@ -196,15 +195,6 @@ static const char *state_to_str(u8 state) } } -static void ldc_set_state(struct ldc_channel *lp, u8 state) -{ - ldcdbg(STATE, "STATE (%s) --> (%s)\n", - state_to_str(lp->state), - state_to_str(state)); - - lp->state = state; -} - static unsigned long __advance(unsigned long off, unsigned long num_entries) { off += LDC_PACKET_SIZE; @@ -829,7 +819,7 @@ static irqreturn_t ldc_rx(int irq, void *dev_id) * everything. */ if (lp->flags & LDC_FLAG_RESET) { - (void) __set_rx_head(lp, lp->rx_tail); + (void) ldc_rx_reset(lp); goto out; } @@ -1447,6 +1437,38 @@ int ldc_state(struct ldc_channel *lp) } EXPORT_SYMBOL(ldc_state); +void ldc_set_state(struct ldc_channel *lp, u8 state) +{ + ldcdbg(STATE, "STATE (%s) --> (%s)\n", + state_to_str(lp->state), + state_to_str(state)); + + lp->state = state; +} + +int ldc_mode(struct ldc_channel *lp) +{ + return lp->cfg.mode; +} + +int ldc_rx_reset(struct ldc_channel *lp) +{ + return __set_rx_head(lp, lp->rx_tail); +} + +void __ldc_print(struct ldc_channel *lp, const char *caller) +{ + pr_info("%s: id=0x%lx flags=0x%x state=%s cstate=0x%lx hsstate=0x%x\n" + "\trx_h=0x%lx rx_t=0x%lx rx_n=%ld\n" + "\ttx_h=0x%lx tx_t=0x%lx tx_n=%ld\n" + "\trcv_nxt=%u snd_nxt=%u\n", + caller, lp->id, lp->flags, state_to_str(lp->state), + lp->chan_state, lp->hs_state, + lp->rx_head, lp->rx_tail, lp->rx_num_entries, + lp->tx_head, lp->tx_tail, lp->tx_num_entries, + lp->rcv_nxt, lp->snd_nxt); +} + static int write_raw(struct ldc_channel *lp, const void *buf, unsigned int size) { struct ldc_packet *p; @@ -1592,7 +1614,7 @@ static int rx_bad_seq(struct ldc_channel *lp, struct ldc_packet *p, if (err) return err; - err = __set_rx_head(lp, lp->rx_tail); + err = ldc_rx_reset(lp); if (err < 0) return ldc_abort(lp); From 29693e75a823131a789b519150027e2d69fecab7 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 9 Jun 2017 12:29:29 -0400 Subject: [PATCH 2/5] sparc64: enhance ldc_abort to print message Enhance ldc_abort to accept a message to be printed when it is called. Add a macro, LDC_ABORT, to print info. about the function that calls ldc_abort. Signed-off-by: Jagannathan Raman Reviewed-by: Aaron Young Reviewed-by: Alexandre Chartre Reviewed-by: Bijan Mottahedeh Reviewed-by: Liam Merwick Signed-off-by: David S. Miller --- arch/sparc/kernel/ldc.c | 53 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index 77c34b00eccc..902cbf4fa007 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -177,6 +177,8 @@ do { if (lp->cfg.debug & LDC_DEBUG_##TYPE) \ printk(KERN_INFO PFX "ID[%lu] " f, lp->id, ## a); \ } while (0) +#define LDC_ABORT(lp) ldc_abort((lp), __func__) + static const char *state_to_str(u8 state) { switch (state) { @@ -506,11 +508,12 @@ static int send_data_nack(struct ldc_channel *lp, struct ldc_packet *data_pkt) return err; } -static int ldc_abort(struct ldc_channel *lp) +static int ldc_abort(struct ldc_channel *lp, const char *msg) { unsigned long hv_err; - ldcdbg(STATE, "ABORT\n"); + ldcdbg(STATE, "ABORT[%s]\n", msg); + ldc_print(lp); /* We report but do not act upon the hypervisor errors because * there really isn't much we can do if they fail at this point. @@ -595,7 +598,7 @@ static int process_ver_info(struct ldc_channel *lp, struct ldc_version *vp) } } if (err) - return ldc_abort(lp); + return LDC_ABORT(lp); return 0; } @@ -608,13 +611,13 @@ static int process_ver_ack(struct ldc_channel *lp, struct ldc_version *vp) if (lp->hs_state == LDC_HS_GOTVERS) { if (lp->ver.major != vp->major || lp->ver.minor != vp->minor) - return ldc_abort(lp); + return LDC_ABORT(lp); } else { lp->ver = *vp; lp->hs_state = LDC_HS_GOTVERS; } if (send_rts(lp)) - return ldc_abort(lp); + return LDC_ABORT(lp); return 0; } @@ -625,17 +628,17 @@ static int process_ver_nack(struct ldc_channel *lp, struct ldc_version *vp) unsigned long new_tail; if (vp->major == 0 && vp->minor == 0) - return ldc_abort(lp); + return LDC_ABORT(lp); vap = find_by_major(vp->major); if (!vap) - return ldc_abort(lp); + return LDC_ABORT(lp); p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS, vap, sizeof(*vap), &new_tail); if (!p) - return ldc_abort(lp); + return LDC_ABORT(lp); return send_tx_packet(lp, p, new_tail); } @@ -658,7 +661,7 @@ static int process_version(struct ldc_channel *lp, return process_ver_nack(lp, vp); default: - return ldc_abort(lp); + return LDC_ABORT(lp); } } @@ -671,13 +674,13 @@ static int process_rts(struct ldc_channel *lp, if (p->stype != LDC_INFO || lp->hs_state != LDC_HS_GOTVERS || p->env != lp->cfg.mode) - return ldc_abort(lp); + return LDC_ABORT(lp); lp->snd_nxt = p->seqid; lp->rcv_nxt = p->seqid; lp->hs_state = LDC_HS_SENTRTR; if (send_rtr(lp)) - return ldc_abort(lp); + return LDC_ABORT(lp); return 0; } @@ -690,7 +693,7 @@ static int process_rtr(struct ldc_channel *lp, if (p->stype != LDC_INFO || p->env != lp->cfg.mode) - return ldc_abort(lp); + return LDC_ABORT(lp); lp->snd_nxt = p->seqid; lp->hs_state = LDC_HS_COMPLETE; @@ -713,7 +716,7 @@ static int process_rdx(struct ldc_channel *lp, if (p->stype != LDC_INFO || !(rx_seq_ok(lp, p->seqid))) - return ldc_abort(lp); + return LDC_ABORT(lp); lp->rcv_nxt = p->seqid; @@ -740,14 +743,14 @@ static int process_control_frame(struct ldc_channel *lp, return process_rdx(lp, p); default: - return ldc_abort(lp); + return LDC_ABORT(lp); } } static int process_error_frame(struct ldc_channel *lp, struct ldc_packet *p) { - return ldc_abort(lp); + return LDC_ABORT(lp); } static int process_data_ack(struct ldc_channel *lp, @@ -766,7 +769,7 @@ static int process_data_ack(struct ldc_channel *lp, return 0; } if (head == lp->tx_tail) - return ldc_abort(lp); + return LDC_ABORT(lp); } return 0; @@ -870,7 +873,7 @@ static irqreturn_t ldc_rx(int irq, void *dev_id) break; default: - err = ldc_abort(lp); + err = LDC_ABORT(lp); break; } @@ -885,7 +888,7 @@ static irqreturn_t ldc_rx(int irq, void *dev_id) err = __set_rx_head(lp, new); if (err < 0) { - (void) ldc_abort(lp); + (void) LDC_ABORT(lp); break; } if (lp->hs_state == LDC_HS_COMPLETE) @@ -1505,7 +1508,7 @@ static int read_raw(struct ldc_channel *lp, void *buf, unsigned int size) &lp->rx_tail, &lp->chan_state); if (hv_err) - return ldc_abort(lp); + return LDC_ABORT(lp); if (lp->chan_state == LDC_CHANNEL_DOWN || lp->chan_state == LDC_CHANNEL_RESETTING) @@ -1548,7 +1551,7 @@ static int write_nonraw(struct ldc_channel *lp, const void *buf, return -EBUSY; if (unlikely(lp->chan_state != LDC_CHANNEL_UP)) - return ldc_abort(lp); + return LDC_ABORT(lp); if (!tx_has_space_for(lp, size)) return -EAGAIN; @@ -1616,7 +1619,7 @@ static int rx_bad_seq(struct ldc_channel *lp, struct ldc_packet *p, err = ldc_rx_reset(lp); if (err < 0) - return ldc_abort(lp); + return LDC_ABORT(lp); return 0; } @@ -1629,7 +1632,7 @@ static int data_ack_nack(struct ldc_channel *lp, struct ldc_packet *p) return err; } if (p->stype & LDC_NACK) - return ldc_abort(lp); + return LDC_ABORT(lp); return 0; } @@ -1649,7 +1652,7 @@ static int rx_data_wait(struct ldc_channel *lp, unsigned long cur_head) &lp->rx_tail, &lp->chan_state); if (hv_err) - return ldc_abort(lp); + return LDC_ABORT(lp); if (lp->chan_state == LDC_CHANNEL_DOWN || lp->chan_state == LDC_CHANNEL_RESETTING) @@ -1672,7 +1675,7 @@ static int rx_set_head(struct ldc_channel *lp, unsigned long head) int err = __set_rx_head(lp, head); if (err < 0) - return ldc_abort(lp); + return LDC_ABORT(lp); lp->rx_head = head; return 0; @@ -1711,7 +1714,7 @@ static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size) &lp->rx_tail, &lp->chan_state); if (hv_err) - return ldc_abort(lp); + return LDC_ABORT(lp); if (lp->chan_state == LDC_CHANNEL_DOWN || lp->chan_state == LDC_CHANNEL_RESETTING) From fc43b978a02985aad7540d77de6b3aa0579a678c Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 9 Jun 2017 12:29:30 -0400 Subject: [PATCH 3/5] 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 Reviewed-by: Aaron Young Reviewed-by: Alexandre Chartre Reviewed-by: Bijan Mottahedeh Reviewed-by: Liam Merwick Signed-off-by: David S. Miller --- arch/sparc/kernel/ldc.c | 30 +++++++++++++++++++++++++----- 1 file 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; From 6c95483b768c62f8ee933ae08a1bdbcb78b5410f Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 9 Jun 2017 12:29:31 -0400 Subject: [PATCH 4/5] sparc64: ldc abort during vds iso boot Orabug: 20902628 When an ldc control-only packet is received during data exchange in read_nonraw(), a new rx head is calculated but the rx queue head is not actually advanced (rx_set_head() is not called) and a branch is taken to 'no_data' at which point two things can happen depending on the value of the newly calculated rx head and the current rx tail: - If the rx queue is determined to be not empty, then the wrong packet is picked up. - If the rx queue is determined to be empty, then a read error (EAGAIN) is eventually returned since it is falsely assumed that more data was expected. The fix is to update the rx head and return in case of a control only packet during data exchange. Signed-off-by: Jagannathan Raman Reviewed-by: Aaron Young Reviewed-by: Alexandre Chartre Reviewed-by: Bijan Mottahedeh Reviewed-by: Liam Merwick Signed-off-by: David S. Miller --- arch/sparc/kernel/ldc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index 639da7b53e83..47817b78ebfc 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -1778,9 +1778,14 @@ static int read_nonraw(struct ldc_channel *lp, void *buf, unsigned int size) lp->rcv_nxt = p->seqid; + /* + * If this is a control-only packet, there is nothing + * else to do but advance the rx queue since the packet + * was already processed above. + */ if (!(p->type & LDC_DATA)) { new = rx_advance(lp, new); - goto no_data; + break; } if (p->stype & (LDC_ACK | LDC_NACK)) { err = data_ack_nack(lp, p); From 93ec4a828e6d777a61f497bc6e0cf9239fde35c7 Mon Sep 17 00:00:00 2001 From: Jag Raman Date: Fri, 9 Jun 2017 12:29:32 -0400 Subject: [PATCH 5/5] sparc64: print debug messages when reading from LDC channel Print debug messages when reading from given LDC channel. Signed-off-by: Jagannathan Raman Reviewed-by: Aaron Young Reviewed-by: Alexandre Chartre Reviewed-by: Bijan Mottahedeh Reviewed-by: Liam Merwick Signed-off-by: David S. Miller --- arch/sparc/kernel/ldc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index 47817b78ebfc..97a5743b04e2 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -1950,6 +1950,8 @@ int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size) unsigned long flags; int err; + ldcdbg(RX, "%s: entered size=%d\n", __func__, size); + if (!buf) return -EINVAL; @@ -1965,6 +1967,9 @@ int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size) spin_unlock_irqrestore(&lp->lock, flags); + ldcdbg(RX, "%s: mode=%d, head=%lu, tail=%lu rv=%d\n", __func__, + lp->cfg.mode, lp->rx_head, lp->rx_tail, err); + return err; } EXPORT_SYMBOL(ldc_read);