diff --git a/usr/src/uts/common/io/aggr/aggr_grp.c b/usr/src/uts/common/io/aggr/aggr_grp.c index a4cfdad51ecd..0c284c6d4c9c 100644 --- a/usr/src/uts/common/io/aggr/aggr_grp.c +++ b/usr/src/uts/common/io/aggr/aggr_grp.c @@ -227,6 +227,8 @@ aggr_grp_destructor(void *buf, void *arg) grp->lg_tx_ports_size * sizeof (aggr_port_t *)); } + kmem_free(grp->lg_rx_groups, grp->lg_rx_groups_size); + mutex_destroy(&grp->lg_lacp_lock); cv_destroy(&grp->lg_lacp_cv); mutex_destroy(&grp->lg_port_lock); @@ -753,7 +755,7 @@ aggr_add_pseudo_rx_group(aggr_port_t *port, aggr_pseudo_rx_group_t *rx_grp) uint_t g_idx = rx_grp->arg_index; ASSERT(MAC_PERIM_HELD(port->lp_grp->lg_mh)); - ASSERT3U(g_idx, <, MAX_GROUPS_PER_PORT); + ASSERT3U(g_idx, <, port->lp_grp->lg_rx_group_count); mac_perim_enter_by_mh(port->lp_mh, &pmph); i = 0; @@ -836,7 +838,7 @@ aggr_rem_pseudo_rx_group(aggr_port_t *port, aggr_pseudo_rx_group_t *rx_grp) uint_t g_idx = rx_grp->arg_index; ASSERT(MAC_PERIM_HELD(port->lp_grp->lg_mh)); - ASSERT3U(g_idx, <, MAX_GROUPS_PER_PORT); + ASSERT3U(g_idx, <, port->lp_grp->lg_rx_group_count); ASSERT3P(rx_grp->arg_gh, !=, NULL); mac_perim_enter_by_mh(port->lp_mh, &pmph); @@ -1491,8 +1493,6 @@ aggr_grp_create(datalink_id_t linkid, uint32_t key, uint_t nports, grp->lg_tx_blocked_rings = kmem_zalloc((sizeof (mac_ring_handle_t *) * MAX_RINGS_PER_GROUP), KM_SLEEP); grp->lg_tx_blocked_cnt = 0; - bzero(&grp->lg_rx_groups, - sizeof (aggr_pseudo_rx_group_t) * MAX_GROUPS_PER_PORT); bzero(&grp->lg_tx_group, sizeof (aggr_pseudo_tx_group_t)); aggr_lacp_init_grp(grp); @@ -1537,16 +1537,12 @@ aggr_grp_create(datalink_id_t linkid, uint32_t key, uint_t nports, num_rgroups); } - /* - * There could be cases where the hardware provides more - * groups than aggr can support. Make sure we never go above - * the max aggr can support. - */ - grp->lg_rx_group_count = MIN(grp->lg_rx_group_count, - MAX_GROUPS_PER_PORT); + grp->lg_rx_groups_size = sizeof (aggr_pseudo_rx_group_t) * + grp->lg_rx_group_count; + grp->lg_rx_groups = kmem_zalloc(grp->lg_rx_groups_size, KM_SLEEP); ASSERT3U(grp->lg_rx_group_count, >, 0); - for (i = 0; i < MAX_GROUPS_PER_PORT; i++) { + for (i = 0; i < grp->lg_rx_group_count; i++) { grp->lg_rx_groups[i].arg_index = i; grp->lg_rx_groups[i].arg_untagged = 0; list_create(&(grp->lg_rx_groups[i].arg_vlans), @@ -2120,7 +2116,7 @@ aggr_grp_delete(datalink_id_t linkid, cred_t *cred) VERIFY(mac_unregister(grp->lg_mh) == 0); grp->lg_mh = NULL; - for (uint_t i = 0; i < MAX_GROUPS_PER_PORT; i++) { + for (uint_t i = 0; i < grp->lg_rx_group_count; i++) { list_destroy(&(grp->lg_rx_groups[i].arg_vlans)); } diff --git a/usr/src/uts/common/io/aggr/aggr_port.c b/usr/src/uts/common/io/aggr/aggr_port.c index e764dd104e6e..5384a5817e8c 100644 --- a/usr/src/uts/common/io/aggr/aggr_port.c +++ b/usr/src/uts/common/io/aggr/aggr_port.c @@ -73,8 +73,9 @@ aggr_port_destructor(void *buf, void *arg) ASSERT3P(port->lp_mnh, ==, NULL); ASSERT(!port->lp_tx_grp_added); - for (uint_t i = 0; i < MAX_GROUPS_PER_PORT; i++) + for (uint_t i = 0; i < port->lp_hwgh_count; i++) ASSERT3P(port->lp_hwghs[i], ==, NULL); + kmem_free(port->lp_hwghs, port->lp_hwghs_size); } void @@ -147,6 +148,8 @@ aggr_port_create(aggr_grp_t *grp, const datalink_id_t linkid, boolean_t force, char port_name[MAXNAMELEN]; mac_diag_t diag; mac_unicast_handle_t mah; + mac_perim_handle_t mph; + uint_t num_rgroups; *pp = NULL; @@ -256,6 +259,14 @@ aggr_port_create(aggr_grp_t *grp, const datalink_id_t linkid, boolean_t force, /* LACP related state */ port->lp_collector_enabled = B_FALSE; + /* Allocate the set of rx group handles. */ + mac_perim_enter_by_mh(port->lp_mh, &mph); + num_rgroups = mac_get_num_rx_groups(port->lp_mh); + mac_perim_exit(mph); + port->lp_hwgh_count = num_rgroups; + port->lp_hwghs_size = sizeof (mac_group_handle_t) * num_rgroups; + port->lp_hwghs = kmem_zalloc(port->lp_hwghs_size, KM_SLEEP); + *pp = port; return (0); @@ -593,7 +604,7 @@ aggr_port_addmac(aggr_port_t *port, uint_t idx, const uint8_t *mac_addr) int err; ASSERT(MAC_PERIM_HELD(port->lp_grp->lg_mh)); - ASSERT3U(idx, <, MAX_GROUPS_PER_PORT); + ASSERT3U(idx, <, port->lp_grp->lg_rx_group_count); mac_perim_enter_by_mh(port->lp_mh, &pmph); /* @@ -602,7 +613,7 @@ aggr_port_addmac(aggr_port_t *port, uint_t idx, const uint8_t *mac_addr) * let the aggr SW classify its traffic. This scenario happens * when mixing ports with a different number of HW groups. */ - if (port->lp_hwghs[idx] == NULL) + if (idx >= port->lp_hwgh_count || port->lp_hwghs[idx] == NULL) idx = 0; /* @@ -657,7 +668,7 @@ aggr_port_remmac(aggr_port_t *port, uint_t idx, const uint8_t *mac_addr) mac_perim_handle_t pmph; ASSERT(MAC_PERIM_HELD(grp->lg_mh)); - ASSERT3U(idx, <, MAX_GROUPS_PER_PORT); + ASSERT3U(idx, <, grp->lg_rx_group_count); mac_perim_enter_by_mh(port->lp_mh, &pmph); /* @@ -684,7 +695,7 @@ aggr_port_remmac(aggr_port_t *port, uint_t idx, const uint8_t *mac_addr) (void) aggr_port_promisc(port, B_FALSE); } else { /* See comment in aggr_port_addmac(). */ - if (port->lp_hwghs[idx] == NULL) + if (idx >= port->lp_hwgh_count || port->lp_hwghs[idx] == NULL) idx = 0; ASSERT3P(port->lp_hwghs[idx], !=, NULL); @@ -701,11 +712,11 @@ aggr_port_addvlan(aggr_port_t *port, uint_t idx, uint16_t vid) int err; ASSERT(MAC_PERIM_HELD(port->lp_grp->lg_mh)); - ASSERT3U(idx, <, MAX_GROUPS_PER_PORT); + ASSERT3U(idx, <, port->lp_grp->lg_rx_group_count); mac_perim_enter_by_mh(port->lp_mh, &pmph); /* See comment in aggr_port_addmac(). */ - if (port->lp_hwghs[idx] == NULL) + if (idx >= port->lp_hwgh_count || port->lp_hwghs[idx] == NULL) idx = 0; /* @@ -714,7 +725,7 @@ aggr_port_addvlan(aggr_port_t *port, uint_t idx, uint16_t vid) * implicitly allow tagged traffic to pass and there is * nothing to do. */ - if (port->lp_hwghs[idx] == NULL) + if (idx >= port->lp_hwgh_count || port->lp_hwghs[idx] == NULL) err = 0; else err = mac_hwgroup_addvlan(port->lp_hwghs[idx], vid); @@ -730,14 +741,14 @@ aggr_port_remvlan(aggr_port_t *port, uint_t idx, uint16_t vid) int err; ASSERT(MAC_PERIM_HELD(port->lp_grp->lg_mh)); - ASSERT3U(idx, <, MAX_GROUPS_PER_PORT); + ASSERT3U(idx, <, port->lp_grp->lg_rx_group_count); mac_perim_enter_by_mh(port->lp_mh, &pmph); /* See comment in aggr_port_addmac(). */ - if (port->lp_hwghs[idx] == NULL) + if (idx >= port->lp_hwgh_count || port->lp_hwghs[idx] == NULL) idx = 0; - if (port->lp_hwghs[idx] == NULL) + if (idx >= port->lp_hwgh_count || port->lp_hwghs[idx] == NULL) err = 0; else err = mac_hwgroup_remvlan(port->lp_hwghs[idx], vid); diff --git a/usr/src/uts/common/sys/aggr_impl.h b/usr/src/uts/common/sys/aggr_impl.h index de4162bc6112..edbfb2d68977 100644 --- a/usr/src/uts/common/sys/aggr_impl.h +++ b/usr/src/uts/common/sys/aggr_impl.h @@ -57,8 +57,6 @@ extern "C" { */ #define MAC_PSEUDO_RING_INUSE 0x01 -#define MAX_GROUPS_PER_PORT 128 - /* * VLAN filters placed on the Rx pseudo group. */ @@ -160,7 +158,9 @@ typedef struct aggr_port_s { * Used by aggr to program HW classification for the pseudo * groups. */ - mac_group_handle_t lp_hwghs[MAX_GROUPS_PER_PORT]; + size_t lp_hwghs_size; + uint_t lp_hwgh_count; + mac_group_handle_t *lp_hwghs; uint_t lp_tx_ring_alloc; uint_t lp_tx_ring_cnt; @@ -255,7 +255,8 @@ typedef struct aggr_grp_s { boolean_t lg_lacp_done; uint_t lg_rx_group_count; - aggr_pseudo_rx_group_t lg_rx_groups[MAX_GROUPS_PER_PORT]; + size_t lg_rx_groups_size; + aggr_pseudo_rx_group_t *lg_rx_groups; aggr_pseudo_tx_group_t lg_tx_group;