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

Commit 21ad1173 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'hns3-next'



Salil Mehta says:

====================
Misc. bug fixes & optimizations for HNS3 driver

This patch-set presents some bug fixes found out during the internal
review and system testing and some small optimizations.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 07f7ee6e 3a678b58
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ enum hclge_mbx_mac_vlan_subcode {
	HCLGE_MBX_MAC_VLAN_MC_ADD,		/* add new MC mac addr */
	HCLGE_MBX_MAC_VLAN_MC_REMOVE,		/* remove MC mac addr */
	HCLGE_MBX_MAC_VLAN_MC_FUNC_MTA_ENABLE,	/* config func MTA enable */
	HCLGE_MBX_MAC_VLAN_MTA_TYPE_READ,	/* read func MTA type */
	HCLGE_MBX_MAC_VLAN_MTA_STATUS_UPDATE,	/* update MTA status */
};

/* below are per-VF vlan cfg subcodes */
+3 −1
Original line number Diff line number Diff line
@@ -316,7 +316,8 @@ struct hnae3_ae_ops {
	int (*set_loopback)(struct hnae3_handle *handle,
			    enum hnae3_loop loop_mode, bool en);

	void (*set_promisc_mode)(struct hnae3_handle *handle, u32 en);
	void (*set_promisc_mode)(struct hnae3_handle *handle, bool en_uc_pmc,
				 bool en_mc_pmc);
	int (*set_mtu)(struct hnae3_handle *handle, int new_mtu);

	void (*get_pauseparam)(struct hnae3_handle *handle,
@@ -352,6 +353,7 @@ struct hnae3_ae_ops {
			   const unsigned char *addr);
	int (*rm_mc_addr)(struct hnae3_handle *handle,
			  const unsigned char *addr);
	int (*update_mta_status)(struct hnae3_handle *handle);

	void (*set_tso_stats)(struct hnae3_handle *handle, int enable);
	void (*update_stats)(struct hnae3_handle *handle,
+57 −3
Original line number Diff line number Diff line
@@ -415,15 +415,21 @@ static void hns3_nic_set_rx_mode(struct net_device *netdev)

	if (h->ae_algo->ops->set_promisc_mode) {
		if (netdev->flags & IFF_PROMISC)
			h->ae_algo->ops->set_promisc_mode(h, 1);
			h->ae_algo->ops->set_promisc_mode(h, true, true);
		else if (netdev->flags & IFF_ALLMULTI)
			h->ae_algo->ops->set_promisc_mode(h, false, true);
		else
			h->ae_algo->ops->set_promisc_mode(h, 0);
			h->ae_algo->ops->set_promisc_mode(h, false, false);
	}
	if (__dev_uc_sync(netdev, hns3_nic_uc_sync, hns3_nic_uc_unsync))
		netdev_err(netdev, "sync uc address fail\n");
	if (netdev->flags & IFF_MULTICAST)
	if (netdev->flags & IFF_MULTICAST) {
		if (__dev_mc_sync(netdev, hns3_nic_mc_sync, hns3_nic_mc_unsync))
			netdev_err(netdev, "sync mc address fail\n");

		if (h->ae_algo->ops->update_mta_status)
			h->ae_algo->ops->update_mta_status(h);
	}
}

static int hns3_set_tso(struct sk_buff *skb, u32 *paylen,
@@ -653,6 +659,32 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto,
	}
}

/* when skb->encapsulation is 0, skb->ip_summed is CHECKSUM_PARTIAL
 * and it is udp packet, which has a dest port as the IANA assigned.
 * the hardware is expected to do the checksum offload, but the
 * hardware will not do the checksum offload when udp dest port is
 * 4789.
 */
static bool hns3_tunnel_csum_bug(struct sk_buff *skb)
{
#define IANA_VXLAN_PORT	4789
	union {
		struct tcphdr *tcp;
		struct udphdr *udp;
		struct gre_base_hdr *gre;
		unsigned char *hdr;
	} l4;

	l4.hdr = skb_transport_header(skb);

	if (!(!skb->encapsulation && l4.udp->dest == htons(IANA_VXLAN_PORT)))
		return false;

	skb_checksum_help(skb);

	return true;
}

static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto,
				   u8 il4_proto, u32 *type_cs_vlan_tso,
				   u32 *ol_type_vlan_len_msec)
@@ -741,6 +773,9 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto,
			       HNS3_L4T_TCP);
		break;
	case IPPROTO_UDP:
		if (hns3_tunnel_csum_bug(skb))
			break;

		hnae_set_field(*type_cs_vlan_tso,
			       HNS3_TXD_L4T_M,
			       HNS3_TXD_L4T_S,
@@ -1130,6 +1165,12 @@ static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
	if (!mac_addr || !is_valid_ether_addr((const u8 *)mac_addr->sa_data))
		return -EADDRNOTAVAIL;

	if (ether_addr_equal(netdev->dev_addr, mac_addr->sa_data)) {
		netdev_info(netdev, "already using mac address %pM\n",
			    mac_addr->sa_data);
		return 0;
	}

	ret = h->ae_algo->ops->set_mac_addr(h, mac_addr->sa_data, false);
	if (ret) {
		netdev_err(netdev, "set_mac_address fail, ret=%d!\n", ret);
@@ -2999,6 +3040,15 @@ static void hns3_init_mac_addr(struct net_device *netdev, bool init)

}

static void hns3_uninit_mac_addr(struct net_device *netdev)
{
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	struct hnae3_handle *h = priv->ae_handle;

	if (h->ae_algo->ops->rm_uc_addr)
		h->ae_algo->ops->rm_uc_addr(h, netdev->dev_addr);
}

static void hns3_nic_set_priv_ops(struct net_device *netdev)
{
	struct hns3_nic_priv *priv = netdev_priv(netdev);
@@ -3127,6 +3177,8 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset)

	priv->ring_data = NULL;

	hns3_uninit_mac_addr(netdev);

	free_netdev(netdev);
}

@@ -3443,6 +3495,8 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)

	priv->ring_data = NULL;

	hns3_uninit_mac_addr(netdev);

	return ret;
}

+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
	if (ret)
		return ret;

	h->ae_algo->ops->set_promisc_mode(h, en);
	h->ae_algo->ops->set_promisc_mode(h, en, en);

	return ret;
}
+171 −34
Original line number Diff line number Diff line
@@ -2288,8 +2288,10 @@ static int hclge_mac_init(struct hclge_dev *hdev)
	struct net_device *netdev = handle->kinfo.netdev;
	struct hclge_mac *mac = &hdev->hw.mac;
	u8 mac_mask[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
	struct hclge_vport *vport;
	int mtu;
	int ret;
	int i;

	ret = hclge_cfg_mac_speed_dup(hdev, hdev->hw.mac.speed, HCLGE_MAC_FULL);
	if (ret) {
@@ -2301,7 +2303,6 @@ static int hclge_mac_init(struct hclge_dev *hdev)
	mac->link = 0;

	/* Initialize the MTA table work mode */
	hdev->accept_mta_mc	= true;
	hdev->enable_mta	= true;
	hdev->mta_mac_sel_type	= HCLGE_MAC_ADDR_47_36;

@@ -2314,12 +2315,18 @@ static int hclge_mac_init(struct hclge_dev *hdev)
		return ret;
	}

	ret = hclge_cfg_func_mta_filter(hdev, 0, hdev->accept_mta_mc);
	for (i = 0; i < hdev->num_alloc_vport; i++) {
		vport = &hdev->vport[i];
		vport->accept_mta_mc = false;

		memset(vport->mta_shadow, 0, sizeof(vport->mta_shadow));
		ret = hclge_cfg_func_mta_filter(hdev, vport->vport_id, false);
		if (ret) {
			dev_err(&hdev->pdev->dev,
				"set mta filter mode fail ret=%d\n", ret);
			return ret;
		}
	}

	ret = hclge_set_default_mac_vlan_mask(hdev, true, mac_mask);
	if (ret) {
@@ -2580,16 +2587,18 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data)
		 * mbx messages reported by this interrupt.
		 */
		hclge_mbx_task_schedule(hdev);

		break;
	default:
		dev_dbg(&hdev->pdev->dev,
		dev_warn(&hdev->pdev->dev,
			 "received unknown or unhandled event of vector0\n");
		break;
	}

	/* we should clear the source of interrupt */
	/* clear the source of interrupt if it is not cause by reset */
	if (event_cause != HCLGE_VECTOR0_EVENT_RST) {
		hclge_clear_event_cause(hdev, event_cause, clearval);
		hclge_enable_vector(&hdev->misc_vector, true);
	}

	return IRQ_HANDLED;
}
@@ -2777,6 +2786,33 @@ static enum hnae3_reset_type hclge_get_reset_level(struct hclge_dev *hdev,
	return rst_level;
}

static void hclge_clear_reset_cause(struct hclge_dev *hdev)
{
	u32 clearval = 0;

	switch (hdev->reset_type) {
	case HNAE3_IMP_RESET:
		clearval = BIT(HCLGE_VECTOR0_IMPRESET_INT_B);
		break;
	case HNAE3_GLOBAL_RESET:
		clearval = BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B);
		break;
	case HNAE3_CORE_RESET:
		clearval = BIT(HCLGE_VECTOR0_CORERESET_INT_B);
		break;
	default:
		dev_warn(&hdev->pdev->dev, "Unsupported reset event to clear:%d",
			 hdev->reset_type);
		break;
	}

	if (!clearval)
		return;

	hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG, clearval);
	hclge_enable_vector(&hdev->misc_vector, true);
}

static void hclge_reset(struct hclge_dev *hdev)
{
	/* perform reset of the stack & ae device for a client */
@@ -2789,6 +2825,8 @@ static void hclge_reset(struct hclge_dev *hdev)
		hclge_reset_ae_dev(hdev->ae_dev);
		hclge_notify_client(hdev, HNAE3_INIT_CLIENT);
		rtnl_unlock();

		hclge_clear_reset_cause(hdev);
	} else {
		/* schedule again to check pending resets later */
		set_bit(hdev->reset_type, &hdev->reset_pending);
@@ -3580,13 +3618,15 @@ void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
	param->vf_id = vport_id;
}

static void hclge_set_promisc_mode(struct hnae3_handle *handle, u32 en)
static void hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
				   bool en_mc_pmc)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	struct hclge_promisc_param param;

	hclge_promisc_param_init(&param, en, en, true, vport->vport_id);
	hclge_promisc_param_init(&param, en_uc_pmc, en_mc_pmc, true,
				 vport->vport_id);
	hclge_cmd_set_promisc_mode(hdev, &param);
}

@@ -3728,9 +3768,6 @@ static int hclge_ae_start(struct hnae3_handle *handle)
	/* reset tqp stats */
	hclge_reset_tqp_stats(handle);

	if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
		return 0;

	ret = hclge_mac_start_phy(hdev);
	if (ret)
		return ret;
@@ -3746,9 +3783,12 @@ static void hclge_ae_stop(struct hnae3_handle *handle)

	del_timer_sync(&hdev->service_timer);
	cancel_work_sync(&hdev->service_task);
	clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state);

	if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
	if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) {
		hclge_mac_stop_phy(hdev);
		return;
	}

	for (i = 0; i < vport->alloc_tqps; i++)
		hclge_tqp_enable(hdev, i, 0, false);
@@ -3972,9 +4012,88 @@ static int hclge_set_mta_table_item(struct hclge_vport *vport,
		return ret;
	}

	if (enable)
		set_bit(idx, vport->mta_shadow);
	else
		clear_bit(idx, vport->mta_shadow);

	return 0;
}

static int hclge_update_mta_status(struct hnae3_handle *handle)
{
	unsigned long mta_status[BITS_TO_LONGS(HCLGE_MTA_TBL_SIZE)];
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct net_device *netdev = handle->kinfo.netdev;
	struct netdev_hw_addr *ha;
	u16 tbl_idx;

	memset(mta_status, 0, sizeof(mta_status));

	/* update mta_status from mc addr list */
	netdev_for_each_mc_addr(ha, netdev) {
		tbl_idx = hclge_get_mac_addr_to_mta_index(vport, ha->addr);
		set_bit(tbl_idx, mta_status);
	}

	return hclge_update_mta_status_common(vport, mta_status,
					0, HCLGE_MTA_TBL_SIZE, true);
}

int hclge_update_mta_status_common(struct hclge_vport *vport,
				   unsigned long *status,
				   u16 idx,
				   u16 count,
				   bool update_filter)
{
	struct hclge_dev *hdev = vport->back;
	u16 update_max = idx + count;
	u16 check_max;
	int ret = 0;
	bool used;
	u16 i;

	/* setup mta check range */
	if (update_filter) {
		i = 0;
		check_max = HCLGE_MTA_TBL_SIZE;
	} else {
		i = idx;
		check_max = update_max;
	}

	used = false;
	/* check and update all mta item */
	for (; i < check_max; i++) {
		/* ignore unused item */
		if (!test_bit(i, vport->mta_shadow))
			continue;

		/* if i in update range then update it */
		if (i >= idx && i < update_max)
			if (!test_bit(i - idx, status))
				hclge_set_mta_table_item(vport, i, false);

		if (!used && test_bit(i, vport->mta_shadow))
			used = true;
	}

	/* no longer use mta, disable it */
	if (vport->accept_mta_mc && update_filter && !used) {
		ret = hclge_cfg_func_mta_filter(hdev,
						vport->vport_id,
						false);
		if (ret)
			dev_err(&hdev->pdev->dev,
				"disable func mta filter fail ret=%d\n",
				ret);
		else
			vport->accept_mta_mc = false;
	}

	return ret;
}

static int hclge_remove_mac_vlan_tbl(struct hclge_vport *vport,
				     struct hclge_mac_vlan_tbl_entry_cmd *req)
{
@@ -4242,9 +4361,25 @@ int hclge_add_mc_addr_common(struct hclge_vport *vport,
		status = hclge_add_mac_vlan_tbl(vport, &req, desc);
	}

	/* If mc mac vlan table is full, use MTA table */
	if (status == -ENOSPC) {
		if (!vport->accept_mta_mc) {
			status = hclge_cfg_func_mta_filter(hdev,
							   vport->vport_id,
							   true);
			if (status) {
				dev_err(&hdev->pdev->dev,
					"set mta filter mode fail ret=%d\n",
					status);
				return status;
			}
			vport->accept_mta_mc = true;
		}

		/* Set MTA table for this MAC address */
		tbl_idx = hclge_get_mac_addr_to_mta_index(vport, addr);
		status = hclge_set_mta_table_item(vport, tbl_idx, true);
	}

	return status;
}
@@ -4264,7 +4399,6 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
	struct hclge_mac_vlan_tbl_entry_cmd req;
	enum hclge_cmd_status status;
	struct hclge_desc desc[3];
	u16 tbl_idx;

	/* mac addr check */
	if (!is_multicast_ether_addr(addr)) {
@@ -4293,17 +4427,15 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
			status = hclge_add_mac_vlan_tbl(vport, &req, desc);

	} else {
		/* This mac addr do not exist, can't delete it */
		dev_err(&hdev->pdev->dev,
			"Rm multicast mac addr failed, ret = %d.\n",
			status);
		return -EIO;
		/* Maybe this mac address is in mta table, but it cannot be
		 * deleted here because an entry of mta represents an address
		 * range rather than a specific address. the delete action to
		 * all entries will take effect in update_mta_status called by
		 * hns3_nic_set_rx_mode.
		 */
		status = 0;
	}

	/* Set MTB table for this MAC address */
	tbl_idx = hclge_get_mac_addr_to_mta_index(vport, addr);
	status = hclge_set_mta_table_item(vport, tbl_idx, false);

	return status;
}

@@ -4525,9 +4657,16 @@ static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
	}

	if (!is_kill) {
#define HCLGE_VF_VLAN_NO_ENTRY	2
		if (!req0->resp_code || req0->resp_code == 1)
			return 0;

		if (req0->resp_code == HCLGE_VF_VLAN_NO_ENTRY) {
			dev_warn(&hdev->pdev->dev,
				 "vf vlan table is full, vf vlan filter is disabled\n");
			return 0;
		}

		dev_err(&hdev->pdev->dev,
			"Add vf vlan filter fail, ret =%d.\n",
			req0->resp_code);
@@ -5651,9 +5790,6 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
		return ret;
	}

	/* Enable MISC vector(vector0) */
	hclge_enable_vector(&hdev->misc_vector, true);

	dev_info(&pdev->dev, "Reset done, %s driver initialization finished.\n",
		 HCLGE_DRIVER_NAME);

@@ -6100,6 +6236,7 @@ static const struct hnae3_ae_ops hclge_ops = {
	.rm_uc_addr = hclge_rm_uc_addr,
	.add_mc_addr = hclge_add_mc_addr,
	.rm_mc_addr = hclge_rm_mc_addr,
	.update_mta_status = hclge_update_mta_status,
	.set_autoneg = hclge_set_autoneg,
	.get_autoneg = hclge_get_autoneg,
	.get_pauseparam = hclge_get_pauseparam,
Loading