Print this page
11493 aggr needs support for multiple pseudo rx groups
Portions contributed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>


   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