diff options
author | vitezslav batrla - Sun Microsystems - Prague Czech Republic <Vitezslav.Batrla@Sun.COM> | 2009-06-03 16:13:19 +0200 |
---|---|---|
committer | vitezslav batrla - Sun Microsystems - Prague Czech Republic <Vitezslav.Batrla@Sun.COM> | 2009-06-03 16:13:19 +0200 |
commit | 6ca163a136944eea4423498926e09cef9889312c (patch) | |
tree | 1919ba3ffa6aa34e319ae3473dba9bd64227af84 /usr/src | |
parent | 34f345ef9f728de9cf6c935468866b3f017a880f (diff) | |
download | illumos-joyent-6ca163a136944eea4423498926e09cef9889312c.tar.gz |
6842781 Customer needs to be able to set MAX_NUM_MULTICAST_ADDRESSES above 256 on igb driver
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/igb/igb_main.c | 78 | ||||
-rw-r--r-- | usr/src/uts/common/io/igb/igb_sw.h | 10 |
2 files changed, 81 insertions, 7 deletions
diff --git a/usr/src/uts/common/io/igb/igb_main.c b/usr/src/uts/common/io/igb/igb_main.c index e23d34949a..6fd6f5e62e 100644 --- a/usr/src/uts/common/io/igb/igb_main.c +++ b/usr/src/uts/common/io/igb/igb_main.c @@ -29,7 +29,7 @@ #include "igb_sw.h" static char ident[] = "Intel 1Gb Ethernet"; -static char igb_version[] = "igb 1.1.6"; +static char igb_version[] = "igb 1.1.7"; /* * Local function protoypes @@ -112,7 +112,7 @@ static int igb_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *); static void igb_fm_init(igb_t *); static void igb_fm_fini(igb_t *); - +static void igb_release_multicast(igb_t *); static struct cb_ops igb_cb_ops = { nulldev, /* cb_open */ @@ -691,6 +691,11 @@ igb_unconfigure(dev_info_t *devinfo, igb_t *igb) } /* + * Free multicast table + */ + igb_release_multicast(igb); + + /* * Free register handle */ if (igb->attach_progress & ATTACH_PROGRESS_REGS_MAP) { @@ -2438,16 +2443,44 @@ igb_unicst_set(igb_t *igb, const uint8_t *mac_addr, int igb_multicst_add(igb_t *igb, const uint8_t *multiaddr) { + struct ether_addr *new_table; + size_t new_len; + size_t old_len; + ASSERT(mutex_owned(&igb->gen_lock)); if ((multiaddr[0] & 01) == 0) { + igb_error(igb, "Illegal multicast address"); return (EINVAL); } - if (igb->mcast_count >= MAX_NUM_MULTICAST_ADDRESSES) { + if (igb->mcast_count >= igb->mcast_max_num) { + igb_error(igb, "Adapter requested more than %d mcast addresses", + igb->mcast_max_num); return (ENOENT); } + if (igb->mcast_count == igb->mcast_alloc_count) { + old_len = igb->mcast_alloc_count * + sizeof (struct ether_addr); + new_len = (igb->mcast_alloc_count + MCAST_ALLOC_COUNT) * + sizeof (struct ether_addr); + + new_table = kmem_alloc(new_len, KM_NOSLEEP); + if (new_table == NULL) { + igb_error(igb, + "Not enough memory to alloc mcast table"); + return (ENOMEM); + } + + if (igb->mcast_table != NULL) { + bcopy(igb->mcast_table, new_table, old_len); + kmem_free(igb->mcast_table, old_len); + } + igb->mcast_alloc_count += MCAST_ALLOC_COUNT; + igb->mcast_table = new_table; + } + bcopy(multiaddr, &igb->mcast_table[igb->mcast_count], ETHERADDRL); igb->mcast_count++; @@ -2471,6 +2504,9 @@ igb_multicst_add(igb_t *igb, const uint8_t *multiaddr) int igb_multicst_remove(igb_t *igb, const uint8_t *multiaddr) { + struct ether_addr *new_table; + size_t new_len; + size_t old_len; int i; ASSERT(mutex_owned(&igb->gen_lock)); @@ -2487,6 +2523,22 @@ igb_multicst_remove(igb_t *igb, const uint8_t *multiaddr) } } + if ((igb->mcast_alloc_count - igb->mcast_count) > + MCAST_ALLOC_COUNT) { + old_len = igb->mcast_alloc_count * + sizeof (struct ether_addr); + new_len = (igb->mcast_alloc_count - MCAST_ALLOC_COUNT) * + sizeof (struct ether_addr); + + new_table = kmem_alloc(new_len, KM_NOSLEEP); + if (new_table != NULL) { + bcopy(igb->mcast_table, new_table, new_len); + kmem_free(igb->mcast_table, old_len); + igb->mcast_alloc_count -= MCAST_ALLOC_COUNT; + igb->mcast_table = new_table; + } + } + /* * Update the multicast table in the hardware */ @@ -2500,6 +2552,16 @@ igb_multicst_remove(igb_t *igb, const uint8_t *multiaddr) return (0); } +static void +igb_release_multicast(igb_t *igb) +{ + if (igb->mcast_table != NULL) { + kmem_free(igb->mcast_table, + igb->mcast_alloc_count * sizeof (struct ether_addr)); + igb->mcast_table = NULL; + } +} + /* * igb_setup_multicast - setup multicast data structures * @@ -2514,8 +2576,7 @@ igb_setup_multicst(igb_t *igb) struct e1000_hw *hw = &igb->hw; ASSERT(mutex_owned(&igb->gen_lock)); - - ASSERT(igb->mcast_count <= MAX_NUM_MULTICAST_ADDRESSES); + ASSERT(igb->mcast_count <= igb->mcast_max_num); mc_addr_list = (uint8_t *)igb->mcast_table; mc_addr_count = igb->mcast_count; @@ -2731,6 +2792,13 @@ igb_get_conf(igb_t *igb) igb->capab->min_intr_throttle, igb->capab->max_intr_throttle, igb->capab->def_intr_throttle); + + /* + * Max number of multicast addresses + */ + igb->mcast_max_num = + igb_get_prop(igb, PROP_MCAST_MAX_NUM, + MIN_MCAST_NUM, MAX_MCAST_NUM, DEFAULT_MCAST_NUM); } /* diff --git a/usr/src/uts/common/io/igb/igb_sw.h b/usr/src/uts/common/io/igb/igb_sw.h index fdfdf1d0e8..b27ec11e35 100644 --- a/usr/src/uts/common/io/igb/igb_sw.h +++ b/usr/src/uts/common/io/igb/igb_sw.h @@ -94,7 +94,7 @@ extern "C" { #define IGB_NO_FREE_SLOT -1 #define MAX_NUM_UNICAST_ADDRESSES E1000_RAR_ENTRIES -#define MAX_NUM_MULTICAST_ADDRESSES 256 +#define MCAST_ALLOC_COUNT 256 #define MAX_COOKIE 18 #define MIN_NUM_TX_DESC 2 @@ -124,6 +124,7 @@ extern "C" { #define MAX_TX_RECYCLE_THRESHOLD DEFAULT_TX_RING_SIZE #define MAX_TX_OVERLOAD_THRESHOLD DEFAULT_TX_RING_SIZE #define MAX_TX_RESCHED_THRESHOLD DEFAULT_TX_RING_SIZE +#define MAX_MCAST_NUM 8192 /* * Minimum values for user configurable parameters @@ -143,6 +144,7 @@ extern "C" { #define MIN_TX_RECYCLE_THRESHOLD MIN_NUM_TX_DESC #define MIN_TX_OVERLOAD_THRESHOLD MIN_NUM_TX_DESC #define MIN_TX_RESCHED_THRESHOLD MIN_NUM_TX_DESC +#define MIN_MCAST_NUM 8 /* * Default values for user configurable parameters @@ -162,6 +164,7 @@ extern "C" { #define DEFAULT_TX_RECYCLE_THRESHOLD (MAX_COOKIE + 1) #define DEFAULT_TX_OVERLOAD_THRESHOLD MIN_NUM_TX_DESC #define DEFAULT_TX_RESCHED_THRESHOLD 128 +#define DEFAULT_MCAST_NUM 4096 #define IGB_LSO_MAXLEN 65535 @@ -220,6 +223,7 @@ extern "C" { #define PROP_RX_COPY_THRESHOLD "rx_copy_threshold" #define PROP_RX_LIMIT_PER_INTR "rx_limit_per_intr" #define PROP_INTR_THROTTLING "intr_throttling" +#define PROP_MCAST_MAX_NUM "mcast_max_num" #define IGB_LB_NONE 0 #define IGB_LB_EXTERNAL 1 @@ -730,7 +734,9 @@ typedef struct igb { uint32_t unicst_total; igb_ether_addr_t unicst_addr[MAX_NUM_UNICAST_ADDRESSES]; uint32_t mcast_count; - struct ether_addr mcast_table[MAX_NUM_MULTICAST_ADDRESSES]; + uint32_t mcast_alloc_count; + uint32_t mcast_max_num; + struct ether_addr *mcast_table; /* * Kstat definitions |