summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorvitezslav batrla - Sun Microsystems - Prague Czech Republic <Vitezslav.Batrla@Sun.COM>2009-06-03 16:13:19 +0200
committervitezslav batrla - Sun Microsystems - Prague Czech Republic <Vitezslav.Batrla@Sun.COM>2009-06-03 16:13:19 +0200
commit6ca163a136944eea4423498926e09cef9889312c (patch)
tree1919ba3ffa6aa34e319ae3473dba9bd64227af84 /usr/src
parent34f345ef9f728de9cf6c935468866b3f017a880f (diff)
downloadillumos-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.c78
-rw-r--r--usr/src/uts/common/io/igb/igb_sw.h10
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