From e8ac5d470eb766b4122c153b209da24ebdc1a2bc Mon Sep 17 00:00:00 2001 From: Till Straumann Date: Mon, 17 Aug 2009 14:27:55 +0000 Subject: 2009-08-17 Till Straumann * 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. --- c/src/lib/libbsp/powerpc/mvme3100/ChangeLog | 8 +++++ .../libbsp/powerpc/mvme3100/network/if_tsec_pub.h | 34 +++++++++++++----- c/src/lib/libbsp/powerpc/mvme3100/network/tsec.c | 41 ++++++++++++++++++---- 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 + + * 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 * 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,35 +182,51 @@ 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. */ 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; imc_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; imc_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 -- cgit v1.2.3