lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <ebe1a61b-0ba5-455a-b29b-5e1506abe900@iscas.ac.cn>
Date: Mon, 23 Jun 2025 11:28:24 +0800
From: Vivian Wang <wangruikang@...as.ac.cn>
To: Andrew Lunn <andrew@...n.ch>
Cc: Andrew Lunn <andrew+netdev@...n.ch>, "David S. Miller"
 <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>,
 Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>,
 Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>,
 Conor Dooley <conor+dt@...nel.org>, Yixun Lan <dlan@...too.org>,
 Philipp Zabel <p.zabel@...gutronix.de>,
 Paul Walmsley <paul.walmsley@...ive.com>, Palmer Dabbelt
 <palmer@...belt.com>, Albert Ou <aou@...s.berkeley.edu>,
 Alexandre Ghiti <alex@...ti.fr>, Vivian Wang <uwu@...m.page>,
 Lukas Bulwahn <lukas.bulwahn@...hat.com>,
 Geert Uytterhoeven <geert+renesas@...der.be>,
 Parthiban Veerasooran <Parthiban.Veerasooran@...rochip.com>,
 netdev@...r.kernel.org, devicetree@...r.kernel.org,
 linux-riscv@...ts.infradead.org, spacemit@...ts.linux.dev,
 linux-kernel@...r.kernel.org
Subject: Re: [PATCH net-next v2 2/6] net: spacemit: Add K1 Ethernet MAC

Hi Andrew,

Thank you for your suggestions.

On 6/19/25 05:17, Andrew Lunn wrote:
>> +/* The sizes (in bytes) of a ethernet packet */
>> +#define ETHERNET_HEADER_SIZE		14
> Please replace with ETH_HLEN
>
>> +#define MINIMUM_ETHERNET_FRAME_SIZE	64 /* Incl. FCS */
> I assume this device supports VLANS? If so, the minimum should
> actually be 68. You can then use ETH_MIN_MTU
>
>> +#define ETHERNET_FCS_SIZE		4
> ETH_FCS_LEN

I will fix usage of these constants in next version.

>> +static int emac_tx_mem_map(struct emac_priv *priv, struct sk_buff *skb,
>> +			   u32 max_tx_len, u32 frag_num)
>> +{
>> +	struct emac_desc tx_desc, *tx_desc_addr;
>> +	u32 skb_linear_len = skb_headlen(skb);
>> +	struct emac_tx_desc_buffer *tx_buf;
>> +	u32 len, i, f, first, buf_idx = 0;
>> +	struct emac_desc_ring *tx_ring;
>> +	phys_addr_t addr;
>> +
>> +	tx_ring = &priv->tx_ring;
>> +
>> +	i = tx_ring->head;
>> +	first = i;
>> +
>> +	if (++i == tx_ring->total_cnt)
>> +		i = 0;
>> +
>> +	/* If the data is fragmented */
>> +	for (f = 0; f < frag_num; f++) {
>> +		const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
>> +
>> +		len = skb_frag_size(frag);
>> +
>> +		buf_idx = (f + 1) % 2;
>> +
>> +		/* First frag fill into second buffer of first descriptor */
>> +		if (f == 0) {
>> +			tx_buf = &tx_ring->tx_desc_buf[first];
>> +			tx_desc_addr = &((struct emac_desc *)
>> +						 tx_ring->desc_addr)[first];
>> +			memset(&tx_desc, 0, sizeof(tx_desc));
>> +		} else {
>> +			/*
>> +			 * From second frags to more frags,
>> +			 * we only get new descriptor when frag num is odd.
>> +			 */
>> +			if (!buf_idx) {
>> +				tx_buf = &tx_ring->tx_desc_buf[i];
>> +				tx_desc_addr = &((struct emac_desc *)
>> +							 tx_ring->desc_addr)[i];
>> +				memset(&tx_desc, 0, sizeof(tx_desc));
>> +			}
>> +		}
>> +		tx_buf->buf[buf_idx].dma_len = len;
>> +
>> +		addr = skb_frag_dma_map(&priv->pdev->dev, frag, 0,
>> +					skb_frag_size(frag), DMA_TO_DEVICE);
>> +
>> +		if (dma_mapping_error(&priv->pdev->dev, addr)) {
>> +			netdev_err(priv->ndev, "fail to map dma page: %d\n", f);
>> +			goto dma_map_err;
>> +		}
>> +		tx_buf->buf[buf_idx].dma_addr = addr;
>> +
>> +		tx_buf->buf[buf_idx].map_as_page = true;
>> +
>> +		/* Every desc has two buffers for packet */
>> +		if (buf_idx) {
>> +			tx_desc.buffer_addr_2 = addr;
>> +			tx_desc.desc1 |= make_buf_size_2(len);
>> +		} else {
>> +			tx_desc.buffer_addr_1 = addr;
>> +			tx_desc.desc1 = make_buf_size_1(len);
>> +
>> +			if (++i == tx_ring->total_cnt) {
>> +				tx_desc.desc1 |= TX_DESC_1_END_RING;
>> +				i = 0;
>> +			}
>> +		}
>> +
>> +		if (f == 0) {
>> +			*tx_desc_addr = tx_desc;
>> +			continue;
>> +		}
>> +
>> +		if (f == frag_num - 1) {
>> +			tx_desc.desc1 |= TX_DESC_1_LAST_SEGMENT;
>> +			tx_buf->skb = skb;
>> +			if (emac_tx_should_interrupt(priv, frag_num + 1))
>> +				tx_desc.desc1 |=
>> +					TX_DESC_1_INTERRUPT_ON_COMPLETION;
>> +		}
>> +
>> +		*tx_desc_addr = tx_desc;
>> +		dma_wmb();
>> +		WRITE_ONCE(tx_desc_addr->desc0, tx_desc.desc0 | TX_DESC_0_OWN);
>> +	}
>> +
>> +	/* fill out first descriptor for skb linear data */
>> +	tx_buf = &tx_ring->tx_desc_buf[first];
>> +
>> +	tx_buf->buf[0].dma_len = skb_linear_len;
>> +
>> +	addr = dma_map_single(&priv->pdev->dev, skb->data, skb_linear_len,
>> +			      DMA_TO_DEVICE);
>> +	if (dma_mapping_error(&priv->pdev->dev, addr)) {
>> +		netdev_err(priv->ndev, "dma_map_single failed\n");
>> +		goto dma_map_err;
>> +	}
>> +
>> +	tx_buf->buf[0].dma_addr = addr;
>> +
>> +	tx_buf->buf[0].buff_addr = skb->data;
>> +	tx_buf->buf[0].map_as_page = false;
>> +
>> +	/* Fill TX descriptor */
>> +	tx_desc_addr = &((struct emac_desc *)tx_ring->desc_addr)[first];
>> +
>> +	tx_desc = *tx_desc_addr;
>> +
>> +	tx_desc.buffer_addr_1 = addr;
>> +	tx_desc.desc1 |= make_buf_size_1(skb_linear_len);
>> +	tx_desc.desc1 |= TX_DESC_1_FIRST_SEGMENT;
>> +
>> +	/* If last desc for ring, set end ring flag */
>> +	if (first == tx_ring->total_cnt - 1)
>> +		tx_desc.desc1 |= TX_DESC_1_END_RING;
>> +
>> +	/*
>> +	 * If frag_num is more than 1, data need another desc, so current
>> +	 * descriptor isn't last piece of packet data.
>> +	 */
>> +	tx_desc.desc1 |= frag_num > 1 ? 0 : TX_DESC_1_LAST_SEGMENT;
>> +
>> +	if (frag_num <= 1 && emac_tx_should_interrupt(priv, 1))
>> +		tx_desc.desc1 |= TX_DESC_1_INTERRUPT_ON_COMPLETION;
>> +
>> +	/* Only last descriptor has skb pointer */
>> +	if (tx_desc.desc1 & TX_DESC_1_LAST_SEGMENT)
>> +		tx_buf->skb = skb;
>> +
>> +	*tx_desc_addr = tx_desc;
>> +	dma_wmb();
>> +	WRITE_ONCE(tx_desc_addr->desc0, tx_desc.desc0 | TX_DESC_0_OWN);
>> +
>> +	emac_dma_start_transmit(priv);
>> +
>> +	tx_ring->head = i;
>> +
>> +	return 0;
>> +
>> +dma_map_err:
>> +	dev_kfree_skb_any(skb);
>> +	priv->ndev->stats.tx_dropped++;
>> +	return 0;
>> +}
> This is a rather large function. Can parts of it be pulled out into
> helpers? The Coding style document says:
>
>   Functions should be short and sweet, and do just one thing. They
>   should fit on one or two screenfuls of text (the ISO/ANSI screen
>   size is 80x24, as we all know), and do one thing and do that well.
I will reorganize this function in next version.
>> +static int emac_mdio_init(struct emac_priv *priv)
>> +{
>> +	struct device *dev = &priv->pdev->dev;
>> +	struct device_node *mii_np;
>> +	struct mii_bus *mii;
>> +	int ret;
>> +
>> +	mii_np = of_get_available_child_by_name(dev->of_node, "mdio-bus");
>> +	if (!mii_np) {
>> +		if (of_phy_is_fixed_link(dev->of_node)) {
>> +			if ((of_phy_register_fixed_link(dev->of_node) < 0))
>> +				return -ENODEV;
>> +
>> +			return 0;
>> +		}
>> +
>> +		dev_info(dev, "No mdio-bus child node found");
>> +		return 0;
>> +	}
> An mdio-bus node is normally optional. You can pass NULL to
> devm_of_mdiobus_register() and it will do the correct thing, register
> the bus, and scan it for devices.
>
> An MDIO bus and fixed link are also not mutually exclusive. When the
> MAC is connected to an Ethernet switch, you often see an fixed-link,
> and have an MDIO bus, with the switches management interface being
> MDIO.

I understand now. I will fix the handling of fixed-link and mdio-bus in
the next version.

>> +static int emac_ethtool_get_regs_len(struct net_device *dev)
>> +{
>> +	return EMAC_REG_SPACE_SIZE;
>> +}
>> +
>> +static void emac_ethtool_get_regs(struct net_device *dev,
>> +				  struct ethtool_regs *regs, void *space)
>> +{
>> +	struct emac_priv *priv = netdev_priv(dev);
>> +	u32 *reg_space = space;
>> +	int i;
>> +
>> +	regs->version = 1;
>> +
>> +	for (i = 0; i < EMAC_DMA_REG_CNT; i++)
>> +		reg_space[i] = emac_rd(priv, DMA_CONFIGURATION + i * 4);
>> +
>> +	for (i = 0; i < EMAC_MAC_REG_CNT; i++)
>> +		reg_space[i + EMAC_DMA_REG_CNT] =
>> +			emac_rd(priv, MAC_GLOBAL_CONTROL + i * 4);
>> +}
> Given this implementation, it would be more readable, and less future
> extension error prone, if emac_ethtool_get_regs_len() returned
>
> EMAC_DMA_REG_CNT + EMAC_MAC_REG_CNT
I will simplify this next version.
>> +static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
>> +{
>> +	if (!netif_running(ndev))
>> +		return -EINVAL;
>> +
>> +	return phy_mii_ioctl(ndev->phydev, rq, cmd);
>> +}
> phy_do_ioctl_running().
I will simplify in next version.
>> +static int emac_phy_connect(struct net_device *ndev)
>> +{
>> +	struct emac_priv *priv = netdev_priv(ndev);
>> +	struct device *dev = &priv->pdev->dev;
>> +	struct phy_device *phydev;
>> +	struct device_node *np;
>> +	int ret;
>> +
>> +	ret = of_get_phy_mode(dev->of_node, &priv->phy_interface);
>> +	if (ret) {
>> +		dev_err(dev, "No phy-mode found");
>> +		return ret;
>> +	}
>> +
>> +	np = of_parse_phandle(dev->of_node, "phy-handle", 0);
>> +	if (!np && of_phy_is_fixed_link(dev->of_node))
>> +		np = of_node_get(dev->of_node);
>> +	if (!np) {
>> +		dev_err(dev, "No PHY specified");
>> +		return -ENODEV;
>> +	}
>> +
>> +	ret = emac_phy_interface_config(priv);
>> +	if (ret)
>> +		goto err_node_put;
>> +
>> +	phydev = of_phy_connect(ndev, np, &emac_adjust_link, 0,
>> +				priv->phy_interface);
>> +	if (IS_ERR_OR_NULL(phydev)) {
>> +		dev_err(dev, "Could not attach to PHY\n");
>> +		ret = phydev ? PTR_ERR(phydev) : -ENODEV;
>> +		goto err_node_put;
>> +	}
> The documentation for of_phy_connect() says:
>
>  * If successful, returns a pointer to the phy_device with the embedded
>  * struct device refcount incremented by one, or NULL on failure. The
>  * refcount must be dropped by calling phy_disconnect() or phy_detach().
>
> An error code is not possible. So you can simply this.
> 	

I will simplify this in next version.

Thanks,
Vivian "dramforever" Wang


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ