summaryrefslogtreecommitdiffstats
path: root/c/src
diff options
context:
space:
mode:
authorTill Straumann <strauman@slac.stanford.edu>2009-08-17 14:27:55 +0000
committerTill Straumann <strauman@slac.stanford.edu>2009-08-17 14:27:55 +0000
commite8ac5d470eb766b4122c153b209da24ebdc1a2bc (patch)
tree6ed3ccdc7c24b558981fc006c556c6182e364deb /c/src
parentRemove centos-4, tighten up suse, move fedora-9 to centos-5. (diff)
downloadrtems-e8ac5d470eb766b4122c153b209da24ebdc1a2bc.tar.bz2
2009-08-17 Till Straumann <strauman@slac.stanford.edu>
* network/tsec.c, network/if_tsec_pub.h: Fixed bugs in multicast support; added reference-count for hash-table entries which allows for the implementation of a 'deletion' routine. NOTE: mcast support largely untested.
Diffstat (limited to 'c/src')
-rw-r--r--c/src/lib/libbsp/powerpc/mvme3100/ChangeLog8
-rw-r--r--c/src/lib/libbsp/powerpc/mvme3100/network/if_tsec_pub.h34
-rw-r--r--c/src/lib/libbsp/powerpc/mvme3100/network/tsec.c41
3 files changed, 68 insertions, 15 deletions
diff --git a/c/src/lib/libbsp/powerpc/mvme3100/ChangeLog b/c/src/lib/libbsp/powerpc/mvme3100/ChangeLog
index d89c396527..cdeba66908 100644
--- a/c/src/lib/libbsp/powerpc/mvme3100/ChangeLog
+++ b/c/src/lib/libbsp/powerpc/mvme3100/ChangeLog
@@ -1,3 +1,11 @@
+2009-08-17 Till Straumann <strauman@slac.stanford.edu>
+
+ * network/tsec.c, network/if_tsec_pub.h:
+ Fixed bugs in multicast support; added reference-count
+ for hash-table entries which allows for the implementation
+ of a 'deletion' routine.
+ NOTE: mcast support largely untested.
+
2009-06-05 Till Straumann <strauman@slac.stanford.edu>
* irq/irq_init.c: silenced compiler warning.
diff --git a/c/src/lib/libbsp/powerpc/mvme3100/network/if_tsec_pub.h b/c/src/lib/libbsp/powerpc/mvme3100/network/if_tsec_pub.h
index 0a7760d0c1..79846b0093 100644
--- a/c/src/lib/libbsp/powerpc/mvme3100/network/if_tsec_pub.h
+++ b/c/src/lib/libbsp/powerpc/mvme3100/network/if_tsec_pub.h
@@ -182,36 +182,52 @@ BSP_tsec_init_hw(struct tsec_private *mp, int promisc, unsigned char *enaddr);
* Clear multicast hash filter. No multicast frames are accepted
* after executing this routine (unless the hardware was initialized
* in 'promiscuous' mode).
+ *
+ * Reset reference count for all hash-table entries
+ * to zero (see BSP_tsec_mcast_filter_accept_del()).
*/
void
BSP_tsec_mcast_filter_clear(struct tsec_private *mp);
/*
* Program multicast filter to accept all multicast frames.
+ *
+ * Increment reference count for all hash-table entries
+ * by one (see BSP_tsec_mcast_filter_accept_del()).
*/
void
BSP_tsec_mcast_filter_accept_all(struct tsec_private *mp);
/*
- * Add a MAC address to the multicast filter.
+ * Add a MAC address to the multicast filter and increment
+ * the reference count for the matching hash-table entry
+ * (see BSP_tsec_mcast_filter_accept_del()).
+ *
* Existing entries are not changed but note that
* the filter is imperfect, i.e., multiple MAC addresses
* may alias to a single filter entry. Hence software
* filtering must still be performed.
*
- * NOTE: Deletion of an address is not possible. This is
- * usually accomplished by a higher-level driver
- * maintaining a list/database of multicast addresses
- * and going through a sequence:
- *
- * BSP_tsec_mcast_filter_clear()
- * forall mcast addresses do
- * BSP_tsec_mcast_filter_accept_add()
*/
void
BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, unsigned char *enaddr);
/*
+ * Remove a MAC address from the (imperfec) multicast
+ * filter.
+ * Note that the driver maintains an internal reference
+ * counter for each multicast hash. The hash-table
+ * entry is only cleared when the reference count
+ * reaches zero ('del' has been called the same
+ * amount of times as 'add' for an address (or
+ * any alias) that matches a given table entry.
+ * BSP_tsec_mcast_filter_clear() resets all reference
+ * counters to zero.
+ */
+void
+BSP_tsec_mcast_filter_accept_del(struct tsec_private *mp, unsigned char *enaddr);
+
+/*
* Dump statistics to FILE 'f'. If NULL, stdout is used.
*/
void
diff --git a/c/src/lib/libbsp/powerpc/mvme3100/network/tsec.c b/c/src/lib/libbsp/powerpc/mvme3100/network/tsec.c
index 3127466b4a..5d6fff773f 100644
--- a/c/src/lib/libbsp/powerpc/mvme3100/network/tsec.c
+++ b/c/src/lib/libbsp/powerpc/mvme3100/network/tsec.c
@@ -640,6 +640,8 @@ static inline void bd_wrbuf(TSEC_BD *bd, uint32_t addr)
/* Driver 'private' data */
+#define NUM_MC_HASHES 256
+
struct tsec_private {
FEC_Enet_Base base; /* Controller base address */
FEC_Enet_Base phy_base; /* Phy base address (not necessarily identical
@@ -684,6 +686,7 @@ struct tsec_private {
unsigned odrops;
unsigned repack;
} stats;
+ uint16_t mc_refcnt[NUM_MC_HASHES];
};
#define NEXT_TXI(mp, i) (((i)+1) < (mp)->tx_ring_size ? (i)+1 : 0 )
@@ -1402,9 +1405,10 @@ rtems_interrupt_level l;
}
static uint8_t
-hash_accept(struct tsec_private *mp, uint32_t tble, const uint8_t *enaddr)
+hash_prog(struct tsec_private *mp, uint32_t tble, const uint8_t *enaddr, int accept)
{
-uint8_t s;
+uint8_t s;
+uint32_t reg, bit;
s = ether_crc32_le(enaddr, ETHER_ADDR_LEN);
@@ -1413,7 +1417,16 @@ uint8_t s;
s = ((s&0x33) << 2) | ((s&0xcc) >> 2);
s = ((s&0x55) << 1) | ((s&0xaa) >> 1);
- fec_wr( mp->base, tble + (s >> (5-2)), (1 << (31 - (s & 31))) );
+ reg = tble + ((s >> (5-2)) & ~3);
+ bit = 1 << (31 - (s & 31));
+
+ if ( accept ) {
+ if ( 0 == mp->mc_refcnt[s]++ )
+ fec_set( mp->base, reg, bit );
+ } else {
+ if ( mp->mc_refcnt[s] > 0 && 0 == --mp->mc_refcnt[s] )
+ fec_clr( mp->base, reg, bit );
+ }
}
void
@@ -1423,6 +1436,8 @@ int i;
for ( i=0; i<8*4; i+=4 ) {
fec_wr( mp->base, TSEC_GADDR0 + i, 0 );
}
+ for ( i=0; i<NUM_MC_HASHES; i++ )
+ mp->mc_refcnt[i] = 0;
}
void
@@ -1432,10 +1447,12 @@ int i;
for ( i=0; i<8*4; i+=4 ) {
fec_wr( mp->base, TSEC_GADDR0 + i, 0xffffffff );
}
+ for ( i=0; i<NUM_MC_HASHES; i++ )
+ mp->mc_refcnt[i]++;
}
-void
-BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, uint8_t *enaddr)
+static void
+mcast_filter_prog(struct tsec_private *mp, uint8_t *enaddr, int accept)
{
static const uint8_t bcst={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if ( ! (enaddr[0] & 0x01) ) {
@@ -1446,7 +1463,19 @@ static const uint8_t bcst={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
/* broadcast; ignore */
return;
}
- hash_accept(mp, TSEC_GADDR0, enaddr);
+ hash_prog(mp, TSEC_GADDR0, enaddr, accept);
+}
+
+void
+BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, uint8_t *enaddr)
+{
+ mcast_filter_prog(mp, enaddr, 1 /* accept */);
+}
+
+void
+BSP_tsec_mcast_filter_accept_del(struct tsec_private *mp, uint8_t *enaddr)
+{
+ mcast_filter_prog(mp, enaddr, 0 /* delete */);
}
void