drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c
Extension
.c
Size
88038 bytes
Lines
3148
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

netdev_for_each_uc_addr(ha, netdev) {
			xlgmac_set_mac_reg(pdata, ha, &mac_reg);
			addn_macs--;
		}

		if (netdev_mc_count(netdev) > addn_macs) {
			xlgmac_set_all_multicast_mode(pdata, 1);
		} else {
			netdev_for_each_mc_addr(ha, netdev) {
				xlgmac_set_mac_reg(pdata, ha, &mac_reg);
				addn_macs--;
			}
		}
	}

	/* Clear remaining additional MAC address entries */
	while (addn_macs--)
		xlgmac_set_mac_reg(pdata, NULL, &mac_reg);
}

static void xlgmac_set_mac_hash_table(struct xlgmac_pdata *pdata)
{
	unsigned int hash_table_shift, hash_table_count;
	u32 hash_table[XLGMAC_MAC_HASH_TABLE_SIZE];
	struct net_device *netdev = pdata->netdev;
	struct netdev_hw_addr *ha;
	unsigned int hash_reg;
	unsigned int i;
	u32 crc;

	hash_table_shift = 26 - (pdata->hw_feat.hash_table_size >> 7);
	hash_table_count = pdata->hw_feat.hash_table_size / 32;
	memset(hash_table, 0, sizeof(hash_table));

	/* Build the MAC Hash Table register values */
	netdev_for_each_uc_addr(ha, netdev) {
		crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN));
		crc >>= hash_table_shift;
		hash_table[crc >> 5] |= (1 << (crc & 0x1f));
	}

	netdev_for_each_mc_addr(ha, netdev) {
		crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN));
		crc >>= hash_table_shift;
		hash_table[crc >> 5] |= (1 << (crc & 0x1f));
	}

	/* Set the MAC Hash Table registers */
	hash_reg = MAC_HTR0;
	for (i = 0; i < hash_table_count; i++) {
		writel(hash_table[i], pdata->mac_regs + hash_reg);
		hash_reg += MAC_HTR_INC;
	}
}

static int xlgmac_add_mac_addresses(struct xlgmac_pdata *pdata)
{
	if (pdata->hw_feat.hash_table_size)
		xlgmac_set_mac_hash_table(pdata);
	else
		xlgmac_set_mac_addn_addrs(pdata);

	return 0;
}

static void xlgmac_config_mac_address(struct xlgmac_pdata *pdata)
{
	u32 regval;

	xlgmac_set_mac_address(pdata, pdata->netdev->dev_addr);

	/* Filtering is done using perfect filtering and hash filtering */
	if (pdata->hw_feat.hash_table_size) {
		regval = readl(pdata->mac_regs + MAC_PFR);
		regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_HPF_POS,
					     MAC_PFR_HPF_LEN, 1);
		regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_HUC_POS,
					     MAC_PFR_HUC_LEN, 1);
		regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_HMC_POS,
					     MAC_PFR_HMC_LEN, 1);
		writel(regval, pdata->mac_regs + MAC_PFR);
	}
}

static void xlgmac_config_jumbo_enable(struct xlgmac_pdata *pdata)
{
	unsigned int val;
	u32 regval;

	val = (pdata->netdev->mtu > XLGMAC_STD_PACKET_MTU) ? 1 : 0;

Annotation

Implementation Notes