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] [thread-next>] [day] [month] [year] [list]
Message-ID: <440e3913-e41a-446d-92ba-b3599f57170e@iscas.ac.cn>
Date: Mon, 16 Jun 2025 11:04:06 +0800
From: Vivian Wang <wangruikang@...as.ac.cn>
To: Vadim Fedorenko <vadim.fedorenko@...ux.dev>,
 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>,
 Paul Walmsley <paul.walmsley@...ive.com>, Palmer Dabbelt
 <palmer@...belt.com>, Albert Ou <aou@...s.berkeley.edu>,
 Alexandre Ghiti <alex@...ti.fr>, Richard Cochran <richardcochran@...il.com>,
 Philipp Zabel <p.zabel@...gutronix.de>, Russell King <linux@...linux.org.uk>
Cc: Vivian Wang <uwu@...m.page>, 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 2/4] net: spacemit: Add K1 Ethernet MAC

Hi Vadim,

Thanks for the review.

On 6/13/25 23:04, Vadim Fedorenko wrote:
> On 13/06/2025 03:15, Vivian Wang wrote:
>> The Ethernet MACs found on SpacemiT K1 appears to be a custom design
>> that only superficially resembles some other embedded MACs. SpacemiT
>> refers to them as "EMAC", so let's just call the driver "k1_emac".
>>
>> This driver is based on "k1x-emac" in the same directory in the vendor's
>> tree [1]. Some debugging tunables have been fixed to vendor-recommended
>> defaults, and PTP support is not included yet.
>>
>> [1]: https://github.com/spacemit-com/linux-k1x
>>
>> Signed-off-by: Vivian Wang <wangruikang@...as.ac.cn>
>> ---
>>   drivers/net/ethernet/Kconfig            |    1 +
>>   drivers/net/ethernet/Makefile           |    1 +
>>   drivers/net/ethernet/spacemit/Kconfig   |   29 +
>>   drivers/net/ethernet/spacemit/Makefile  |    6 +
>>   drivers/net/ethernet/spacemit/k1_emac.c | 2059
>> +++++++++++++++++++++++++++++++
>>   drivers/net/ethernet/spacemit/k1_emac.h |  416 +++++++
>>   6 files changed, 2512 insertions(+)
>
> [...]
>
>> +
>> +static int emac_init_hw(struct emac_priv *priv)
>> +{
>> +    u32 val = 0;
>> +
>> +    regmap_set_bits(priv->regmap_apmu,
>> +            priv->regmap_apmu_offset + APMU_EMAC_CTRL_REG,
>> +            AXI_SINGLE_ID);
>> +
>> +    /* Disable transmit and receive units */
>> +    emac_wr(priv, MAC_RECEIVE_CONTROL, 0x0);
>> +    emac_wr(priv, MAC_TRANSMIT_CONTROL, 0x0);
>> +
>> +    /* Enable mac address 1 filtering */
>> +    emac_wr(priv, MAC_ADDRESS_CONTROL, MREGBIT_MAC_ADDRESS1_ENABLE);
>> +
>> +    /* Zero initialize the multicast hash table */
>> +    emac_wr(priv, MAC_MULTICAST_HASH_TABLE1, 0x0);
>> +    emac_wr(priv, MAC_MULTICAST_HASH_TABLE2, 0x0);
>> +    emac_wr(priv, MAC_MULTICAST_HASH_TABLE3, 0x0);
>> +    emac_wr(priv, MAC_MULTICAST_HASH_TABLE4, 0x0);
>> +
>> +    /* Configure Thresholds */
>> +    emac_wr(priv, MAC_TRANSMIT_FIFO_ALMOST_FULL,
>> DEFAULT_TX_ALMOST_FULL);
>> +    emac_wr(priv, MAC_TRANSMIT_PACKET_START_THRESHOLD,
>> DEFAULT_TX_THRESHOLD);
>> +    emac_wr(priv, MAC_RECEIVE_PACKET_START_THRESHOLD,
>> DEFAULT_RX_THRESHOLD);
>> +
>> +    /* RX IRQ mitigation */
>> +    val = EMAC_RX_FRAMES & MREGBIT_RECEIVE_IRQ_FRAME_COUNTER_MASK;
>> +    val |= (EMAC_RX_COAL_TIMEOUT
>> +        << MREGBIT_RECEIVE_IRQ_TIMEOUT_COUNTER_SHIFT) &
>> +           MREGBIT_RECEIVE_IRQ_TIMEOUT_COUNTER_MASK;
>> +
>> +    val |= MREGBIT_RECEIVE_IRQ_MITIGATION_ENABLE;
>> +    emac_wr(priv, DMA_RECEIVE_IRQ_MITIGATION_CTRL, val);
>> +
>> +    /* Disable and reset DMA */
>> +    emac_wr(priv, DMA_CONTROL, 0x0);
>> +
>> +    emac_wr(priv, DMA_CONFIGURATION, MREGBIT_SOFTWARE_RESET);
>> +    usleep_range(9000, 10000);
>> +    emac_wr(priv, DMA_CONFIGURATION, 0x0);
>> +    usleep_range(9000, 10000);
>> +
>> +    val |= MREGBIT_STRICT_BURST;
>> +    val |= MREGBIT_DMA_64BIT_MODE;
>> +    val |= DEFAULT_DMA_BURST;
>
>        val here will have bits of MREGBIT_RECEIVE_IRQ_FRAME_COUNTER_MASK
>        and MREGBIT_RECEIVE_IRQ_TIMEOUT_COUNTER_MASK set. Not sure if
>        it's intended
>
Thanks for the catch. I will fix this in the next version.
>> +
>> +    emac_wr(priv, DMA_CONFIGURATION, val);
>> +
>> +    return 0;
>> +}
>> +
>> +static void emac_set_mac_addr(struct emac_priv *priv, const unsigned
>> char *addr)
>> +{
>> +    emac_wr(priv, MAC_ADDRESS1_HIGH, ((addr[1] << 8) | addr[0]));
>> +    emac_wr(priv, MAC_ADDRESS1_MED, ((addr[3] << 8) | addr[2]));
>> +    emac_wr(priv, MAC_ADDRESS1_LOW, ((addr[5] << 8) | addr[4]));
>> +}
>> +
>> +static void emac_dma_start_transmit(struct emac_priv *priv)
>> +{
>> +    emac_wr(priv, DMA_TRANSMIT_POLL_DEMAND, 0xFF);
>> +}
>> +
>> +static void emac_enable_interrupt(struct emac_priv *priv)
>> +{
>> +    u32 val;
>> +
>> +    val = emac_rd(priv, DMA_INTERRUPT_ENABLE);
>> +    val |= MREGBIT_TRANSMIT_TRANSFER_DONE_INTR_ENABLE;
>> +    val |= MREGBIT_RECEIVE_TRANSFER_DONE_INTR_ENABLE;
>> +    emac_wr(priv, DMA_INTERRUPT_ENABLE, val);
>> +}
>> +
>> +static void emac_disable_interrupt(struct emac_priv *priv)
>> +{
>> +    u32 val;
>> +
>> +    val = emac_rd(priv, DMA_INTERRUPT_ENABLE);
>> +    val &= ~MREGBIT_TRANSMIT_TRANSFER_DONE_INTR_ENABLE;
>> +    val &= ~MREGBIT_RECEIVE_TRANSFER_DONE_INTR_ENABLE;
>> +    emac_wr(priv, DMA_INTERRUPT_ENABLE, val);
>> +}
>> +
>> +static inline u32 emac_tx_avail(struct emac_priv *priv)
>
> please, avoid "static inline" in .c files, let the compiler to choose
> what to inline.
>
I will remove inline in next version.
>> +{
>> +    struct emac_desc_ring *tx_ring = &priv->tx_ring;
>> +    u32 avail;
>> +
>> +    if (tx_ring->tail > tx_ring->head)
>> +        avail = tx_ring->tail - tx_ring->head - 1;
>> +    else
>> +        avail = tx_ring->total_cnt - tx_ring->head + tx_ring->tail - 1;
>> +
>> +    return avail;
>> +}
>> +
[...]
>> +static int emac_up(struct emac_priv *priv)
>> +{
>> +    struct platform_device *pdev = priv->pdev;
>> +    struct net_device *ndev = priv->ndev;
>> +    int ret;
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +    pm_runtime_get_sync(&pdev->dev);
>> +#endif
>
> Not sure why do you depend on CONFIG_PM_SLEEP, but
> pm_runtime_get_sync/pm_runtime_put_sync are available with and without
> CONFIG_PM, no need
> for ifdef
>
I will remove #ifdef in next version.
>> +
>> +    ret = emac_phy_connect(ndev);
>> +    if (ret) {
>> +        dev_err(&pdev->dev, "emac_phy_connect failed\n");
>> +        goto err;
>> +    }
>> +
>> +    emac_init_hw(priv);
>> +
>> +    emac_set_mac_addr(priv, ndev->dev_addr);
>> +    emac_configure_tx(priv);
>> +    emac_configure_rx(priv);
>> +
>> +    emac_alloc_rx_desc_buffers(priv);
>> +
>> +    if (ndev->phydev)
>> +        phy_start(ndev->phydev);
>> +
>> +    ret = request_irq(priv->irq, emac_interrupt_handler, IRQF_SHARED,
>> +              ndev->name, ndev);
>> +    if (ret) {
>> +        dev_err(&pdev->dev, "request_irq failed\n");
>> +        goto request_irq_failed;
>> +    }
>> +
>> +    /* Don't enable MAC interrupts */
>> +    emac_wr(priv, MAC_INTERRUPT_ENABLE, 0x0);
>> +
>> +    /* Enable DMA interrupts */
>> +    emac_wr(priv, DMA_INTERRUPT_ENABLE,
>> +        MREGBIT_TRANSMIT_TRANSFER_DONE_INTR_ENABLE |
>> +            MREGBIT_TRANSMIT_DMA_STOPPED_INTR_ENABLE |
>> +            MREGBIT_RECEIVE_TRANSFER_DONE_INTR_ENABLE |
>> +            MREGBIT_RECEIVE_DMA_STOPPED_INTR_ENABLE |
>> +            MREGBIT_RECEIVE_MISSED_FRAME_INTR_ENABLE);
>> +
>> +    napi_enable(&priv->napi);
>> +
>> +    netif_start_queue(ndev);
>> +    return 0;
>> +
>> +request_irq_failed:
>> +    emac_reset_hw(priv);
>> +    if (ndev->phydev) {
>> +        phy_stop(ndev->phydev);
>> +        phy_disconnect(ndev->phydev);
>> +    }
>> +err:
>> +#ifdef CONFIG_PM_SLEEP
>> +    pm_runtime_put_sync(&pdev->dev);
>> +#endif
>> +    return ret;
>> +}
>> +
>> +static int emac_down(struct emac_priv *priv)
>> +{
>> +    struct platform_device *pdev = priv->pdev;
>> +    struct net_device *ndev = priv->ndev;
>> +
>> +    netif_stop_queue(ndev);
>> +
>> +    if (ndev->phydev) {
>> +        phy_stop(ndev->phydev);
>> +        phy_disconnect(ndev->phydev);
>> +    }
>> +
>> +    priv->link = false;
>> +    priv->duplex = DUPLEX_UNKNOWN;
>> +    priv->speed = SPEED_UNKNOWN;
>> +
>> +    emac_wr(priv, MAC_INTERRUPT_ENABLE, 0x0);
>> +    emac_wr(priv, DMA_INTERRUPT_ENABLE, 0x0);
>> +
>> +    free_irq(priv->irq, ndev);
>> +
>> +    napi_disable(&priv->napi);
>> +
>> +    emac_reset_hw(priv);
>> +    netif_carrier_off(ndev);
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +    pm_runtime_put_sync(&pdev->dev);
>> +#endif
>
> ditto
>
I will remove #ifdef in next version.

Thanks again for your review.

Regards,
Vivian "dramforever" Wang

>> +    return 0;
>> +}
>> +
>
> [...]


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ