Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6140cc20 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'Support-of-Flow-Director-in-HNS3-Ethernet-Driver-for-HiP08-Rev2-SoC'



Salil Mehta says:

====================
Support of Flow Director in HNS3 Ethernet Driver for HiP08 Rev2 SoC

This patch-set adds the support of FD(Flow Director) in the HNS3 PF driver
for HiP08 Rev2(0x21) SoC of Hisilicon. FD can be used in filtering the flows
and deciding to drop the flow or forward it to paricular queue.

Configuration consists of rules with input keys and actions. The rules are
stored in TCAM.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 26cf48a6 c17852a8
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@
#define HNAE3_KNIC_CLIENT_INITED_B		0x3
#define HNAE3_UNIC_CLIENT_INITED_B		0x4
#define HNAE3_ROCE_CLIENT_INITED_B		0x5
#define HNAE3_DEV_SUPPORT_FD_B			0x6

#define HNAE3_DEV_SUPPORT_ROCE_DCB_BITS (BIT(HNAE3_DEV_SUPPORT_DCB_B) |\
		BIT(HNAE3_DEV_SUPPORT_ROCE_B))
@@ -61,6 +62,9 @@
#define hnae3_dev_dcb_supported(hdev) \
	hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_DCB_B)

#define hnae3_dev_fd_supported(hdev) \
	hnae3_get_bit((hdev)->ae_dev->flag, HNAE3_DEV_SUPPORT_FD_B)

#define ring_ptr_move_fw(ring, p) \
	((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
#define ring_ptr_move_bw(ring, p) \
@@ -175,6 +179,7 @@ struct hnae3_ae_dev {
	struct list_head node;
	u32 flag;
	enum hnae3_dev_type dev_type;
	enum hnae3_reset_type reset_type;
	void *priv;
};

@@ -412,6 +417,20 @@ struct hnae3_ae_ops {
	void (*get_link_mode)(struct hnae3_handle *handle,
			      unsigned long *supported,
			      unsigned long *advertising);
	int (*add_fd_entry)(struct hnae3_handle *handle,
			    struct ethtool_rxnfc *cmd);
	int (*del_fd_entry)(struct hnae3_handle *handle,
			    struct ethtool_rxnfc *cmd);
	void (*del_all_fd_entries)(struct hnae3_handle *handle,
				   bool clear_list);
	int (*get_fd_rule_cnt)(struct hnae3_handle *handle,
			       struct ethtool_rxnfc *cmd);
	int (*get_fd_rule_info)(struct hnae3_handle *handle,
				struct ethtool_rxnfc *cmd);
	int (*get_fd_all_rules)(struct hnae3_handle *handle,
				struct ethtool_rxnfc *cmd, u32 *rule_locs);
	int (*restore_fd_rules)(struct hnae3_handle *handle);
	void (*enable_fd)(struct hnae3_handle *handle, bool enable);
};

struct hnae3_dcb_ops {
+54 −1
Original line number Diff line number Diff line
@@ -1285,6 +1285,13 @@ static int hns3_nic_set_features(struct net_device *netdev,
			return ret;
	}

	if ((changed & NETIF_F_NTUPLE) && h->ae_algo->ops->enable_fd) {
		if (features & NETIF_F_NTUPLE)
			h->ae_algo->ops->enable_fd(h, true);
		else
			h->ae_algo->ops->enable_fd(h, false);
	}

	netdev->features = features;
	return 0;
}
@@ -1622,6 +1629,13 @@ static void hns3_disable_sriov(struct pci_dev *pdev)
	pci_disable_sriov(pdev);
}

static void hns3_get_dev_capability(struct pci_dev *pdev,
				    struct hnae3_ae_dev *ae_dev)
{
	if (pdev->revision >= 0x21)
		hnae3_set_bit(ae_dev->flag, HNAE3_DEV_SUPPORT_FD_B, 1);
}

/* hns3_probe - Device initialization routine
 * @pdev: PCI device information struct
 * @ent: entry in hns3_pci_tbl
@@ -1647,6 +1661,8 @@ static int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	ae_dev->pdev = pdev;
	ae_dev->flag = ent->driver_data;
	ae_dev->dev_type = HNAE3_DEV_KNIC;
	ae_dev->reset_type = HNAE3_NONE_RESET;
	hns3_get_dev_capability(pdev, ae_dev);
	pci_set_drvdata(pdev, ae_dev);

	hnae3_register_ae_dev(ae_dev);
@@ -1761,8 +1777,14 @@ static void hns3_set_default_feature(struct net_device *netdev)
		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC;

	if (pdev->revision != 0x20)
	if (pdev->revision >= 0x21) {
		netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;

		if (!(h->flags & HNAE3_SUPPORT_VF)) {
			netdev->hw_features |= NETIF_F_NTUPLE;
			netdev->features |= NETIF_F_NTUPLE;
		}
	}
}

static int hns3_alloc_buffer(struct hns3_enet_ring *ring,
@@ -3142,6 +3164,25 @@ static void hns3_uninit_mac_addr(struct net_device *netdev)
		h->ae_algo->ops->rm_uc_addr(h, netdev->dev_addr);
}

static int hns3_restore_fd_rules(struct net_device *netdev)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);
	int ret = 0;

	if (h->ae_algo->ops->restore_fd_rules)
		ret = h->ae_algo->ops->restore_fd_rules(h);

	return ret;
}

static void hns3_del_all_fd_rules(struct net_device *netdev, bool clear_list)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);

	if (h->ae_algo->ops->del_all_fd_entries)
		h->ae_algo->ops->del_all_fd_entries(h, clear_list);
}

static void hns3_nic_set_priv_ops(struct net_device *netdev)
{
	struct hns3_nic_priv *priv = netdev_priv(netdev);
@@ -3258,6 +3299,8 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
	if (netdev->reg_state != NETREG_UNINITIALIZED)
		unregister_netdev(netdev);

	hns3_del_all_fd_rules(netdev, true);

	hns3_force_clear_all_rx_ring(handle);

	ret = hns3_nic_uninit_vector_data(priv);
@@ -3553,6 +3596,8 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
	if (!(handle->flags & HNAE3_SUPPORT_VF))
		hns3_restore_vlan(netdev);

	hns3_restore_fd_rules(netdev);

	/* Carrier off reporting is important to ethtool even BEFORE open */
	netif_carrier_off(netdev);

@@ -3573,6 +3618,7 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)

static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
{
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
	struct net_device *netdev = handle->kinfo.netdev;
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	int ret;
@@ -3593,6 +3639,13 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)

	hns3_uninit_mac_addr(netdev);

	/* it is cumbersome for hardware to pick-and-choose rules for deletion
	 * from TCAM. Hence, for function reset software intervention is
	 * required to delete the rules
	 */
	if (hns3_dev_ongoing_func_reset(ae_dev))
		hns3_del_all_fd_rules(netdev, false);

	return ret;
}

+5 −0
Original line number Diff line number Diff line
@@ -585,6 +585,11 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
	writel(value, reg_addr + reg);
}

static inline bool hns3_dev_ongoing_func_reset(struct hnae3_ae_dev *ae_dev)
{
	return (ae_dev && (ae_dev->reset_type == HNAE3_FUNC_RESET));
}

#define hns3_write_dev(a, reg, value) \
	hns3_write_reg((a)->io_base, (reg), (value))

+31 −8
Original line number Diff line number Diff line
@@ -699,20 +699,33 @@ static int hns3_get_rxnfc(struct net_device *netdev,
{
	struct hnae3_handle *h = hns3_get_handle(netdev);

	if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->get_rss_tuple)
	if (!h->ae_algo || !h->ae_algo->ops)
		return -EOPNOTSUPP;

	switch (cmd->cmd) {
	case ETHTOOL_GRXRINGS:
		cmd->data = h->kinfo.rss_size;
		break;
		cmd->data = h->kinfo.num_tqps;
		return 0;
	case ETHTOOL_GRXFH:
		if (h->ae_algo->ops->get_rss_tuple)
			return h->ae_algo->ops->get_rss_tuple(h, cmd);
		return -EOPNOTSUPP;
	case ETHTOOL_GRXCLSRLCNT:
		if (h->ae_algo->ops->get_fd_rule_cnt)
			return h->ae_algo->ops->get_fd_rule_cnt(h, cmd);
		return -EOPNOTSUPP;
	case ETHTOOL_GRXCLSRULE:
		if (h->ae_algo->ops->get_fd_rule_info)
			return h->ae_algo->ops->get_fd_rule_info(h, cmd);
		return -EOPNOTSUPP;
	case ETHTOOL_GRXCLSRLALL:
		if (h->ae_algo->ops->get_fd_all_rules)
			return h->ae_algo->ops->get_fd_all_rules(h, cmd,
								 rule_locs);
		return -EOPNOTSUPP;
	default:
		return -EOPNOTSUPP;
	}

	return 0;
}

static int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv,
@@ -795,12 +808,22 @@ static int hns3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);

	if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->set_rss_tuple)
	if (!h->ae_algo || !h->ae_algo->ops)
		return -EOPNOTSUPP;

	switch (cmd->cmd) {
	case ETHTOOL_SRXFH:
		if (h->ae_algo->ops->set_rss_tuple)
			return h->ae_algo->ops->set_rss_tuple(h, cmd);
		return -EOPNOTSUPP;
	case ETHTOOL_SRXCLSRLINS:
		if (h->ae_algo->ops->add_fd_entry)
			return h->ae_algo->ops->add_fd_entry(h, cmd);
		return -EOPNOTSUPP;
	case ETHTOOL_SRXCLSRLDEL:
		if (h->ae_algo->ops->del_fd_entry)
			return h->ae_algo->ops->del_fd_entry(h, cmd);
		return -EOPNOTSUPP;
	default:
		return -EOPNOTSUPP;
	}
+77 −0
Original line number Diff line number Diff line
@@ -190,6 +190,13 @@ enum hclge_opcode_type {
	HCLGE_OPC_VLAN_FILTER_PF_CFG	= 0x1101,
	HCLGE_OPC_VLAN_FILTER_VF_CFG	= 0x1102,

	/* Flow Director commands */
	HCLGE_OPC_FD_MODE_CTRL		= 0x1200,
	HCLGE_OPC_FD_GET_ALLOCATION	= 0x1201,
	HCLGE_OPC_FD_KEY_CONFIG		= 0x1202,
	HCLGE_OPC_FD_TCAM_OP		= 0x1203,
	HCLGE_OPC_FD_AD_OP		= 0x1204,

	/* MDIO command */
	HCLGE_OPC_MDIO_CONFIG		= 0x1900,

@@ -819,6 +826,76 @@ struct hclge_set_led_state_cmd {
	u8 rsv2[20];
};

struct hclge_get_fd_mode_cmd {
	u8 mode;
	u8 enable;
	u8 rsv[22];
};

struct hclge_get_fd_allocation_cmd {
	__le32 stage1_entry_num;
	__le32 stage2_entry_num;
	__le16 stage1_counter_num;
	__le16 stage2_counter_num;
	u8 rsv[12];
};

struct hclge_set_fd_key_config_cmd {
	u8 stage;
	u8 key_select;
	u8 inner_sipv6_word_en;
	u8 inner_dipv6_word_en;
	u8 outer_sipv6_word_en;
	u8 outer_dipv6_word_en;
	u8 rsv1[2];
	__le32 tuple_mask;
	__le32 meta_data_mask;
	u8 rsv2[8];
};

#define HCLGE_FD_EPORT_SW_EN_B		0
struct hclge_fd_tcam_config_1_cmd {
	u8 stage;
	u8 xy_sel;
	u8 port_info;
	u8 rsv1[1];
	__le32 index;
	u8 entry_vld;
	u8 rsv2[7];
	u8 tcam_data[8];
};

struct hclge_fd_tcam_config_2_cmd {
	u8 tcam_data[24];
};

struct hclge_fd_tcam_config_3_cmd {
	u8 tcam_data[20];
	u8 rsv[4];
};

#define HCLGE_FD_AD_DROP_B		0
#define HCLGE_FD_AD_DIRECT_QID_B	1
#define HCLGE_FD_AD_QID_S		2
#define HCLGE_FD_AD_QID_M		GENMASK(12, 2)
#define HCLGE_FD_AD_USE_COUNTER_B	12
#define HCLGE_FD_AD_COUNTER_NUM_S	13
#define HCLGE_FD_AD_COUNTER_NUM_M	GENMASK(20, 13)
#define HCLGE_FD_AD_NXT_STEP_B		20
#define HCLGE_FD_AD_NXT_KEY_S		21
#define HCLGE_FD_AD_NXT_KEY_M		GENMASK(26, 21)
#define HCLGE_FD_AD_WR_RULE_ID_B	0
#define HCLGE_FD_AD_RULE_ID_S		1
#define HCLGE_FD_AD_RULE_ID_M		GENMASK(13, 1)

struct hclge_fd_ad_config_cmd {
	u8 stage;
	u8 rsv1[3];
	__le32 index;
	__le64 ad_data;
	u8 rsv2[8];
};

int hclge_cmd_init(struct hclge_dev *hdev);
static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
{
Loading