2 * Copyright (C) 2007-2014 VMware, Inc. All rights reserved.
4 * The contents of this file are subject to the terms of the Common
5 * Development and Distribution License (the "License") version 1.0
6 * and no later version. You may not use this file except in
7 * compliance with the License.
9 * You can obtain a copy of the License at
10 * http://www.opensource.org/licenses/cddl1.php
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
17 * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
23 * This driver is based on VMware's version 3227872, and contains additional
24 * enhancements (see README.txt).
26 #define BUILD_NUMBER_NUMERIC 3227872
29 * If we run out of rxPool buffers, only allocate if the MTU is <= PAGESIZE
30 * so that we don't have to incur the cost of allocating multiple contiguous
31 * pages (very slow) in interrupt context.
33 #define VMXNET3_ALLOC_OK(dp) ((dp)->cur_mtu <= PAGESIZE)
38 * - MAC_CAPAB_POLL support
42 static int vmxnet3_getstat(void *, uint_t
, uint64_t *);
43 static int vmxnet3_start(void *);
44 static void vmxnet3_stop(void *);
45 static int vmxnet3_setpromisc(void *, boolean_t
);
46 static void vmxnet3_ioctl(void *arg
, queue_t
*wq
, mblk_t
*mp
);
47 static int vmxnet3_multicst(void *, boolean_t
, const uint8_t *);
48 static int vmxnet3_unicst(void *, const uint8_t *);
49 static boolean_t
vmxnet3_getcapab(void *, mac_capab_t
, void *);
50 static int vmxnet3_get_prop(void *, const char *, mac_prop_id_t
, uint_t
,
52 static int vmxnet3_set_prop(void *, const char *, mac_prop_id_t
, uint_t
,
54 static void vmxnet3_prop_info(void *, const char *, mac_prop_id_t
,
55 mac_prop_info_handle_t
);
57 int vmxnet3s_debug
= 0;
60 static mac_callbacks_t vmxnet3_mac_callbacks
= {
61 .mc_callbacks
= MC_GETCAPAB
| MC_IOCTL
| MC_SETPROP
| MC_PROPINFO
,
62 .mc_getstat
= vmxnet3_getstat
,
63 .mc_start
= vmxnet3_start
,
64 .mc_stop
= vmxnet3_stop
,
65 .mc_setpromisc
= vmxnet3_setpromisc
,
66 .mc_multicst
= vmxnet3_multicst
,
67 .mc_unicst
= vmxnet3_unicst
,
69 .mc_ioctl
= vmxnet3_ioctl
,
70 .mc_getcapab
= vmxnet3_getcapab
,
71 .mc_getprop
= vmxnet3_get_prop
,
72 .mc_setprop
= vmxnet3_set_prop
,
73 .mc_propinfo
= vmxnet3_prop_info
76 /* Tx DMA engine description */
77 static ddi_dma_attr_t vmxnet3_dma_attrs_tx
= {
78 .dma_attr_version
= DMA_ATTR_V0
,
79 .dma_attr_addr_lo
= 0x0000000000000000ull
,
80 .dma_attr_addr_hi
= 0xFFFFFFFFFFFFFFFFull
,
81 .dma_attr_count_max
= 0xFFFFFFFFFFFFFFFFull
,
82 .dma_attr_align
= 0x0000000000000001ull
,
83 .dma_attr_burstsizes
= 0x0000000000000001ull
,
84 .dma_attr_minxfer
= 0x00000001,
85 .dma_attr_maxxfer
= 0x000000000000FFFFull
,
86 .dma_attr_seg
= 0xFFFFFFFFFFFFFFFFull
,
87 .dma_attr_sgllen
= -1,
88 .dma_attr_granular
= 0x00000001,
95 * Fetch the statistics of a vmxnet3 device.
98 * 0 on success, non-zero on failure.
101 vmxnet3_getstat(void *data
, uint_t stat
, uint64_t *val
)
103 vmxnet3_softc_t
*dp
= data
;
104 UPT1_TxStats
*txStats
;
105 UPT1_RxStats
*rxStats
;
107 VMXNET3_DEBUG(dp
, 3, "getstat(%u)\n", stat
);
109 if (!dp
->devEnabled
) {
113 txStats
= &VMXNET3_TQDESC(dp
)->stats
;
114 rxStats
= &VMXNET3_RQDESC(dp
)->stats
;
117 * First touch the related register
120 case MAC_STAT_MULTIRCV
:
121 case MAC_STAT_BRDCSTRCV
:
122 case MAC_STAT_MULTIXMT
:
123 case MAC_STAT_BRDCSTXMT
:
124 case MAC_STAT_NORCVBUF
:
125 case MAC_STAT_IERRORS
:
126 case MAC_STAT_NOXMTBUF
:
127 case MAC_STAT_OERRORS
:
128 case MAC_STAT_RBYTES
:
129 case MAC_STAT_IPACKETS
:
130 case MAC_STAT_OBYTES
:
131 case MAC_STAT_OPACKETS
:
132 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
, VMXNET3_CMD_GET_STATS
);
134 case MAC_STAT_IFSPEED
:
135 case MAC_STAT_COLLISIONS
:
136 case ETHER_STAT_LINK_DUPLEX
:
144 * Then fetch the corresponding stat
147 case MAC_STAT_IFSPEED
:
148 *val
= dp
->linkSpeed
;
150 case MAC_STAT_MULTIRCV
:
151 *val
= rxStats
->mcastPktsRxOK
;
153 case MAC_STAT_BRDCSTRCV
:
154 *val
= rxStats
->bcastPktsRxOK
;
156 case MAC_STAT_MULTIXMT
:
157 *val
= txStats
->mcastPktsTxOK
;
159 case MAC_STAT_BRDCSTXMT
:
160 *val
= txStats
->bcastPktsTxOK
;
162 case MAC_STAT_NORCVBUF
:
163 *val
= rxStats
->pktsRxOutOfBuf
+ dp
->rx_alloc_failed
;
165 case MAC_STAT_IERRORS
:
166 *val
= rxStats
->pktsRxError
;
168 case MAC_STAT_NOXMTBUF
:
169 *val
= txStats
->pktsTxDiscard
+ dp
->tx_pullup_failed
;
171 case MAC_STAT_OERRORS
:
172 *val
= txStats
->pktsTxError
+ dp
->tx_error
;
174 case MAC_STAT_COLLISIONS
:
177 case MAC_STAT_RBYTES
:
178 *val
= rxStats
->ucastBytesRxOK
+ rxStats
->mcastBytesRxOK
+
179 rxStats
->bcastBytesRxOK
;
181 case MAC_STAT_IPACKETS
:
182 *val
= rxStats
->ucastPktsRxOK
+ rxStats
->mcastPktsRxOK
+
183 rxStats
->bcastPktsRxOK
;
185 case MAC_STAT_OBYTES
:
186 *val
= txStats
->ucastBytesTxOK
+ txStats
->mcastBytesTxOK
+
187 txStats
->bcastBytesTxOK
;
189 case MAC_STAT_OPACKETS
:
190 *val
= txStats
->ucastPktsTxOK
+ txStats
->mcastPktsTxOK
+
191 txStats
->bcastPktsTxOK
;
193 case ETHER_STAT_LINK_DUPLEX
:
194 *val
= LINK_DUPLEX_FULL
;
204 * Allocate and initialize the shared data structures of a vmxnet3 device.
207 * 0 on sucess, non-zero on failure.
210 vmxnet3_prepare_drivershared(vmxnet3_softc_t
*dp
)
212 Vmxnet3_DriverShared
*ds
;
213 size_t allocSize
= sizeof (Vmxnet3_DriverShared
);
216 if ((err
= vmxnet3_alloc_dma_mem_1(dp
, &dp
->sharedData
, allocSize
,
221 (void) memset(ds
, 0, allocSize
);
223 allocSize
= sizeof (Vmxnet3_TxQueueDesc
) + sizeof (Vmxnet3_RxQueueDesc
);
224 if ((err
= vmxnet3_alloc_dma_mem_128(dp
, &dp
->queueDescs
, allocSize
,
226 vmxnet3_free_dma_mem(&dp
->sharedData
);
229 (void) memset(dp
->queueDescs
.buf
, 0, allocSize
);
231 ds
->magic
= VMXNET3_REV1_MAGIC
;
233 /* Take care of most of devRead */
234 ds
->devRead
.misc
.driverInfo
.version
= BUILD_NUMBER_NUMERIC
;
236 ds
->devRead
.misc
.driverInfo
.gos
.gosBits
= VMXNET3_GOS_BITS_64
;
238 ds
->devRead
.misc
.driverInfo
.gos
.gosBits
= VMXNET3_GOS_BITS_32
;
240 ds
->devRead
.misc
.driverInfo
.gos
.gosType
= VMXNET3_GOS_TYPE_SOLARIS
;
241 ds
->devRead
.misc
.driverInfo
.gos
.gosVer
= 10;
242 ds
->devRead
.misc
.driverInfo
.vmxnet3RevSpt
= 1;
243 ds
->devRead
.misc
.driverInfo
.uptVerSpt
= 1;
245 ds
->devRead
.misc
.uptFeatures
= UPT1_F_RXCSUM
;
246 ds
->devRead
.misc
.mtu
= dp
->cur_mtu
;
248 /* XXX: ds->devRead.misc.maxNumRxSG */
249 ds
->devRead
.misc
.numTxQueues
= 1;
250 ds
->devRead
.misc
.numRxQueues
= 1;
251 ds
->devRead
.misc
.queueDescPA
= dp
->queueDescs
.bufPA
;
252 ds
->devRead
.misc
.queueDescLen
= allocSize
;
254 /* TxQueue and RxQueue information is filled in other functions */
255 ds
->devRead
.intrConf
.autoMask
= (dp
->intrMaskMode
== VMXNET3_IMM_AUTO
);
256 ds
->devRead
.intrConf
.numIntrs
= 1;
257 /* XXX: ds->intr.modLevels */
258 ds
->devRead
.intrConf
.eventIntrIdx
= 0;
260 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_DSAL
,
261 VMXNET3_ADDR_LO(dp
->sharedData
.bufPA
));
262 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_DSAH
,
263 VMXNET3_ADDR_HI(dp
->sharedData
.bufPA
));
269 * Destroy the shared data structures of a vmxnet3 device.
272 vmxnet3_destroy_drivershared(vmxnet3_softc_t
*dp
)
274 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_DSAL
, 0);
275 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_DSAH
, 0);
277 vmxnet3_free_dma_mem(&dp
->queueDescs
);
278 vmxnet3_free_dma_mem(&dp
->sharedData
);
282 * Allocate and initialize the command ring of a queue.
285 * 0 on success, non-zero on error.
288 vmxnet3_alloc_cmdring(vmxnet3_softc_t
*dp
, vmxnet3_cmdring_t
*cmdRing
)
290 size_t ringSize
= cmdRing
->size
* sizeof (Vmxnet3_TxDesc
);
293 if ((err
= vmxnet3_alloc_dma_mem_512(dp
, &cmdRing
->dma
, ringSize
,
297 (void) memset(cmdRing
->dma
.buf
, 0, ringSize
);
298 cmdRing
->avail
= cmdRing
->size
;
299 cmdRing
->next2fill
= 0;
300 cmdRing
->gen
= VMXNET3_INIT_GEN
;
306 * Allocate and initialize the completion ring of a queue.
309 * DDI_SUCCESS or DDI_FAILURE.
312 vmxnet3_alloc_compring(vmxnet3_softc_t
*dp
, vmxnet3_compring_t
*compRing
)
314 size_t ringSize
= compRing
->size
* sizeof (Vmxnet3_TxCompDesc
);
316 if (vmxnet3_alloc_dma_mem_512(dp
, &compRing
->dma
, ringSize
,
317 B_TRUE
) != DDI_SUCCESS
) {
318 return (DDI_FAILURE
);
320 (void) memset(compRing
->dma
.buf
, 0, ringSize
);
321 compRing
->next2comp
= 0;
322 compRing
->gen
= VMXNET3_INIT_GEN
;
324 return (DDI_SUCCESS
);
328 * Initialize the tx queue of a vmxnet3 device.
331 * 0 on success, non-zero on failure.
334 vmxnet3_prepare_txqueue(vmxnet3_softc_t
*dp
)
336 Vmxnet3_TxQueueDesc
*tqdesc
= VMXNET3_TQDESC(dp
);
337 vmxnet3_txqueue_t
*txq
= &dp
->txQueue
;
340 ASSERT(!(txq
->cmdRing
.size
& VMXNET3_RING_SIZE_MASK
));
341 ASSERT(!(txq
->compRing
.size
& VMXNET3_RING_SIZE_MASK
));
342 ASSERT(!txq
->cmdRing
.dma
.buf
&& !txq
->compRing
.dma
.buf
);
344 if ((err
= vmxnet3_alloc_cmdring(dp
, &txq
->cmdRing
)) != 0) {
347 tqdesc
->conf
.txRingBasePA
= txq
->cmdRing
.dma
.bufPA
;
348 tqdesc
->conf
.txRingSize
= txq
->cmdRing
.size
;
349 tqdesc
->conf
.dataRingBasePA
= 0;
350 tqdesc
->conf
.dataRingSize
= 0;
352 if ((err
= vmxnet3_alloc_compring(dp
, &txq
->compRing
)) != 0) {
355 tqdesc
->conf
.compRingBasePA
= txq
->compRing
.dma
.bufPA
;
356 tqdesc
->conf
.compRingSize
= txq
->compRing
.size
;
358 txq
->metaRing
= kmem_zalloc(txq
->cmdRing
.size
*
359 sizeof (vmxnet3_metatx_t
), KM_SLEEP
);
360 ASSERT(txq
->metaRing
);
362 if ((err
= vmxnet3_txqueue_init(dp
, txq
)) != 0) {
369 kmem_free(txq
->metaRing
, txq
->cmdRing
.size
* sizeof (vmxnet3_metatx_t
));
370 vmxnet3_free_dma_mem(&txq
->compRing
.dma
);
372 vmxnet3_free_dma_mem(&txq
->cmdRing
.dma
);
378 * Initialize the rx queue of a vmxnet3 device.
381 * 0 on success, non-zero on failure.
384 vmxnet3_prepare_rxqueue(vmxnet3_softc_t
*dp
)
386 Vmxnet3_RxQueueDesc
*rqdesc
= VMXNET3_RQDESC(dp
);
387 vmxnet3_rxqueue_t
*rxq
= &dp
->rxQueue
;
390 ASSERT(!(rxq
->cmdRing
.size
& VMXNET3_RING_SIZE_MASK
));
391 ASSERT(!(rxq
->compRing
.size
& VMXNET3_RING_SIZE_MASK
));
392 ASSERT(!rxq
->cmdRing
.dma
.buf
&& !rxq
->compRing
.dma
.buf
);
394 if ((err
= vmxnet3_alloc_cmdring(dp
, &rxq
->cmdRing
)) != 0) {
397 rqdesc
->conf
.rxRingBasePA
[0] = rxq
->cmdRing
.dma
.bufPA
;
398 rqdesc
->conf
.rxRingSize
[0] = rxq
->cmdRing
.size
;
399 rqdesc
->conf
.rxRingBasePA
[1] = 0;
400 rqdesc
->conf
.rxRingSize
[1] = 0;
402 if ((err
= vmxnet3_alloc_compring(dp
, &rxq
->compRing
)) != 0) {
405 rqdesc
->conf
.compRingBasePA
= rxq
->compRing
.dma
.bufPA
;
406 rqdesc
->conf
.compRingSize
= rxq
->compRing
.size
;
408 rxq
->bufRing
= kmem_zalloc(rxq
->cmdRing
.size
*
409 sizeof (vmxnet3_bufdesc_t
), KM_SLEEP
);
410 ASSERT(rxq
->bufRing
);
412 if ((err
= vmxnet3_rxqueue_init(dp
, rxq
)) != 0) {
419 kmem_free(rxq
->bufRing
, rxq
->cmdRing
.size
* sizeof (vmxnet3_bufdesc_t
));
420 vmxnet3_free_dma_mem(&rxq
->compRing
.dma
);
422 vmxnet3_free_dma_mem(&rxq
->cmdRing
.dma
);
428 * Destroy the tx queue of a vmxnet3 device.
431 vmxnet3_destroy_txqueue(vmxnet3_softc_t
*dp
)
433 vmxnet3_txqueue_t
*txq
= &dp
->txQueue
;
435 ASSERT(txq
->metaRing
);
436 ASSERT(txq
->cmdRing
.dma
.buf
&& txq
->compRing
.dma
.buf
);
438 vmxnet3_txqueue_fini(dp
, txq
);
440 kmem_free(txq
->metaRing
, txq
->cmdRing
.size
* sizeof (vmxnet3_metatx_t
));
442 vmxnet3_free_dma_mem(&txq
->cmdRing
.dma
);
443 vmxnet3_free_dma_mem(&txq
->compRing
.dma
);
447 * Destroy the rx queue of a vmxnet3 device.
450 vmxnet3_destroy_rxqueue(vmxnet3_softc_t
*dp
)
452 vmxnet3_rxqueue_t
*rxq
= &dp
->rxQueue
;
454 ASSERT(rxq
->bufRing
);
455 ASSERT(rxq
->cmdRing
.dma
.buf
&& rxq
->compRing
.dma
.buf
);
457 vmxnet3_rxqueue_fini(dp
, rxq
);
459 kmem_free(rxq
->bufRing
, rxq
->cmdRing
.size
* sizeof (vmxnet3_bufdesc_t
));
461 vmxnet3_free_dma_mem(&rxq
->cmdRing
.dma
);
462 vmxnet3_free_dma_mem(&rxq
->compRing
.dma
);
466 * Apply new RX filters settings to a vmxnet3 device.
469 vmxnet3_refresh_rxfilter(vmxnet3_softc_t
*dp
)
471 Vmxnet3_DriverShared
*ds
= VMXNET3_DS(dp
);
473 ds
->devRead
.rxFilterConf
.rxMode
= dp
->rxMode
;
474 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
, VMXNET3_CMD_UPDATE_RX_MODE
);
478 * Fetch the link state of a vmxnet3 device.
481 vmxnet3_refresh_linkstate(vmxnet3_softc_t
*dp
)
485 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
, VMXNET3_CMD_GET_LINK
);
486 ret32
= VMXNET3_BAR1_GET32(dp
, VMXNET3_REG_CMD
);
488 dp
->linkState
= LINK_STATE_UP
;
489 dp
->linkSpeed
= (ret32
>> 16) * 1000000ULL;
491 dp
->linkState
= LINK_STATE_DOWN
;
497 * Start a vmxnet3 device: allocate and initialize the shared data
498 * structures and send a start command to the device.
501 * 0 on success, non-zero error on failure.
504 vmxnet3_start(void *data
)
506 vmxnet3_softc_t
*dp
= data
;
507 Vmxnet3_TxQueueDesc
*tqdesc
;
508 Vmxnet3_RxQueueDesc
*rqdesc
;
509 int txQueueSize
, rxQueueSize
;
513 VMXNET3_DEBUG(dp
, 1, "start()\n");
516 * Allocate vmxnet3's shared data and advertise its PA
518 if ((err
= vmxnet3_prepare_drivershared(dp
)) != 0) {
519 VMXNET3_WARN(dp
, "vmxnet3_prepare_drivershared() failed: %d",
523 tqdesc
= VMXNET3_TQDESC(dp
);
524 rqdesc
= VMXNET3_RQDESC(dp
);
527 * Create and initialize the tx queue
529 txQueueSize
= vmxnet3_getprop(dp
, "TxRingSize", 32, 4096,
530 VMXNET3_DEF_TX_RING_SIZE
);
531 if (!(txQueueSize
& VMXNET3_RING_SIZE_MASK
)) {
532 dp
->txQueue
.cmdRing
.size
= txQueueSize
;
533 dp
->txQueue
.compRing
.size
= txQueueSize
;
534 dp
->txQueue
.sharedCtrl
= &tqdesc
->ctrl
;
535 if ((err
= vmxnet3_prepare_txqueue(dp
)) != 0) {
536 VMXNET3_WARN(dp
, "vmxnet3_prepare_txqueue() failed: %d",
538 goto error_shared_data
;
541 VMXNET3_WARN(dp
, "invalid tx ring size (%d)\n", txQueueSize
);
543 goto error_shared_data
;
547 * Create and initialize the rx queue
549 rxQueueSize
= vmxnet3_getprop(dp
, "RxRingSize", 32, 4096,
550 VMXNET3_DEF_RX_RING_SIZE
);
551 if (!(rxQueueSize
& VMXNET3_RING_SIZE_MASK
)) {
552 dp
->rxQueue
.cmdRing
.size
= rxQueueSize
;
553 dp
->rxQueue
.compRing
.size
= rxQueueSize
;
554 dp
->rxQueue
.sharedCtrl
= &rqdesc
->ctrl
;
555 if ((err
= vmxnet3_prepare_rxqueue(dp
)) != 0) {
556 VMXNET3_WARN(dp
, "vmxnet3_prepare_rxqueue() failed: %d",
561 VMXNET3_WARN(dp
, "invalid rx ring size (%d)\n", rxQueueSize
);
567 * Allocate the Tx DMA handle
569 if ((dmaerr
= ddi_dma_alloc_handle(dp
->dip
, &vmxnet3_dma_attrs_tx
,
570 DDI_DMA_SLEEP
, NULL
, &dp
->txDmaHandle
)) != DDI_SUCCESS
) {
571 VMXNET3_WARN(dp
, "ddi_dma_alloc_handle() failed: %d", dmaerr
);
572 err
= vmxnet3_dmaerr2errno(dmaerr
);
577 * Activate the device
579 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
, VMXNET3_CMD_ACTIVATE_DEV
);
580 ret32
= VMXNET3_BAR1_GET32(dp
, VMXNET3_REG_CMD
);
582 VMXNET3_WARN(dp
, "ACTIVATE_DEV failed: 0x%x\n", ret32
);
586 dp
->devEnabled
= B_TRUE
;
588 VMXNET3_BAR0_PUT32(dp
, VMXNET3_REG_RXPROD
,
589 dp
->txQueue
.cmdRing
.size
- 1);
592 * Update the RX filters, must be done after ACTIVATE_DEV
594 dp
->rxMode
= VMXNET3_RXM_UCAST
| VMXNET3_RXM_BCAST
;
595 vmxnet3_refresh_rxfilter(dp
);
598 * Get the link state now because no events will be generated
600 vmxnet3_refresh_linkstate(dp
);
601 mac_link_update(dp
->mac
, dp
->linkState
);
604 * Finally, unmask the interrupt
606 VMXNET3_BAR0_PUT32(dp
, VMXNET3_REG_IMR
, 0);
611 ddi_dma_free_handle(&dp
->txDmaHandle
);
613 vmxnet3_destroy_rxqueue(dp
);
615 vmxnet3_destroy_txqueue(dp
);
617 vmxnet3_destroy_drivershared(dp
);
623 * Stop a vmxnet3 device: send a stop command to the device and
624 * de-allocate the shared data structures.
627 vmxnet3_stop(void *data
)
629 vmxnet3_softc_t
*dp
= data
;
631 VMXNET3_DEBUG(dp
, 1, "stop()\n");
634 * Take the 2 locks related to asynchronous events.
635 * These events should always check dp->devEnabled before poking dp.
637 mutex_enter(&dp
->intrLock
);
638 mutex_enter(&dp
->rxPoolLock
);
639 VMXNET3_BAR0_PUT32(dp
, VMXNET3_REG_IMR
, 1);
640 dp
->devEnabled
= B_FALSE
;
641 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
, VMXNET3_CMD_QUIESCE_DEV
);
642 mutex_exit(&dp
->rxPoolLock
);
643 mutex_exit(&dp
->intrLock
);
645 ddi_dma_free_handle(&dp
->txDmaHandle
);
647 vmxnet3_destroy_rxqueue(dp
);
648 vmxnet3_destroy_txqueue(dp
);
650 vmxnet3_destroy_drivershared(dp
);
654 * Set or unset promiscuous mode on a vmxnet3 device.
657 vmxnet3_setpromisc(void *data
, boolean_t promisc
)
659 vmxnet3_softc_t
*dp
= data
;
661 VMXNET3_DEBUG(dp
, 2, "setpromisc(%s)\n", promisc
? "TRUE" : "FALSE");
664 dp
->rxMode
|= VMXNET3_RXM_PROMISC
;
666 dp
->rxMode
&= ~VMXNET3_RXM_PROMISC
;
669 vmxnet3_refresh_rxfilter(dp
);
675 * Add or remove a multicast address from/to a vmxnet3 device.
678 * 0 on success, non-zero on failure.
681 vmxnet3_multicst(void *data
, boolean_t add
, const uint8_t *macaddr
)
683 vmxnet3_softc_t
*dp
= data
;
684 vmxnet3_dmabuf_t newMfTable
;
689 VMXNET3_DEBUG(dp
, 2, "multicst(%s, "MACADDR_FMT
")\n",
690 add
? "add" : "remove", MACADDR_FMT_ARGS(macaddr
));
693 * First lookup the position of the given MAC to check if it is
694 * present in the existing MF table.
696 for (macIdx
= 0; macIdx
< dp
->mfTable
.bufLen
; macIdx
+= 6) {
697 if (memcmp(&dp
->mfTable
.buf
[macIdx
], macaddr
, 6) == 0) {
703 * Check for 2 situations we can handle gracefully by bailing out:
704 * Adding an already existing filter or removing a non-existing one.
706 if (add
&& macIdx
< dp
->mfTable
.bufLen
) {
707 VMXNET3_WARN(dp
, MACADDR_FMT
" already in MC filter list "
708 "@ %u\n", MACADDR_FMT_ARGS(macaddr
), macIdx
/ 6);
712 if (!add
&& macIdx
== dp
->mfTable
.bufLen
) {
713 VMXNET3_WARN(dp
, MACADDR_FMT
" not in MC filter list @ %u\n",
714 MACADDR_FMT_ARGS(macaddr
), macIdx
/ 6);
720 * Create the new MF table
722 allocSize
= dp
->mfTable
.bufLen
+ (add
? 6 : -6);
724 ret
= vmxnet3_alloc_dma_mem_1(dp
, &newMfTable
, allocSize
,
728 (void) memcpy(newMfTable
.buf
, dp
->mfTable
.buf
,
730 (void) memcpy(newMfTable
.buf
+ dp
->mfTable
.bufLen
,
733 (void) memcpy(newMfTable
.buf
, dp
->mfTable
.buf
,
735 (void) memcpy(newMfTable
.buf
+ macIdx
,
736 dp
->mfTable
.buf
+ macIdx
+ 6,
737 dp
->mfTable
.bufLen
- macIdx
- 6);
740 newMfTable
.buf
= NULL
;
741 newMfTable
.bufPA
= 0;
742 newMfTable
.bufLen
= 0;
746 * Now handle 2 corner cases: if we're creating the first filter or
747 * removing the last one, we have to update rxMode accordingly.
749 if (add
&& newMfTable
.bufLen
== 6) {
750 ASSERT(!(dp
->rxMode
& VMXNET3_RXM_MCAST
));
751 dp
->rxMode
|= VMXNET3_RXM_MCAST
;
752 vmxnet3_refresh_rxfilter(dp
);
754 if (!add
&& dp
->mfTable
.bufLen
== 6) {
755 ASSERT(newMfTable
.buf
== NULL
);
756 ASSERT(dp
->rxMode
& VMXNET3_RXM_MCAST
);
757 dp
->rxMode
&= ~VMXNET3_RXM_MCAST
;
758 vmxnet3_refresh_rxfilter(dp
);
762 * Now replace the old MF table with the new one
764 if (dp
->mfTable
.buf
) {
765 vmxnet3_free_dma_mem(&dp
->mfTable
);
767 dp
->mfTable
= newMfTable
;
768 VMXNET3_DS(dp
)->devRead
.rxFilterConf
.mfTablePA
= newMfTable
.bufPA
;
769 VMXNET3_DS(dp
)->devRead
.rxFilterConf
.mfTableLen
= newMfTable
.bufLen
;
772 /* Always update the filters */
773 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
, VMXNET3_CMD_UPDATE_MAC_FILTERS
);
779 * Set the mac address of a vmxnet3 device.
785 vmxnet3_unicst(void *data
, const uint8_t *macaddr
)
787 vmxnet3_softc_t
*dp
= data
;
790 VMXNET3_DEBUG(dp
, 2, "unicst("MACADDR_FMT
")\n",
791 MACADDR_FMT_ARGS(macaddr
));
793 val32
= *((uint32_t *)(macaddr
+ 0));
794 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_MACL
, val32
);
795 val32
= *((uint16_t *)(macaddr
+ 4));
796 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_MACH
, val32
);
798 (void) memcpy(dp
->macaddr
, macaddr
, 6);
804 * Change the MTU as seen by the driver. This is only supported when
805 * the mac is stopped.
808 * EBUSY if the device is enabled.
809 * EINVAL for invalid MTU values.
813 vmxnet3_change_mtu(vmxnet3_softc_t
*dp
, uint32_t new_mtu
)
820 if (new_mtu
== dp
->cur_mtu
) {
821 VMXNET3_WARN(dp
, "New MTU is same as old mtu : %d.\n", new_mtu
);
825 if (new_mtu
< VMXNET3_MIN_MTU
|| new_mtu
> VMXNET3_MAX_MTU
) {
826 VMXNET3_WARN(dp
, "New MTU not in valid range [%d, %d].\n",
827 VMXNET3_MIN_MTU
, VMXNET3_MAX_MTU
);
829 } else if (new_mtu
> ETHERMTU
&& !dp
->allow_jumbo
) {
830 VMXNET3_WARN(dp
, "MTU cannot be greater than %d because "
831 "accept-jumbo is not enabled.\n", ETHERMTU
);
835 dp
->cur_mtu
= new_mtu
;
836 dp
->alloc_ok
= VMXNET3_ALLOC_OK(dp
);
838 if ((ret
= mac_maxsdu_update(dp
->mac
, new_mtu
)) != 0)
839 VMXNET3_WARN(dp
, "Unable to update mac with %d mtu: %d",
847 vmxnet3_get_prop(void *data
, const char *prop_name
, mac_prop_id_t prop_id
,
848 uint_t prop_val_size
, void *prop_val
)
850 vmxnet3_softc_t
*dp
= data
;
855 ASSERT(prop_val_size
>= sizeof (uint32_t));
856 bcopy(&dp
->cur_mtu
, prop_val
, sizeof (uint32_t));
867 vmxnet3_set_prop(void *data
, const char *prop_name
, mac_prop_id_t prop_id
,
868 uint_t prop_val_size
, const void *prop_val
)
870 vmxnet3_softc_t
*dp
= data
;
876 ASSERT(prop_val_size
>= sizeof (uint32_t));
877 bcopy(prop_val
, &new_mtu
, sizeof (new_mtu
));
878 ret
= vmxnet3_change_mtu(dp
, new_mtu
);
891 vmxnet3_prop_info(void *data
, const char *prop_name
, mac_prop_id_t prop_id
,
892 mac_prop_info_handle_t prop_handle
)
896 mac_prop_info_set_range_uint32(prop_handle
, VMXNET3_MIN_MTU
,
905 * DDI/DDK callback to handle IOCTL in driver. Currently it only handles
906 * ND_SET ioctl. Rest all are ignored. The ND_SET is used to set/reset
907 * accept-jumbo ndd parameted for the interface.
910 * MTU can be changed and device can be reset. An ACK or NACK is conveyed
911 * to the calling function from the mblk which was used to call this
915 vmxnet3_ioctl(void *arg
, queue_t
*wq
, mblk_t
*mp
)
917 vmxnet3_softc_t
*dp
= arg
;
924 iocp
= (void *)mp
->b_rptr
;
927 switch (iocp
->ioc_cmd
) {
930 * The mblk in continuation would contain the ndd parameter name
931 * and data value to be set
935 VMXNET3_WARN(dp
, "Error locating parameter name.\n");
940 /* Force null termination */
941 mp1
->b_datap
->db_lim
[-1] = '\0';
944 * From kernel/net/nd.c : nd_getset()
945 * "logic throughout nd_xxx assumes single data block for ioctl.
946 * However, existing code sends in some big buffers."
949 freemsg(mp1
->b_cont
);
953 valp
= (char *)mp1
->b_rptr
; /* Points to param name */
956 VMXNET3_DEBUG(dp
, 3, "ND Set ioctl for %s\n", param
);
959 * Go past the end of this null terminated string to get the
962 while (*valp
&& valp
<= (char *)mp1
->b_wptr
)
965 if (valp
> (char *)mp1
->b_wptr
) {
967 * We are already beyond the readable area of mblk and
968 * still haven't found the end of param string.
971 "No data value found to be set to param\n");
974 /* Now this points to data string */
976 /* Get numeric value of first letter */
977 data
= (int)*valp
- (int)'0';
980 if (strcmp("accept-jumbo", param
) == 0) {
983 "Accepting jumbo frames\n");
984 dp
->allow_jumbo
= B_TRUE
;
985 ret
= vmxnet3_change_mtu(dp
, VMXNET3_MAX_MTU
);
986 } else if (data
== 0) {
988 "Rejecting jumbo frames\n");
989 dp
->allow_jumbo
= B_FALSE
;
990 ret
= vmxnet3_change_mtu(dp
, ETHERMTU
);
992 VMXNET3_WARN(dp
, "Invalid data value to be set,"
1003 freemsg(mp
->b_cont
);
1011 miocack(wq
, mp
, 0, 0);
1013 miocnak(wq
, mp
, 0, EINVAL
);
1017 * Get the capabilities of a vmxnet3 device.
1020 * B_TRUE if the capability is supported, B_FALSE otherwise.
1023 vmxnet3_getcapab(void *data
, mac_capab_t capab
, void *arg
)
1025 vmxnet3_softc_t
*dp
= data
;
1029 case MAC_CAPAB_HCKSUM
: {
1030 uint32_t *txflags
= arg
;
1031 *txflags
= HCKSUM_INET_PARTIAL
;
1035 case MAC_CAPAB_LSO
: {
1036 mac_capab_lso_t
*lso
= arg
;
1037 lso
->lso_flags
= LSO_TX_BASIC_TCP_IPV4
;
1038 lso
->lso_basic_tcp_ipv4
.lso_max
= IP_MAXPACKET
;
1039 ret
= vmxnet3_getprop(dp
, "EnableLSO", 0, 1, 1);
1046 VMXNET3_DEBUG(dp
, 2, "getcapab(0x%x) -> %s\n", capab
,
1047 ret
? "yes" : "no");
1053 * Reset a vmxnet3 device. Only to be used when the device is wedged.
1056 * The device is reset.
1059 vmxnet3_reset(void *data
)
1063 vmxnet3_softc_t
*dp
= data
;
1065 VMXNET3_DEBUG(dp
, 1, "vmxnet3_reset()\n");
1067 atomic_inc_32(&dp
->reset_count
);
1069 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
, VMXNET3_CMD_RESET_DEV
);
1070 if ((ret
= vmxnet3_start(dp
)) != 0)
1071 VMXNET3_WARN(dp
, "failed to reset the device: %d", ret
);
1075 * Process pending events on a vmxnet3 device.
1078 * B_TRUE if the link state changed, B_FALSE otherwise.
1081 vmxnet3_intr_events(vmxnet3_softc_t
*dp
)
1083 Vmxnet3_DriverShared
*ds
= VMXNET3_DS(dp
);
1084 boolean_t linkStateChanged
= B_FALSE
;
1085 uint32_t events
= ds
->ecr
;
1088 VMXNET3_DEBUG(dp
, 2, "events(0x%x)\n", events
);
1089 if (events
& (VMXNET3_ECR_RQERR
| VMXNET3_ECR_TQERR
)) {
1090 Vmxnet3_TxQueueDesc
*tqdesc
= VMXNET3_TQDESC(dp
);
1091 Vmxnet3_RxQueueDesc
*rqdesc
= VMXNET3_RQDESC(dp
);
1093 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
,
1094 VMXNET3_CMD_GET_QUEUE_STATUS
);
1095 if (tqdesc
->status
.stopped
) {
1096 VMXNET3_WARN(dp
, "tq error 0x%x\n",
1097 tqdesc
->status
.error
);
1099 if (rqdesc
->status
.stopped
) {
1100 VMXNET3_WARN(dp
, "rq error 0x%x\n",
1101 rqdesc
->status
.error
);
1104 if (ddi_taskq_dispatch(dp
->resetTask
, vmxnet3_reset
,
1105 dp
, DDI_NOSLEEP
) == DDI_SUCCESS
) {
1106 VMXNET3_WARN(dp
, "reset scheduled\n");
1109 "ddi_taskq_dispatch() failed\n");
1112 if (events
& VMXNET3_ECR_LINK
) {
1113 vmxnet3_refresh_linkstate(dp
);
1114 linkStateChanged
= B_TRUE
;
1116 if (events
& VMXNET3_ECR_DIC
) {
1117 VMXNET3_DEBUG(dp
, 1, "device implementation change\n");
1119 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_ECR
, events
);
1122 return (linkStateChanged
);
1126 * Interrupt handler of a vmxnet3 device.
1129 * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED.
1133 vmxnet3_intr(caddr_t data1
, caddr_t data2
)
1135 vmxnet3_softc_t
*dp
= (void *) data1
;
1137 VMXNET3_DEBUG(dp
, 3, "intr()\n");
1139 mutex_enter(&dp
->intrLock
);
1141 if (dp
->devEnabled
) {
1142 boolean_t linkStateChanged
;
1143 boolean_t mustUpdateTx
;
1146 if (dp
->intrType
== DDI_INTR_TYPE_FIXED
&&
1147 !VMXNET3_BAR1_GET32(dp
, VMXNET3_REG_ICR
)) {
1148 goto intr_unclaimed
;
1151 if (dp
->intrMaskMode
== VMXNET3_IMM_ACTIVE
) {
1152 VMXNET3_BAR0_PUT32(dp
, VMXNET3_REG_IMR
, 1);
1155 linkStateChanged
= vmxnet3_intr_events(dp
);
1156 mustUpdateTx
= vmxnet3_tx_complete(dp
, &dp
->txQueue
);
1157 mps
= vmxnet3_rx_intr(dp
, &dp
->rxQueue
);
1159 mutex_exit(&dp
->intrLock
);
1160 VMXNET3_BAR0_PUT32(dp
, VMXNET3_REG_IMR
, 0);
1162 if (linkStateChanged
) {
1163 mac_link_update(dp
->mac
, dp
->linkState
);
1166 mac_tx_update(dp
->mac
);
1169 mac_rx(dp
->mac
, NULL
, mps
);
1172 return (DDI_INTR_CLAIMED
);
1176 mutex_exit(&dp
->intrLock
);
1177 return (DDI_INTR_UNCLAIMED
);
1181 vmxnet3_kstat_update(kstat_t
*ksp
, int rw
)
1183 vmxnet3_softc_t
*dp
= ksp
->ks_private
;
1184 vmxnet3_kstats_t
*statp
= ksp
->ks_data
;
1186 if (rw
== KSTAT_WRITE
)
1189 statp
->reset_count
.value
.ul
= dp
->reset_count
;
1190 statp
->tx_pullup_needed
.value
.ul
= dp
->tx_pullup_needed
;
1191 statp
->tx_ring_full
.value
.ul
= dp
->tx_ring_full
;
1192 statp
->rx_alloc_buf
.value
.ul
= dp
->rx_alloc_buf
;
1193 statp
->rx_pool_empty
.value
.ul
= dp
->rx_pool_empty
;
1194 statp
->rx_num_bufs
.value
.ul
= dp
->rx_num_bufs
;
1200 vmxnet3_kstat_init(vmxnet3_softc_t
*dp
)
1202 vmxnet3_kstats_t
*statp
;
1204 dp
->devKstats
= kstat_create(VMXNET3_MODNAME
, dp
->instance
,
1205 "statistics", "dev", KSTAT_TYPE_NAMED
,
1206 sizeof (vmxnet3_kstats_t
) / sizeof (kstat_named_t
), 0);
1207 if (dp
->devKstats
== NULL
)
1208 return (DDI_FAILURE
);
1210 dp
->devKstats
->ks_update
= vmxnet3_kstat_update
;
1211 dp
->devKstats
->ks_private
= dp
;
1213 statp
= dp
->devKstats
->ks_data
;
1215 kstat_named_init(&statp
->reset_count
, "reset_count", KSTAT_DATA_ULONG
);
1216 kstat_named_init(&statp
->tx_pullup_needed
, "tx_pullup_needed",
1218 kstat_named_init(&statp
->tx_ring_full
, "tx_ring_full",
1220 kstat_named_init(&statp
->rx_alloc_buf
, "rx_alloc_buf",
1222 kstat_named_init(&statp
->rx_pool_empty
, "rx_pool_empty",
1224 kstat_named_init(&statp
->rx_num_bufs
, "rx_num_bufs",
1227 kstat_install(dp
->devKstats
);
1229 return (DDI_SUCCESS
);
1233 * Probe and attach a vmxnet3 instance to the stack.
1236 * DDI_SUCCESS or DDI_FAILURE.
1239 vmxnet3_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
1241 vmxnet3_softc_t
*dp
;
1242 mac_register_t
*macr
;
1243 uint16_t vendorId
, devId
, ret16
;
1248 if (cmd
!= DDI_ATTACH
) {
1253 * Allocate the soft state
1255 dp
= kmem_zalloc(sizeof (vmxnet3_softc_t
), KM_SLEEP
);
1259 dp
->instance
= ddi_get_instance(dip
);
1260 dp
->cur_mtu
= ETHERMTU
;
1261 dp
->allow_jumbo
= B_TRUE
;
1262 dp
->alloc_ok
= VMXNET3_ALLOC_OK(dp
);
1264 VMXNET3_DEBUG(dp
, 1, "attach()\n");
1266 ddi_set_driver_private(dip
, dp
);
1269 * Get access to the PCI bus configuration space
1271 if (pci_config_setup(dip
, &dp
->pciHandle
) != DDI_SUCCESS
) {
1272 VMXNET3_WARN(dp
, "pci_config_setup() failed\n");
1273 goto error_soft_state
;
1277 * Make sure the chip is a vmxnet3 device
1279 vendorId
= pci_config_get16(dp
->pciHandle
, PCI_CONF_VENID
);
1280 devId
= pci_config_get16(dp
->pciHandle
, PCI_CONF_DEVID
);
1281 if (vendorId
!= PCI_VENDOR_ID_VMWARE
||
1282 devId
!= PCI_DEVICE_ID_VMWARE_VMXNET3
) {
1283 VMXNET3_WARN(dp
, "wrong PCI venid/devid (0x%x, 0x%x)\n",
1285 goto error_pci_config
;
1289 * Make sure we can access the registers through the I/O space
1291 ret16
= pci_config_get16(dp
->pciHandle
, PCI_CONF_COMM
);
1292 ret16
|= PCI_COMM_IO
| PCI_COMM_ME
;
1293 pci_config_put16(dp
->pciHandle
, PCI_CONF_COMM
, ret16
);
1296 * Map the I/O space in memory
1298 if (ddi_regs_map_setup(dip
, 1, &dp
->bar0
, 0, 0, &vmxnet3_dev_attr
,
1299 &dp
->bar0Handle
) != DDI_SUCCESS
) {
1300 VMXNET3_WARN(dp
, "ddi_regs_map_setup() for BAR0 failed\n");
1301 goto error_pci_config
;
1304 if (ddi_regs_map_setup(dip
, 2, &dp
->bar1
, 0, 0, &vmxnet3_dev_attr
,
1305 &dp
->bar1Handle
) != DDI_SUCCESS
) {
1306 VMXNET3_WARN(dp
, "ddi_regs_map_setup() for BAR1 failed\n");
1307 goto error_regs_map_0
;
1311 * Check the version number of the virtual device
1313 if (VMXNET3_BAR1_GET32(dp
, VMXNET3_REG_VRRS
) & 1) {
1314 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_VRRS
, 1);
1316 VMXNET3_WARN(dp
, "incompatible h/w version\n");
1317 goto error_regs_map_1
;
1320 if (VMXNET3_BAR1_GET32(dp
, VMXNET3_REG_UVRS
) & 1) {
1321 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_UVRS
, 1);
1323 VMXNET3_WARN(dp
, "incompatible upt version\n");
1324 goto error_regs_map_1
;
1327 if (vmxnet3_kstat_init(dp
) != DDI_SUCCESS
) {
1328 VMXNET3_WARN(dp
, "unable to initialize kstats");
1329 goto error_regs_map_1
;
1333 * Read the MAC address from the device
1335 ret32
= VMXNET3_BAR1_GET32(dp
, VMXNET3_REG_MACL
);
1336 *((uint32_t *)(dp
->macaddr
+ 0)) = ret32
;
1337 ret32
= VMXNET3_BAR1_GET32(dp
, VMXNET3_REG_MACH
);
1338 *((uint16_t *)(dp
->macaddr
+ 4)) = ret32
;
1341 * Register with the MAC framework
1343 if (!(macr
= mac_alloc(MAC_VERSION
))) {
1344 VMXNET3_WARN(dp
, "mac_alloc() failed\n");
1348 macr
->m_type_ident
= MAC_PLUGIN_IDENT_ETHER
;
1349 macr
->m_driver
= dp
;
1351 macr
->m_instance
= 0;
1352 macr
->m_src_addr
= dp
->macaddr
;
1353 macr
->m_dst_addr
= NULL
;
1354 macr
->m_callbacks
= &vmxnet3_mac_callbacks
;
1355 macr
->m_min_sdu
= 0;
1356 macr
->m_max_sdu
= ETHERMTU
;
1357 macr
->m_margin
= VLAN_TAGSZ
;
1358 macr
->m_pdata
= NULL
;
1359 macr
->m_pdata_size
= 0;
1361 ret
= mac_register(macr
, &dp
->mac
);
1363 if (ret
!= DDI_SUCCESS
) {
1364 VMXNET3_WARN(dp
, "mac_register() failed\n");
1369 * Register the interrupt(s) in this order of preference:
1372 VMXNET3_BAR1_PUT32(dp
, VMXNET3_REG_CMD
, VMXNET3_CMD_GET_CONF_INTR
);
1373 ret32
= VMXNET3_BAR1_GET32(dp
, VMXNET3_REG_CMD
);
1374 switch (ret32
& 0x3) {
1375 case VMXNET3_IT_AUTO
:
1376 case VMXNET3_IT_MSIX
:
1377 dp
->intrType
= DDI_INTR_TYPE_MSIX
;
1378 err
= ddi_intr_alloc(dip
, &dp
->intrHandle
, dp
->intrType
, 0, 1,
1379 &ret
, DDI_INTR_ALLOC_STRICT
);
1380 if (err
== DDI_SUCCESS
)
1382 VMXNET3_DEBUG(dp
, 2, "DDI_INTR_TYPE_MSIX failed, err:%d\n",
1385 case VMXNET3_IT_MSI
:
1386 dp
->intrType
= DDI_INTR_TYPE_MSI
;
1387 if (ddi_intr_alloc(dip
, &dp
->intrHandle
, dp
->intrType
, 0, 1,
1388 &ret
, DDI_INTR_ALLOC_STRICT
) == DDI_SUCCESS
)
1390 VMXNET3_DEBUG(dp
, 2, "DDI_INTR_TYPE_MSI failed\n");
1392 case VMXNET3_IT_INTX
:
1393 dp
->intrType
= DDI_INTR_TYPE_FIXED
;
1394 if (ddi_intr_alloc(dip
, &dp
->intrHandle
, dp
->intrType
, 0, 1,
1395 &ret
, DDI_INTR_ALLOC_STRICT
) == DDI_SUCCESS
) {
1398 VMXNET3_DEBUG(dp
, 2, "DDI_INTR_TYPE_INTX failed\n");
1401 VMXNET3_WARN(dp
, "ddi_intr_alloc() failed\n");
1404 dp
->intrMaskMode
= (ret32
>> 2) & 0x3;
1405 if (dp
->intrMaskMode
== VMXNET3_IMM_LAZY
) {
1406 VMXNET3_WARN(dp
, "Lazy masking is not supported\n");
1410 if (ddi_intr_get_pri(dp
->intrHandle
, &uret
) != DDI_SUCCESS
) {
1411 VMXNET3_WARN(dp
, "ddi_intr_get_pri() failed\n");
1415 VMXNET3_DEBUG(dp
, 2, "intrType=0x%x, intrMaskMode=0x%x, intrPrio=%u\n",
1416 dp
->intrType
, dp
->intrMaskMode
, uret
);
1419 * Create a task queue to reset the device if it wedges.
1421 dp
->resetTask
= ddi_taskq_create(dip
, "vmxnet3_reset_task", 1,
1422 TASKQ_DEFAULTPRI
, 0);
1423 if (!dp
->resetTask
) {
1424 VMXNET3_WARN(dp
, "ddi_taskq_create() failed()\n");
1429 * Initialize our mutexes now that we know the interrupt priority
1430 * This _must_ be done before ddi_intr_enable()
1432 mutex_init(&dp
->intrLock
, NULL
, MUTEX_DRIVER
, DDI_INTR_PRI(uret
));
1433 mutex_init(&dp
->txLock
, NULL
, MUTEX_DRIVER
, DDI_INTR_PRI(uret
));
1434 mutex_init(&dp
->rxPoolLock
, NULL
, MUTEX_DRIVER
, DDI_INTR_PRI(uret
));
1436 if (ddi_intr_add_handler(dp
->intrHandle
, vmxnet3_intr
,
1437 dp
, NULL
) != DDI_SUCCESS
) {
1438 VMXNET3_WARN(dp
, "ddi_intr_add_handler() failed\n");
1442 err
= ddi_intr_get_cap(dp
->intrHandle
, &dp
->intrCap
);
1443 if (err
!= DDI_SUCCESS
) {
1444 VMXNET3_WARN(dp
, "ddi_intr_get_cap() failed %d", err
);
1445 goto error_intr_handler
;
1448 if (dp
->intrCap
& DDI_INTR_FLAG_BLOCK
) {
1449 err
= ddi_intr_block_enable(&dp
->intrHandle
, 1);
1450 if (err
!= DDI_SUCCESS
) {
1451 VMXNET3_WARN(dp
, "ddi_intr_block_enable() failed, "
1453 goto error_intr_handler
;
1456 err
= ddi_intr_enable(dp
->intrHandle
);
1457 if ((err
!= DDI_SUCCESS
)) {
1458 VMXNET3_WARN(dp
, "ddi_intr_enable() failed, err:%d\n",
1460 goto error_intr_handler
;
1464 return (DDI_SUCCESS
);
1467 (void) ddi_intr_remove_handler(dp
->intrHandle
);
1469 mutex_destroy(&dp
->rxPoolLock
);
1470 mutex_destroy(&dp
->txLock
);
1471 mutex_destroy(&dp
->intrLock
);
1472 ddi_taskq_destroy(dp
->resetTask
);
1474 (void) ddi_intr_free(dp
->intrHandle
);
1476 (void) mac_unregister(dp
->mac
);
1478 kstat_delete(dp
->devKstats
);
1480 ddi_regs_map_free(&dp
->bar1Handle
);
1482 ddi_regs_map_free(&dp
->bar0Handle
);
1484 pci_config_teardown(&dp
->pciHandle
);
1486 kmem_free(dp
, sizeof (vmxnet3_softc_t
));
1488 return (DDI_FAILURE
);
1492 * Detach a vmxnet3 instance from the stack.
1495 * DDI_SUCCESS or DDI_FAILURE.
1498 vmxnet3_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
1500 vmxnet3_softc_t
*dp
= ddi_get_driver_private(dip
);
1501 unsigned int retries
= 0;
1504 VMXNET3_DEBUG(dp
, 1, "detach()\n");
1506 if (cmd
!= DDI_DETACH
) {
1507 return (DDI_FAILURE
);
1510 while (dp
->rx_num_bufs
> 0) {
1511 if (retries
++ < 10) {
1512 VMXNET3_WARN(dp
, "rx pending (%u), waiting 1 second\n",
1516 VMXNET3_WARN(dp
, "giving up\n");
1517 return (DDI_FAILURE
);
1521 if (dp
->intrCap
& DDI_INTR_FLAG_BLOCK
) {
1522 ret
= ddi_intr_block_disable(&dp
->intrHandle
, 1);
1524 ret
= ddi_intr_disable(dp
->intrHandle
);
1526 if (ret
!= DDI_SUCCESS
) {
1527 VMXNET3_WARN(dp
, "unable to disable interrupts");
1528 return (DDI_FAILURE
);
1530 if (ddi_intr_remove_handler(dp
->intrHandle
) != DDI_SUCCESS
) {
1531 VMXNET3_WARN(dp
, "unable to remove interrupt handler");
1532 return (DDI_FAILURE
);
1534 (void) ddi_intr_free(dp
->intrHandle
);
1536 VERIFY(mac_unregister(dp
->mac
) == 0);
1538 kstat_delete(dp
->devKstats
);
1540 if (dp
->mfTable
.buf
) {
1541 vmxnet3_free_dma_mem(&dp
->mfTable
);
1544 mutex_destroy(&dp
->rxPoolLock
);
1545 mutex_destroy(&dp
->txLock
);
1546 mutex_destroy(&dp
->intrLock
);
1547 ddi_taskq_destroy(dp
->resetTask
);
1549 ddi_regs_map_free(&dp
->bar1Handle
);
1550 ddi_regs_map_free(&dp
->bar0Handle
);
1551 pci_config_teardown(&dp
->pciHandle
);
1553 kmem_free(dp
, sizeof (vmxnet3_softc_t
));
1555 return (DDI_SUCCESS
);
1559 * Structures used by the module loader
1562 #define VMXNET3_IDENT "VMware Ethernet v3 " VMXNET3_DRIVER_VERSION_STRING
1564 DDI_DEFINE_STREAM_OPS(
1574 ddi_quiesce_not_supported
);
1576 static struct modldrv vmxnet3_modldrv
= {
1577 &mod_driverops
, /* drv_modops */
1578 VMXNET3_IDENT
, /* drv_linkinfo */
1579 &vmxnet3_dev_ops
/* drv_dev_ops */
1582 static struct modlinkage vmxnet3_modlinkage
= {
1583 MODREV_1
, /* ml_rev */
1584 { &vmxnet3_modldrv
, NULL
} /* ml_linkage */
1587 /* Module load entry point */
1593 mac_init_ops(&vmxnet3_dev_ops
, VMXNET3_MODNAME
);
1594 ret
= mod_install(&vmxnet3_modlinkage
);
1595 if (ret
!= DDI_SUCCESS
) {
1596 mac_fini_ops(&vmxnet3_dev_ops
);
1602 /* Module unload entry point */
1608 ret
= mod_remove(&vmxnet3_modlinkage
);
1609 if (ret
== DDI_SUCCESS
) {
1610 mac_fini_ops(&vmxnet3_dev_ops
);
1616 /* Module info entry point */
1618 _info(struct modinfo
*modinfop
)
1620 return (mod_info(&vmxnet3_modlinkage
, modinfop
));