switch (priv->family_id) {
case RTL8380_FAMILY_ID:
rtl838x_hw_en_rxtx(priv);
- /* Trap IGMP traffic to CPU-Port */
+ /* Trap IGMP/MLD traffic to CPU-Port */
sw_w32(0x3, RTL838X_SPCL_TRAP_IGMP_CTRL);
/* Flush learned FDB entries on link down of a port */
sw_w32_mask(0, BIT(7), RTL838X_L2_CTRL_0);
break;
+
case RTL8390_FAMILY_ID:
rtl839x_hw_en_rxtx(priv);
+ // Trap MLD and IGMP messages to CPU_PORT
sw_w32(0x3, RTL839X_SPCL_TRAP_IGMP_CTRL);
/* Flush learned FDB entries on link down of a port */
sw_w32_mask(0, BIT(7), RTL839X_L2_CTRL_0);
break;
+
case RTL9300_FAMILY_ID:
rtl93xx_hw_en_rxtx(priv);
/* Flush learned FDB entries on link down of a port */
sw_w32_mask(0, BIT(7), RTL930X_L2_CTRL);
- sw_w32_mask(BIT(28), 0, RTL930X_L2_PORT_SABLK_CTRL);
- sw_w32_mask(BIT(28), 0, RTL930X_L2_PORT_DABLK_CTRL);
+ // Trap MLD and IGMP messages to CPU_PORT
+ sw_w32((0x2 << 3) | 0x2, RTL930X_VLAN_APP_PKT_CTRL);
break;
case RTL9310_FAMILY_ID:
rtl93xx_hw_en_rxtx(priv);
-// TODO: Add trapping of IGMP frames to CPU-port
break;
}
/* Check for DSA tagging at the end of the buffer */
if (netdev_uses_dsa(dev) && skb->data[len-4] == 0x80 && skb->data[len-3] > 0
- && skb->data[len-3] < 28 && skb->data[len-2] == 0x10
+ && skb->data[len-3] < priv->cpu_port && skb->data[len-2] == 0x10
&& skb->data[len-1] == 0x00) {
/* Reuse tag space for CRC if possible */
dest_port = skb->data[len-3];
+ skb->data[len-4] = skb->data[len-3] = skb->data[len-2] = skb->data[len-1] = 0x00;
len -= 4;
}
len += 4; // Add space for CRC
- // On RTL8380 SoCs, the packet needs extra padding
- if (priv->family_id == RTL8380_FAMILY_ID) {
- if (len < ETH_ZLEN)
- len = ETH_ZLEN; // SoC not automatically padding to ETH_ZLEN
- else
- len += 4;
- }
-
if (skb_padto(skb, len)) {
ret = NETDEV_TX_OK;
goto txdone;
h = &ring->tx_header[q][ring->c_tx[q]];
h->size = len;
h->len = len;
+ // On RTL8380 SoCs, small packet lengths being sent need adjustments
+ if (priv->family_id == RTL8380_FAMILY_ID) {
+ if (len < ETH_ZLEN - 4)
+ h->len -= 4;
+ }
priv->r->create_tx_header(h, dest_port, skb->priority >> 1);
struct device_node *dn = pdev->dev.of_node;
struct rtl838x_eth_priv *priv;
struct resource *res, *mem;
- const void *mac;
phy_interface_t phy_mode;
struct phylink *phylink;
int err = 0, i, rxrings, rxringlen;
* 1) from device tree data
* 2) from internal registers set by bootloader
*/
- mac = of_get_mac_address(pdev->dev.of_node);
- if (!IS_ERR(mac)) {
- memcpy(dev->dev_addr, mac, ETH_ALEN);
- rtl838x_set_mac_hw(dev, (u8 *)mac);
+ of_get_mac_address(pdev->dev.of_node, dev->dev_addr);
+ if (is_valid_ether_addr(dev->dev_addr))) {
+ rtl838x_set_mac_hw(dev, (u8 *)dev->dev_addr);
} else {
dev->dev_addr[0] = (sw_r32(priv->r->mac) >> 8) & 0xff;
dev->dev_addr[1] = sw_r32(priv->r->mac) & 0xff;