]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: hibmcge: Implement some .ndo functions
authorJijie Shao <shaojijie@huawei.com>
Tue, 15 Oct 2024 12:35:11 +0000 (20:35 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Mon, 21 Oct 2024 09:26:52 +0000 (11:26 +0200)
Implement the .ndo_open() .ndo_stop() .ndo_set_mac_address()
and .ndo_change_mtu functions().
And .ndo_validate_addr calls the eth_validate_addr function directly

Signed-off-by: Jijie Shao <shaojijie@huawei.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h

index 76ce0d811f648fd200b25db8504a481fa7a76796..5258c5376987700e43835860e0a56e365057b0b7 100644 (file)
@@ -15,6 +15,7 @@
  * ctrl means packet description, data means skb packet data
  */
 #define HBG_ENDIAN_CTRL_LE_DATA_BE     0x0
+#define HBG_PCU_FRAME_LEN_PLUS 4
 
 static bool hbg_hw_spec_is_valid(struct hbg_priv *priv)
 {
@@ -132,6 +133,44 @@ void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable)
        hbg_reg_write(priv, HBG_REG_CF_INTRPT_MSK_ADDR, value);
 }
 
+void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr)
+{
+       hbg_reg_write64(priv, HBG_REG_STATION_ADDR_LOW_2_ADDR, mac_addr);
+}
+
+static void hbg_hw_set_pcu_max_frame_len(struct hbg_priv *priv,
+                                        u16 max_frame_len)
+{
+       max_frame_len = max_t(u32, max_frame_len, ETH_DATA_LEN);
+
+       /* lower two bits of value must be set to 0 */
+       max_frame_len = round_up(max_frame_len, HBG_PCU_FRAME_LEN_PLUS);
+
+       hbg_reg_write_field(priv, HBG_REG_MAX_FRAME_LEN_ADDR,
+                           HBG_REG_MAX_FRAME_LEN_M, max_frame_len);
+}
+
+static void hbg_hw_set_mac_max_frame_len(struct hbg_priv *priv,
+                                        u16 max_frame_size)
+{
+       hbg_reg_write_field(priv, HBG_REG_MAX_FRAME_SIZE_ADDR,
+                           HBG_REG_MAX_FRAME_LEN_M, max_frame_size);
+}
+
+void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu)
+{
+       hbg_hw_set_pcu_max_frame_len(priv, mtu);
+       hbg_hw_set_mac_max_frame_len(priv, mtu);
+}
+
+void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable)
+{
+       hbg_reg_write_field(priv, HBG_REG_PORT_ENABLE_ADDR,
+                           HBG_REG_PORT_ENABLE_TX_B, enable);
+       hbg_reg_write_field(priv, HBG_REG_PORT_ENABLE_ADDR,
+                           HBG_REG_PORT_ENABLE_RX_B, enable);
+}
+
 void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex)
 {
        hbg_reg_write_field(priv, HBG_REG_PORT_MODE_ADDR,
index 4d09bdd41c76529e33282416dda5823e6261cefe..0ce500e907b3e04043d12527c1a386ff514f71d7 100644 (file)
@@ -49,5 +49,8 @@ u32 hbg_hw_get_irq_status(struct hbg_priv *priv);
 void hbg_hw_irq_clear(struct hbg_priv *priv, u32 mask);
 bool hbg_hw_irq_is_enabled(struct hbg_priv *priv, u32 mask);
 void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable);
+void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu);
+void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable);
+void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr);
 
 #endif
index e71ff821c582e66697251964a9487b9e714e996d..3f6f3b381c506b3d1e2de5d451b658a099103f59 100644 (file)
@@ -2,6 +2,7 @@
 // Copyright (c) 2024 Hisilicon Limited.
 
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
 #include "hbg_common.h"
@@ -9,6 +10,90 @@
 #include "hbg_irq.h"
 #include "hbg_mdio.h"
 
+static void hbg_all_irq_enable(struct hbg_priv *priv, bool enabled)
+{
+       struct hbg_irq_info *info;
+       u32 i;
+
+       for (i = 0; i < priv->vectors.info_array_len; i++) {
+               info = &priv->vectors.info_array[i];
+               hbg_hw_irq_enable(priv, info->mask, enabled);
+       }
+}
+
+static int hbg_net_open(struct net_device *netdev)
+{
+       struct hbg_priv *priv = netdev_priv(netdev);
+
+       hbg_all_irq_enable(priv, true);
+       hbg_hw_mac_enable(priv, HBG_STATUS_ENABLE);
+       netif_start_queue(netdev);
+       hbg_phy_start(priv);
+
+       return 0;
+}
+
+static int hbg_net_stop(struct net_device *netdev)
+{
+       struct hbg_priv *priv = netdev_priv(netdev);
+
+       hbg_phy_stop(priv);
+       netif_stop_queue(netdev);
+       hbg_hw_mac_enable(priv, HBG_STATUS_DISABLE);
+       hbg_all_irq_enable(priv, false);
+
+       return 0;
+}
+
+static int hbg_net_set_mac_address(struct net_device *netdev, void *addr)
+{
+       struct hbg_priv *priv = netdev_priv(netdev);
+       u8 *mac_addr;
+
+       mac_addr = ((struct sockaddr *)addr)->sa_data;
+
+       if (!is_valid_ether_addr(mac_addr))
+               return -EADDRNOTAVAIL;
+
+       hbg_hw_set_uc_addr(priv, ether_addr_to_u64(mac_addr));
+       dev_addr_set(netdev, mac_addr);
+
+       return 0;
+}
+
+static void hbg_change_mtu(struct hbg_priv *priv, int new_mtu)
+{
+       u32 frame_len;
+
+       frame_len = new_mtu + VLAN_HLEN * priv->dev_specs.vlan_layers +
+                   ETH_HLEN + ETH_FCS_LEN;
+       hbg_hw_set_mtu(priv, frame_len);
+}
+
+static int hbg_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       struct hbg_priv *priv = netdev_priv(netdev);
+
+       if (netif_running(netdev))
+               return -EBUSY;
+
+       hbg_change_mtu(priv, new_mtu);
+       WRITE_ONCE(netdev->mtu, new_mtu);
+
+       dev_dbg(&priv->pdev->dev,
+               "change mtu from %u to %u\n", netdev->mtu, new_mtu);
+
+       return 0;
+}
+
+static const struct net_device_ops hbg_netdev_ops = {
+       .ndo_open               = hbg_net_open,
+       .ndo_stop               = hbg_net_stop,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = hbg_net_set_mac_address,
+       .ndo_change_mtu         = hbg_net_change_mtu,
+};
+
 static int hbg_init(struct hbg_priv *priv)
 {
        int ret;
@@ -82,6 +167,12 @@ static int hbg_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return ret;
 
        netdev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
+       netdev->max_mtu = priv->dev_specs.max_mtu;
+       netdev->min_mtu = priv->dev_specs.min_mtu;
+       netdev->netdev_ops = &hbg_netdev_ops;
+
+       hbg_change_mtu(priv, ETH_DATA_LEN);
+       hbg_net_set_mac_address(priv->netdev, &priv->dev_specs.mac_addr);
 
        ret = devm_register_netdev(dev, netdev);
        if (ret)
index 8cdf018c2de9715b01c372c7643939269fdbf56b..fbc17ca5564f1f68562d995c8f0b5a23dfc6cb7f 100644 (file)
 #define HBG_REG_SGMII_BASE                     0x10000
 #define HBG_REG_DUPLEX_TYPE_ADDR               (HBG_REG_SGMII_BASE + 0x0008)
 #define HBG_REG_DUPLEX_B                       BIT(0)
+#define HBG_REG_MAX_FRAME_SIZE_ADDR            (HBG_REG_SGMII_BASE + 0x003C)
 #define HBG_REG_PORT_MODE_ADDR                 (HBG_REG_SGMII_BASE + 0x0040)
 #define HBG_REG_PORT_MODE_M                    GENMASK(3, 0)
+#define HBG_REG_PORT_ENABLE_ADDR               (HBG_REG_SGMII_BASE + 0x0044)
+#define HBG_REG_PORT_ENABLE_RX_B               BIT(1)
+#define HBG_REG_PORT_ENABLE_TX_B               BIT(2)
 #define HBG_REG_TRANSMIT_CTRL_ADDR             (HBG_REG_SGMII_BASE + 0x0060)
 #define HBG_REG_TRANSMIT_CTRL_PAD_EN_B         BIT(7)
 #define HBG_REG_TRANSMIT_CTRL_CRC_ADD_B                BIT(6)
@@ -49,6 +53,8 @@
 #define HBG_REG_MODE_CHANGE_EN_B               BIT(0)
 #define HBG_REG_RECV_CTRL_ADDR                 (HBG_REG_SGMII_BASE + 0x01E0)
 #define HBG_REG_RECV_CTRL_STRIP_PAD_EN_B       BIT(3)
+#define HBG_REG_STATION_ADDR_LOW_2_ADDR                (HBG_REG_SGMII_BASE + 0x0210)
+#define HBG_REG_STATION_ADDR_HIGH_2_ADDR       (HBG_REG_SGMII_BASE + 0x0214)
 
 /* PCU */
 #define HBG_REG_CF_INTRPT_MSK_ADDR             (HBG_REG_SGMII_BASE + 0x042C)
@@ -72,6 +78,8 @@
 #define HBG_INT_MSK_RX_B                       BIT(0) /* just used in driver */
 #define HBG_REG_CF_INTRPT_STAT_ADDR            (HBG_REG_SGMII_BASE + 0x0434)
 #define HBG_REG_CF_INTRPT_CLR_ADDR             (HBG_REG_SGMII_BASE + 0x0438)
+#define HBG_REG_MAX_FRAME_LEN_ADDR             (HBG_REG_SGMII_BASE + 0x0444)
+#define HBG_REG_MAX_FRAME_LEN_M                        GENMASK(15, 0)
 #define HBG_REG_RX_BUF_SIZE_ADDR               (HBG_REG_SGMII_BASE + 0x04E4)
 #define HBG_REG_RX_BUF_SIZE_M                  GENMASK(15, 0)
 #define HBG_REG_BUS_CTRL_ADDR                  (HBG_REG_SGMII_BASE + 0x04E8)
@@ -86,6 +94,7 @@
 #define HBG_REG_RX_PKT_MODE_ADDR               (HBG_REG_SGMII_BASE + 0x04F4)
 #define HBG_REG_RX_PKT_MODE_PARSE_MODE_M       GENMASK(22, 21)
 #define HBG_REG_CF_IND_TXINT_MSK_ADDR          (HBG_REG_SGMII_BASE + 0x0694)
+#define HBG_REG_IND_INTR_MASK_B                        BIT(0)
 #define HBG_REG_CF_IND_TXINT_STAT_ADDR         (HBG_REG_SGMII_BASE + 0x0698)
 #define HBG_REG_CF_IND_TXINT_CLR_ADDR          (HBG_REG_SGMII_BASE + 0x069C)
 #define HBG_REG_CF_IND_RXINT_MSK_ADDR          (HBG_REG_SGMII_BASE + 0x06a0)