usr/src/uts/intel/io/vmxnet3s/vmxnet3_rx.c
changeset 14277 711401aaa206
parent 13976 814bae19b8a2
--- a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_rx.c	Thu Apr 30 20:04:18 2015 +0100
+++ b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_rx.c	Sun May 03 18:26:55 2015 +0100
@@ -14,7 +14,7 @@
  *
  *********************************************************/
 /*
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #include <vmxnet3_solaris.h>
@@ -104,6 +104,42 @@
 /*
  *---------------------------------------------------------------------------
  *
+ * vmxnet3_put_rxpool_buf --
+ *
+ *    Return a rxBuf to the pool.
+ *
+ * Results:
+ *    B_TRUE if there was room in the pool and the rxBuf was returned,
+ *    B_FALSE otherwise.
+ *
+ * Side effects:
+ *    None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static boolean_t
+vmxnet3_put_rxpool_buf(vmxnet3_softc_t *dp, vmxnet3_rxbuf_t *rxBuf)
+{
+   vmxnet3_rxpool_t *rxPool = &dp->rxPool;
+   boolean_t returned = B_FALSE;
+
+   mutex_enter(&dp->rxPoolLock);
+   ASSERT(rxPool->nBufs <= rxPool->nBufsLimit);
+   if (dp->devEnabled && rxPool->nBufs < rxPool->nBufsLimit) {
+      ASSERT((rxPool->listHead == NULL && rxPool->nBufs == 0) ||
+         (rxPool->listHead != NULL && rxPool->nBufs != 0));
+      rxBuf->next = rxPool->listHead;
+      rxPool->listHead = rxBuf;
+      rxPool->nBufs++;
+      returned = B_TRUE;
+   }
+   mutex_exit(&dp->rxPoolLock);
+   return returned;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
  * vmxnet3_put_rxbuf --
  *
  *    Return a rxBuf to the pool or free it.
@@ -120,19 +156,44 @@
 vmxnet3_put_rxbuf(vmxnet3_rxbuf_t *rxBuf)
 {
    vmxnet3_softc_t *dp = rxBuf->dp;
-   vmxnet3_rxpool_t *rxPool = &dp->rxPool;
 
    VMXNET3_DEBUG(dp, 5, "free 0x%p\n", rxBuf);
 
+   if (!vmxnet3_put_rxpool_buf(dp, rxBuf))
+      vmxnet3_free_rxbuf(dp, rxBuf);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * vmxnet3_get_rxpool_buf --
+ *
+ *    Get an unused rxBuf from the pool.
+ *
+ * Results:
+ *    A rxBuf or NULL if there are no buffers in the pool.
+ *
+ * Side effects:
+ *    None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static vmxnet3_rxbuf_t *
+vmxnet3_get_rxpool_buf(vmxnet3_softc_t *dp)
+{
+   vmxnet3_rxpool_t *rxPool = &dp->rxPool;
+   vmxnet3_rxbuf_t *rxBuf = NULL;
+
    mutex_enter(&dp->rxPoolLock);
-   if (dp->devEnabled && rxPool->nBufs < rxPool->nBufsLimit) {
-      rxBuf->next = rxPool->listHead;
-      rxPool->listHead = rxBuf;
-      mutex_exit(&dp->rxPoolLock);
-   } else {
-      mutex_exit(&dp->rxPoolLock);
-      vmxnet3_free_rxbuf(dp, rxBuf);
+   if (rxPool->listHead) {
+      rxBuf = rxPool->listHead;
+      rxPool->listHead = rxBuf->next;
+      rxPool->nBufs--;
+      ASSERT((rxPool->listHead == NULL && rxPool->nBufs == 0) ||
+         (rxPool->listHead != NULL && rxPool->nBufs != 0));
    }
+   mutex_exit(&dp->rxPoolLock);
+   return rxBuf;
 }
 
 /*
@@ -155,35 +216,24 @@
 vmxnet3_get_rxbuf(vmxnet3_softc_t *dp, boolean_t canSleep)
 {
    vmxnet3_rxbuf_t *rxBuf;
-   vmxnet3_rxpool_t *rxPool = &dp->rxPool;
 
-   mutex_enter(&dp->rxPoolLock);
-   if (rxPool->listHead) {
-      rxBuf = rxPool->listHead;
-      rxPool->listHead = rxBuf->next;
-      mutex_exit(&dp->rxPoolLock);
+   if ((rxBuf = vmxnet3_get_rxpool_buf(dp))) {
       VMXNET3_DEBUG(dp, 5, "alloc 0x%p from pool\n", rxBuf);
-   } else {
-      mutex_exit(&dp->rxPoolLock);
-      rxBuf = vmxnet3_alloc_rxbuf(dp, canSleep);
-      if (!rxBuf) {
-         goto done;
-      }
+   } else if ((rxBuf = vmxnet3_alloc_rxbuf(dp, canSleep))) {
       VMXNET3_DEBUG(dp, 5, "alloc 0x%p from mem\n", rxBuf);
    }
 
-   ASSERT(rxBuf);
-
-   rxBuf->mblk = desballoc((uchar_t *) rxBuf->dma.buf,
-                           rxBuf->dma.bufLen, BPRI_MED,
-                           &rxBuf->freeCB);
-   if (!rxBuf->mblk) {
-      vmxnet3_put_rxbuf(rxBuf);
-      atomic_inc_32(&dp->rx_alloc_failed);
-      rxBuf = NULL;
+   if (rxBuf) {
+      rxBuf->mblk = desballoc((uchar_t *) rxBuf->dma.buf,
+                              rxBuf->dma.bufLen, BPRI_MED,
+                              &rxBuf->freeCB);
+      if (!rxBuf->mblk) {
+         vmxnet3_put_rxbuf(rxBuf);
+         atomic_inc_32(&dp->rx_alloc_failed);
+         rxBuf = NULL;
+      }
    }
 
-done:
    return rxBuf;
 }
 
@@ -287,18 +337,14 @@
 void
 vmxnet3_rxqueue_fini(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq)
 {
-   vmxnet3_rxpool_t *rxPool = &dp->rxPool;
    vmxnet3_rxbuf_t *rxBuf;
    unsigned int i;
 
    ASSERT(!dp->devEnabled);
 
    /* First the rxPool */
-   while (rxPool->listHead) {
-      rxBuf = rxPool->listHead;
-      rxPool->listHead = rxBuf->next;
+   while ((rxBuf = vmxnet3_get_rxpool_buf(dp)))
       vmxnet3_free_rxbuf(dp, rxBuf);
-   }
 
    /* Then the ring */
    for (i = 0; i < rxq->cmdRing.size; i++) {