net/cadence_gem: Implement RX descriptor match mode flags

The various Rx packet address matching mode flags were not being set in
the rx descriptor. Implement.

Reported-by: Deepika Dhamija <deepika@xilinx.com>
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 6002a24a6a8ceaa11d3009ab5392840d1c084b28.1386136219.git.peter.crosthwaite@xilinx.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Crosthwaite 2013-12-03 21:57:24 -08:00 committed by Peter Maydell
parent 06c2fe951d
commit 63af1e0cff
1 changed files with 69 additions and 13 deletions

View File

@ -222,8 +222,13 @@
#define PHY_REG_INT_ST_ENERGY 0x0010
/***********************************************************************/
#define GEM_RX_REJECT 1
#define GEM_RX_ACCEPT 0
#define GEM_RX_REJECT (-1)
#define GEM_RX_PROMISCUOUS_ACCEPT (-2)
#define GEM_RX_BROADCAST_ACCEPT (-3)
#define GEM_RX_MULTICAST_HASH_ACCEPT (-4)
#define GEM_RX_UNICAST_HASH_ACCEPT (-5)
#define GEM_RX_SAR_ACCEPT 0
/***********************************************************************/
@ -236,6 +241,12 @@
#define DESC_0_RX_WRAP 0x00000002
#define DESC_0_RX_OWNERSHIP 0x00000001
#define R_DESC_1_RX_SAR_SHIFT 25
#define R_DESC_1_RX_SAR_LENGTH 2
#define R_DESC_1_RX_UNICAST_HASH (1 << 29)
#define R_DESC_1_RX_MULTICAST_HASH (1 << 30)
#define R_DESC_1_RX_BROADCAST (1 << 31)
#define DESC_1_RX_SOF 0x00004000
#define DESC_1_RX_EOF 0x00008000
@ -315,6 +326,27 @@ static inline void rx_desc_set_length(unsigned *desc, unsigned len)
desc[1] |= len;
}
static inline void rx_desc_set_broadcast(unsigned *desc)
{
desc[1] |= R_DESC_1_RX_BROADCAST;
}
static inline void rx_desc_set_unicast_hash(unsigned *desc)
{
desc[1] |= R_DESC_1_RX_UNICAST_HASH;
}
static inline void rx_desc_set_multicast_hash(unsigned *desc)
{
desc[1] |= R_DESC_1_RX_MULTICAST_HASH;
}
static inline void rx_desc_set_sar(unsigned *desc, int sar_idx)
{
desc[1] = deposit32(desc[1], R_DESC_1_RX_SAR_SHIFT, R_DESC_1_RX_SAR_LENGTH,
sar_idx);
}
#define TYPE_CADENCE_GEM "cadence_gem"
#define GEM(obj) OBJECT_CHECK(GemState, (obj), TYPE_CADENCE_GEM)
@ -529,7 +561,10 @@ static unsigned calc_mac_hash(const uint8_t *mac)
* Accept or reject this destination address?
* Returns:
* GEM_RX_REJECT: reject
* GEM_RX_ACCEPT: accept
* >= 0: Specific address accept (which matched SAR is returned)
* others for various other modes of accept:
* GEM_RM_PROMISCUOUS_ACCEPT, GEM_RX_BROADCAST_ACCEPT,
* GEM_RX_MULTICAST_HASH_ACCEPT or GEM_RX_UNICAST_HASH_ACCEPT
*/
static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
{
@ -538,7 +573,7 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
/* Promiscuous mode? */
if (s->regs[GEM_NWCFG] & GEM_NWCFG_PROMISC) {
return GEM_RX_ACCEPT;
return GEM_RX_PROMISCUOUS_ACCEPT;
}
if (!memcmp(packet, broadcast_addr, 6)) {
@ -546,7 +581,7 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
if (s->regs[GEM_NWCFG] & GEM_NWCFG_BCAST_REJ) {
return GEM_RX_REJECT;
}
return GEM_RX_ACCEPT;
return GEM_RX_BROADCAST_ACCEPT;
}
/* Accept packets -w- hash match? */
@ -557,24 +592,24 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
hash_index = calc_mac_hash(packet);
if (hash_index < 32) {
if (s->regs[GEM_HASHLO] & (1<<hash_index)) {
return GEM_RX_ACCEPT;
return packet[0] == 0x01 ? GEM_RX_MULTICAST_HASH_ACCEPT :
GEM_RX_UNICAST_HASH_ACCEPT;
}
} else {
hash_index -= 32;
if (s->regs[GEM_HASHHI] & (1<<hash_index)) {
return GEM_RX_ACCEPT;
return packet[0] == 0x01 ? GEM_RX_MULTICAST_HASH_ACCEPT :
GEM_RX_UNICAST_HASH_ACCEPT;
}
}
}
/* Check all 4 specific addresses */
gem_spaddr = (uint8_t *)&(s->regs[GEM_SPADDR1LO]);
for (i = 0; i < 4; i++) {
if (!memcmp(packet, gem_spaddr, 6)) {
return GEM_RX_ACCEPT;
for (i = 3; i >= 0; i--) {
if (!memcmp(packet, gem_spaddr + 8 * i, 6)) {
return GEM_RX_SAR_ACCEPT + i;
}
gem_spaddr += 8;
}
/* No address match; reject the packet */
@ -611,11 +646,13 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
uint8_t rxbuf[2048];
uint8_t *rxbuf_ptr;
bool first_desc = true;
int maf;
s = qemu_get_nic_opaque(nc);
/* Is this destination MAC address "for us" ? */
if (gem_mac_address_filter(s, buf) == GEM_RX_REJECT) {
maf = gem_mac_address_filter(s, buf);
if (maf == GEM_RX_REJECT) {
return -1;
}
@ -706,6 +743,25 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
rx_desc_set_length(s->rx_desc, size);
}
rx_desc_set_ownership(s->rx_desc);
switch (maf) {
case GEM_RX_PROMISCUOUS_ACCEPT:
break;
case GEM_RX_BROADCAST_ACCEPT:
rx_desc_set_broadcast(s->rx_desc);
break;
case GEM_RX_UNICAST_HASH_ACCEPT:
rx_desc_set_unicast_hash(s->rx_desc);
break;
case GEM_RX_MULTICAST_HASH_ACCEPT:
rx_desc_set_multicast_hash(s->rx_desc);
break;
case GEM_RX_REJECT:
abort();
default: /* SAR */
rx_desc_set_sar(s->rx_desc, maf);
}
/* Descriptor write-back. */
cpu_physical_memory_write(s->rx_desc_addr,
(uint8_t *)s->rx_desc, sizeof(s->rx_desc));