summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4v/io/ldc.c
diff options
context:
space:
mode:
authornarayan <none@none>2006-10-02 11:51:14 -0700
committernarayan <none@none>2006-10-02 11:51:14 -0700
commita8ea4ede2107d9ad3895b91946b9f33a83c5f7ee (patch)
treef72299ef21f6265923a058d4881bacb3206d26ba /usr/src/uts/sun4v/io/ldc.c
parent055d7c804dc8f1263f0b3166ba459c65996b8697 (diff)
downloadillumos-joyent-a8ea4ede2107d9ad3895b91946b9f33a83c5f7ee.tar.gz
6475901 vnet fails to establish connection with vswitch after service domain reboot
6476056 vldc incorrectly marks port in RESET state 6476337 call to ldc_close blocks for a very long time
Diffstat (limited to 'usr/src/uts/sun4v/io/ldc.c')
-rw-r--r--usr/src/uts/sun4v/io/ldc.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/usr/src/uts/sun4v/io/ldc.c b/usr/src/uts/sun4v/io/ldc.c
index 7fab6d0239..96dc16b5c8 100644
--- a/usr/src/uts/sun4v/io/ldc.c
+++ b/usr/src/uts/sun4v/io/ldc.c
@@ -72,6 +72,7 @@
static int i_ldc_h2v_error(int h_error);
static int i_ldc_txq_reconf(ldc_chan_t *ldcp);
static int i_ldc_rxq_reconf(ldc_chan_t *ldcp, boolean_t force_reset);
+static int i_ldc_rxq_drain(ldc_chan_t *ldcp);
static void i_ldc_reset_state(ldc_chan_t *ldcp);
static void i_ldc_reset(ldc_chan_t *ldcp, boolean_t force_reset);
@@ -561,6 +562,30 @@ i_ldc_rxq_reconf(ldc_chan_t *ldcp, boolean_t force_reset)
return (0);
}
+
+/*
+ * Drain the contents of the receive queue
+ */
+static int
+i_ldc_rxq_drain(ldc_chan_t *ldcp)
+{
+ int rv;
+ uint64_t rx_head, rx_tail;
+
+ ASSERT(MUTEX_HELD(&ldcp->lock));
+ rv = hv_ldc_rx_get_state(ldcp->id, &rx_head, &rx_tail,
+ &(ldcp->link_state));
+ if (rv) {
+ cmn_err(CE_WARN, "i_ldc_rxq_drain: (0x%lx) cannot get state",
+ ldcp->id);
+ return (EIO);
+ }
+
+ /* flush contents by setting the head = tail */
+ return (i_ldc_set_rx_head(ldcp, rx_tail));
+}
+
+
/*
* Reset LDC state structure and its contents
*/
@@ -2668,10 +2693,15 @@ ldc_close(ldc_handle_t handle)
}
/*
- * Drain the Tx and Rx queues
+ * Drain the Tx and Rx queues as we are closing the
+ * channel. We dont care about any pending packets.
+ * We have to also drain the queue prior to clearing
+ * pending interrupts, otherwise the HV will trigger
+ * an interrupt the moment the interrupt state is
+ * cleared.
*/
(void) i_ldc_txq_reconf(ldcp);
- (void) i_ldc_rxq_reconf(ldcp, B_TRUE);
+ (void) i_ldc_rxq_drain(ldcp);
/*
* Unregister the channel with the nexus
@@ -2682,7 +2712,7 @@ ldc_close(ldc_handle_t handle)
mutex_exit(&ldcp->lock);
/* if any error other than EAGAIN return back */
- if (rv != EAGAIN || retries >= LDC_MAX_RETRIES) {
+ if (rv != EAGAIN || retries >= ldc_max_retries) {
cmn_err(CE_WARN,
"ldc_close: (0x%lx) unregister failed, %d\n",
ldcp->id, rv);
@@ -2693,7 +2723,7 @@ ldc_close(ldc_handle_t handle)
* As there could be pending interrupts we need
* to wait and try again
*/
- drv_usecwait(LDC_DELAY);
+ drv_usecwait(ldc_delay);
mutex_enter(&ldcp->lock);
mutex_enter(&ldcp->tx_lock);
retries++;