Commit a93a0a31 authored by Michael J. Ruhl's avatar Michael J. Ruhl Committed by Doug Ledford

IB/hfi1: Reorder incorrect send context disable

User send context integrity bits are cleared before the context is
disabled.  If the send context is still processing data, any packets
that need those integrity bits will cause an error and halt the send
context.

During the disable handling, the driver waits for the context to drain.
If the context is halted, the driver will eventually timeout because
the context won't drain and then incorrectly bounce the link.

Reorder the bit clearing and the context disable.

Examine the software state and send context status as well as the
egress status to determine if a send context is in the halted state.

Promote the check macros to static functions for consistency with the
new check and to follow kernel style.

Remove an unused define that refers to the egress timeout.

Cc: <stable@vger.kernel.org> # 4.9.x
Reviewed-by: default avatarMitko Haralanov <mitko.haralanov@intel.com>
Reviewed-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarMichael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent e4607073
...@@ -689,8 +689,8 @@ static int hfi1_file_close(struct inode *inode, struct file *fp) ...@@ -689,8 +689,8 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
* checks to default and disable the send context. * checks to default and disable the send context.
*/ */
if (uctxt->sc) { if (uctxt->sc) {
set_pio_integrity(uctxt->sc);
sc_disable(uctxt->sc); sc_disable(uctxt->sc);
set_pio_integrity(uctxt->sc);
} }
hfi1_free_ctxt_rcv_groups(uctxt); hfi1_free_ctxt_rcv_groups(uctxt);
......
...@@ -50,8 +50,6 @@ ...@@ -50,8 +50,6 @@
#include "qp.h" #include "qp.h"
#include "trace.h" #include "trace.h"
#define SC_CTXT_PACKET_EGRESS_TIMEOUT 350 /* in chip cycles */
#define SC(name) SEND_CTXT_##name #define SC(name) SEND_CTXT_##name
/* /*
* Send Context functions * Send Context functions
...@@ -961,15 +959,40 @@ void sc_disable(struct send_context *sc) ...@@ -961,15 +959,40 @@ void sc_disable(struct send_context *sc)
} }
/* return SendEgressCtxtStatus.PacketOccupancy */ /* return SendEgressCtxtStatus.PacketOccupancy */
#define packet_occupancy(r) \ static u64 packet_occupancy(u64 reg)
(((r) & SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_PACKET_OCCUPANCY_SMASK)\ {
>> SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_PACKET_OCCUPANCY_SHIFT) return (reg &
SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_PACKET_OCCUPANCY_SMASK)
>> SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_PACKET_OCCUPANCY_SHIFT;
}
/* is egress halted on the context? */ /* is egress halted on the context? */
#define egress_halted(r) \ static bool egress_halted(u64 reg)
((r) & SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_HALT_STATUS_SMASK) {
return !!(reg & SEND_EGRESS_CTXT_STATUS_CTXT_EGRESS_HALT_STATUS_SMASK);
}
/* wait for packet egress, optionally pause for credit return */ /* is the send context halted? */
static bool is_sc_halted(struct hfi1_devdata *dd, u32 hw_context)
{
return !!(read_kctxt_csr(dd, hw_context, SC(STATUS)) &
SC(STATUS_CTXT_HALTED_SMASK));
}
/**
* sc_wait_for_packet_egress
* @sc: valid send context
* @pause: wait for credit return
*
* Wait for packet egress, optionally pause for credit return
*
* Egress halt and Context halt are not necessarily the same thing, so
* check for both.
*
* NOTE: The context halt bit may not be set immediately. Because of this,
* it is necessary to check the SW SFC_HALTED bit (set in the IRQ) and the HW
* context bit to determine if the context is halted.
*/
static void sc_wait_for_packet_egress(struct send_context *sc, int pause) static void sc_wait_for_packet_egress(struct send_context *sc, int pause)
{ {
struct hfi1_devdata *dd = sc->dd; struct hfi1_devdata *dd = sc->dd;
...@@ -981,8 +1004,9 @@ static void sc_wait_for_packet_egress(struct send_context *sc, int pause) ...@@ -981,8 +1004,9 @@ static void sc_wait_for_packet_egress(struct send_context *sc, int pause)
reg_prev = reg; reg_prev = reg;
reg = read_csr(dd, sc->hw_context * 8 + reg = read_csr(dd, sc->hw_context * 8 +
SEND_EGRESS_CTXT_STATUS); SEND_EGRESS_CTXT_STATUS);
/* done if egress is stopped */ /* done if any halt bits, SW or HW are set */
if (egress_halted(reg)) if (sc->flags & SCF_HALTED ||
is_sc_halted(dd, sc->hw_context) || egress_halted(reg))
break; break;
reg = packet_occupancy(reg); reg = packet_occupancy(reg);
if (reg == 0) if (reg == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment