5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <sys/errno.h>
29 #include <sys/param.h>
30 #include <sys/callb.h>
31 #include <sys/stream.h>
32 #include <sys/kmem.h>
33 #include <sys/conf.h>
34 #include <sys/devops.h>
35 #include <sys/ksynch.h>
36 #include <sys/stat.h>
37 #include <sys/modctl.h>
38 #include <sys/modhash.h>
39 #include <sys/debug.h>
40 #include <sys/ethernet.h>
41 #include <sys/dlpi.h>
42 #include <net/if.h>
43 #include <sys/mac_provider.h>
44 #include <sys/mac_client.h>
2388 rx_ringp->gen_num = mr_gen_num;
2389 rx_ringp->state |= VNET_RXRING_STARTED;
2390 return (0);
2391 }
2392
2393 ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0);
2394
2395 /*
2396 * This must be a ring reserved for a hwring. If the hwring is not
2397 * bound yet, simply mark the state to indicate the ring is started and
2398 * return. If and when a hybrid resource is activated for this vnet
2399 * device, we will bind the hwring and start it then. If a hwring is
2400 * already bound, start it now.
2401 */
2402 if (rx_ringp->hw_rh == NULL) {
2403 rx_ringp->gen_num = mr_gen_num;
2404 rx_ringp->state |= VNET_RXRING_STARTED;
2405 return (0);
2406 }
2407
2408 err = mac_hwring_start(rx_ringp->hw_rh);
2409 if (err == 0) {
2410 rx_ringp->gen_num = mr_gen_num;
2411 rx_ringp->state |= VNET_RXRING_STARTED;
2412 } else {
2413 err = ENXIO;
2414 }
2415
2416 return (err);
2417 }
2418
2419 static void
2420 vnet_rx_ring_stop(mac_ring_driver_t arg)
2421 {
2422 vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg;
2423
2424 /*
2425 * If this ring is mapped to a LDC resource, simply mark the state to
2426 * indicate the ring is now stopped and return.
2427 */
2428 if ((rx_ringp->state &
2429 (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0) {
2430 rx_ringp->state &= ~VNET_RXRING_STARTED;
2431 return;
2432 }
2433
2434 ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0);
2435
2436 /*
2437 * This must be a ring reserved for a hwring. If the hwring is not
2438 * bound yet, simply mark the state to indicate the ring is stopped and
2439 * return. If a hwring is already bound, stop it now.
2440 */
2441 if (rx_ringp->hw_rh == NULL) {
2442 rx_ringp->state &= ~VNET_RXRING_STARTED;
2443 return;
2444 }
2445
2446 mac_hwring_stop(rx_ringp->hw_rh);
2447 rx_ringp->state &= ~VNET_RXRING_STARTED;
2448 }
2449
2450 static int
2451 vnet_rx_ring_stat(mac_ring_driver_t rdriver, uint_t stat, uint64_t *val)
2452 {
2453 vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)rdriver;
2454 vnet_t *vnetp = (vnet_t *)rx_ringp->vnetp;
2455 vnet_res_t *vresp;
2456 mac_register_t *macp;
2457 mac_callbacks_t *cbp;
2458
2459 /*
2460 * Refer to vnet_m_capab() function for detailed comments on ring
2461 * synchronization.
2462 */
2463 if ((rx_ringp->state & VNET_RXRING_HYBRID) != 0) {
2464 READ_ENTER(&vnetp->vsw_fp_rw);
2465 if (vnetp->hio_fp == NULL) {
2466 RW_EXIT(&vnetp->vsw_fp_rw);
2829 /*
2830 * Bind the pseudo rings to the hwrings and start the hwrings.
2831 * Note we don't need to register these with the upper mac, as we have
2832 * statically exported these pseudo rxrings which are reserved for
2833 * rxrings of Hybrid resource.
2834 */
2835 rx_grp = &vnetp->rx_grp[0];
2836 for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
2837 /* Pick the rxrings reserved for Hybrid resource */
2838 rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX];
2839
2840 /* Store the hw ring handle */
2841 rx_ringp->hw_rh = hw_rh[i];
2842
2843 /* Bind the pseudo ring to the underlying hwring */
2844 mac_hwring_setup(rx_ringp->hw_rh,
2845 (mac_resource_handle_t)rx_ringp, NULL);
2846
2847 /* Start the hwring if needed */
2848 if (rx_ringp->state & VNET_RXRING_STARTED) {
2849 rv = mac_hwring_start(rx_ringp->hw_rh);
2850 if (rv != 0) {
2851 mac_hwring_teardown(rx_ringp->hw_rh);
2852 rx_ringp->hw_rh = NULL;
2853 goto fail;
2854 }
2855 }
2856 }
2857
2858 /* Get the list of the underlying TX rings. */
2859 hw_ring_cnt = mac_hwrings_get(vnetp->hio_mch, &vnetp->tx_hwgh, hw_rh,
2860 MAC_RING_TYPE_TX);
2861
2862 /* We expect the # of hw tx rings to match VNET_NUM_HYBRID_RINGS */
2863 if (hw_ring_cnt != VNET_NUM_HYBRID_RINGS) {
2864 cmn_err(CE_WARN,
2865 "!vnet%d: vnet_bind_hwrings: bad tx hw_ring_cnt(%d)\n",
2866 vnetp->instance, hw_ring_cnt);
2867 goto fail;
2868 }
2869
2903 int i;
2904
2905 mac_perim_enter_by_mh(vnetp->hio_mh, &mph1);
2906
2907 tx_grp = &vnetp->tx_grp[0];
2908 for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
2909 tx_ringp = &tx_grp->rings[i];
2910 if (tx_ringp->state & VNET_TXRING_HYBRID) {
2911 tx_ringp->state &= ~VNET_TXRING_HYBRID;
2912 tx_ringp->hw_rh = NULL;
2913 }
2914 }
2915 (void) mac_client_tx_notify(vnetp->hio_mch, NULL,
2916 tx_grp->tx_notify_handle);
2917
2918 rx_grp = &vnetp->rx_grp[0];
2919 for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
2920 rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX];
2921 if (rx_ringp->hw_rh != NULL) {
2922 /* Stop the hwring */
2923 mac_hwring_stop(rx_ringp->hw_rh);
2924
2925 /* Teardown the hwring */
2926 mac_hwring_teardown(rx_ringp->hw_rh);
2927 rx_ringp->hw_rh = NULL;
2928 }
2929 }
2930
2931 if (vnetp->rx_hwgh != NULL) {
2932 vnetp->rx_hwgh = NULL;
2933 /*
2934 * First clear the permanent-quiesced flag of the RX srs then
2935 * restart the HW ring and the mac srs on the ring.
2936 */
2937 mac_srs_perm_quiesce(vnetp->hio_mch, B_FALSE);
2938 mac_rx_client_restart(vnetp->hio_mch);
2939 }
2940
2941 mac_perim_exit(mph1);
2942 }
2943
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2018 Joyent, Inc.
26 */
27
28 #include <sys/types.h>
29 #include <sys/errno.h>
30 #include <sys/param.h>
31 #include <sys/callb.h>
32 #include <sys/stream.h>
33 #include <sys/kmem.h>
34 #include <sys/conf.h>
35 #include <sys/devops.h>
36 #include <sys/ksynch.h>
37 #include <sys/stat.h>
38 #include <sys/modctl.h>
39 #include <sys/modhash.h>
40 #include <sys/debug.h>
41 #include <sys/ethernet.h>
42 #include <sys/dlpi.h>
43 #include <net/if.h>
44 #include <sys/mac_provider.h>
45 #include <sys/mac_client.h>
2389 rx_ringp->gen_num = mr_gen_num;
2390 rx_ringp->state |= VNET_RXRING_STARTED;
2391 return (0);
2392 }
2393
2394 ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0);
2395
2396 /*
2397 * This must be a ring reserved for a hwring. If the hwring is not
2398 * bound yet, simply mark the state to indicate the ring is started and
2399 * return. If and when a hybrid resource is activated for this vnet
2400 * device, we will bind the hwring and start it then. If a hwring is
2401 * already bound, start it now.
2402 */
2403 if (rx_ringp->hw_rh == NULL) {
2404 rx_ringp->gen_num = mr_gen_num;
2405 rx_ringp->state |= VNET_RXRING_STARTED;
2406 return (0);
2407 }
2408
2409 err = mac_hwring_activate(rx_ringp->hw_rh);
2410 if (err == 0) {
2411 rx_ringp->gen_num = mr_gen_num;
2412 rx_ringp->state |= VNET_RXRING_STARTED;
2413 } else {
2414 err = ENXIO;
2415 }
2416
2417 return (err);
2418 }
2419
2420 static void
2421 vnet_rx_ring_stop(mac_ring_driver_t arg)
2422 {
2423 vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg;
2424
2425 /*
2426 * If this ring is mapped to a LDC resource, simply mark the state to
2427 * indicate the ring is now stopped and return.
2428 */
2429 if ((rx_ringp->state &
2430 (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0) {
2431 rx_ringp->state &= ~VNET_RXRING_STARTED;
2432 return;
2433 }
2434
2435 ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0);
2436
2437 /*
2438 * This must be a ring reserved for a hwring. If the hwring is not
2439 * bound yet, simply mark the state to indicate the ring is stopped and
2440 * return. If a hwring is already bound, stop it now.
2441 */
2442 if (rx_ringp->hw_rh == NULL) {
2443 rx_ringp->state &= ~VNET_RXRING_STARTED;
2444 return;
2445 }
2446
2447 mac_hwring_quiesce(rx_ringp->hw_rh);
2448 rx_ringp->state &= ~VNET_RXRING_STARTED;
2449 }
2450
2451 static int
2452 vnet_rx_ring_stat(mac_ring_driver_t rdriver, uint_t stat, uint64_t *val)
2453 {
2454 vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)rdriver;
2455 vnet_t *vnetp = (vnet_t *)rx_ringp->vnetp;
2456 vnet_res_t *vresp;
2457 mac_register_t *macp;
2458 mac_callbacks_t *cbp;
2459
2460 /*
2461 * Refer to vnet_m_capab() function for detailed comments on ring
2462 * synchronization.
2463 */
2464 if ((rx_ringp->state & VNET_RXRING_HYBRID) != 0) {
2465 READ_ENTER(&vnetp->vsw_fp_rw);
2466 if (vnetp->hio_fp == NULL) {
2467 RW_EXIT(&vnetp->vsw_fp_rw);
2830 /*
2831 * Bind the pseudo rings to the hwrings and start the hwrings.
2832 * Note we don't need to register these with the upper mac, as we have
2833 * statically exported these pseudo rxrings which are reserved for
2834 * rxrings of Hybrid resource.
2835 */
2836 rx_grp = &vnetp->rx_grp[0];
2837 for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
2838 /* Pick the rxrings reserved for Hybrid resource */
2839 rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX];
2840
2841 /* Store the hw ring handle */
2842 rx_ringp->hw_rh = hw_rh[i];
2843
2844 /* Bind the pseudo ring to the underlying hwring */
2845 mac_hwring_setup(rx_ringp->hw_rh,
2846 (mac_resource_handle_t)rx_ringp, NULL);
2847
2848 /* Start the hwring if needed */
2849 if (rx_ringp->state & VNET_RXRING_STARTED) {
2850 rv = mac_hwring_activate(rx_ringp->hw_rh);
2851 if (rv != 0) {
2852 mac_hwring_teardown(rx_ringp->hw_rh);
2853 rx_ringp->hw_rh = NULL;
2854 goto fail;
2855 }
2856 }
2857 }
2858
2859 /* Get the list of the underlying TX rings. */
2860 hw_ring_cnt = mac_hwrings_get(vnetp->hio_mch, &vnetp->tx_hwgh, hw_rh,
2861 MAC_RING_TYPE_TX);
2862
2863 /* We expect the # of hw tx rings to match VNET_NUM_HYBRID_RINGS */
2864 if (hw_ring_cnt != VNET_NUM_HYBRID_RINGS) {
2865 cmn_err(CE_WARN,
2866 "!vnet%d: vnet_bind_hwrings: bad tx hw_ring_cnt(%d)\n",
2867 vnetp->instance, hw_ring_cnt);
2868 goto fail;
2869 }
2870
2904 int i;
2905
2906 mac_perim_enter_by_mh(vnetp->hio_mh, &mph1);
2907
2908 tx_grp = &vnetp->tx_grp[0];
2909 for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
2910 tx_ringp = &tx_grp->rings[i];
2911 if (tx_ringp->state & VNET_TXRING_HYBRID) {
2912 tx_ringp->state &= ~VNET_TXRING_HYBRID;
2913 tx_ringp->hw_rh = NULL;
2914 }
2915 }
2916 (void) mac_client_tx_notify(vnetp->hio_mch, NULL,
2917 tx_grp->tx_notify_handle);
2918
2919 rx_grp = &vnetp->rx_grp[0];
2920 for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
2921 rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX];
2922 if (rx_ringp->hw_rh != NULL) {
2923 /* Stop the hwring */
2924 mac_hwring_quiesce(rx_ringp->hw_rh);
2925
2926 /* Teardown the hwring */
2927 mac_hwring_teardown(rx_ringp->hw_rh);
2928 rx_ringp->hw_rh = NULL;
2929 }
2930 }
2931
2932 if (vnetp->rx_hwgh != NULL) {
2933 vnetp->rx_hwgh = NULL;
2934 /*
2935 * First clear the permanent-quiesced flag of the RX srs then
2936 * restart the HW ring and the mac srs on the ring.
2937 */
2938 mac_srs_perm_quiesce(vnetp->hio_mch, B_FALSE);
2939 mac_rx_client_restart(vnetp->hio_mch);
2940 }
2941
2942 mac_perim_exit(mph1);
2943 }
2944
|