Commit 52c951f1 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-hns3-Add-vf-mtu-support'



Salil Mehta says:

====================
net: hns3: Add vf mtu support

This patchset adds vf mtu support to HNS3 driver.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d7b4a2f2 cdca4c48
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -36,6 +36,9 @@ enum HCLGE_MBX_OPCODE {
	HCLGE_MBX_BIND_FUNC_QUEUE,	/* (VF -> PF) bind function and queue */
	HCLGE_MBX_GET_LINK_STATUS,	/* (VF -> PF) get link status */
	HCLGE_MBX_QUEUE_RESET,		/* (VF -> PF) reset queue */
	HCLGE_MBX_KEEP_ALIVE,		/* (VF -> PF) send keep alive cmd */
	HCLGE_MBX_SET_ALIVE,		/* (VF -> PF) set alive state */
	HCLGE_MBX_SET_MTU,		/* (VF -> PF) set mtu */
};

/* below are per-VF mac-vlan subcodes */
+6 −0
Original line number Diff line number Diff line
@@ -210,6 +210,10 @@ struct hnae3_ae_dev {
 *   Enable the hardware
 * stop()
 *   Disable the hardware
 * start_client()
 *   Inform the hclge that client has been started
 * stop_client()
 *   Inform the hclge that client has been stopped
 * get_status()
 *   Get the carrier state of the back channel of the handle, 1 for ok, 0 for
 *   non-ok
@@ -319,6 +323,8 @@ struct hnae3_ae_ops {
				       struct hnae3_ae_dev *ae_dev);
	int (*start)(struct hnae3_handle *handle);
	void (*stop)(struct hnae3_handle *handle);
	int (*client_start)(struct hnae3_handle *handle);
	void (*client_stop)(struct hnae3_handle *handle);
	int (*get_status)(struct hnae3_handle *handle);
	void (*get_ksettings_an_result)(struct hnae3_handle *handle,
					u8 *auto_neg, u32 *speed, u8 *duplex);
+26 −13
Original line number Diff line number Diff line
@@ -1573,18 +1573,11 @@ static int hns3_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
static int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);
	bool if_running = netif_running(netdev);
	int ret;

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

	/* if this was called with netdev up then bring netdevice down */
	if (if_running) {
		(void)hns3_nic_net_stop(netdev);
		msleep(100);
	}

	ret = h->ae_algo->ops->set_mtu(h, new_mtu);
	if (ret)
		netdev_err(netdev, "failed to change MTU in hardware %d\n",
@@ -1592,10 +1585,6 @@ static int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu)
	else
		netdev->mtu = new_mtu;

	/* if the netdev was running earlier, bring it up again */
	if (if_running && hns3_nic_net_open(netdev))
		ret = -EINVAL;

	return ret;
}

@@ -3540,6 +3529,22 @@ static void hns3_nic_set_priv_ops(struct net_device *netdev)
		priv->ops.maybe_stop_tx = hns3_nic_maybe_stop_tx;
}

static int hns3_client_start(struct hnae3_handle *handle)
{
	if (!handle->ae_algo->ops->client_start)
		return 0;

	return handle->ae_algo->ops->client_start(handle);
}

static void hns3_client_stop(struct hnae3_handle *handle)
{
	if (!handle->ae_algo->ops->client_stop)
		return;

	handle->ae_algo->ops->client_stop(handle);
}

static int hns3_client_init(struct hnae3_handle *handle)
{
	struct pci_dev *pdev = handle->pdev;
@@ -3607,10 +3612,16 @@ static int hns3_client_init(struct hnae3_handle *handle)
		goto out_reg_netdev_fail;
	}

	ret = hns3_client_start(handle);
	if (ret) {
		dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret);
			goto out_reg_netdev_fail;
	}

	hns3_dcbnl_setup(handle);

	/* MTU range: (ETH_MIN_MTU(kernel default) - 9706) */
	netdev->max_mtu = HNS3_MAX_MTU - (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
	/* MTU range: (ETH_MIN_MTU(kernel default) - 9702) */
	netdev->max_mtu = HNS3_MAX_MTU;

	set_bit(HNS3_NIC_STATE_INITED, &priv->state);

@@ -3635,6 +3646,8 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset)
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	int ret;

	hns3_client_stop(handle);

	hns3_remove_hw_addr(netdev);

	if (netdev->reg_state != NETREG_UNINITIALIZED)
+4 −1
Original line number Diff line number Diff line
@@ -76,7 +76,10 @@ enum hns3_nic_state {
#define HNS3_RING_MAX_PENDING			32768
#define HNS3_RING_MIN_PENDING			8
#define HNS3_RING_BD_MULTIPLE			8
#define HNS3_MAX_MTU				9728
/* max frame size of mac */
#define HNS3_MAC_MAX_FRAME			9728
#define HNS3_MAX_MTU \
	(HNS3_MAC_MAX_FRAME - (ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN))

#define HNS3_BD_SIZE_512_TYPE			0
#define HNS3_BD_SIZE_1024_TYPE			1
+116 −32
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@
#define HCLGE_STATS_READ(p, offset) (*((u64 *)((u8 *)(p) + (offset))))
#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f))

static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu);
static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps);
static int hclge_init_vlan_config(struct hclge_dev *hdev);
static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev);
static int hclge_set_umv_space(struct hclge_dev *hdev, u16 space_size,
@@ -1166,6 +1166,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
	for (i = 0; i < num_vport; i++) {
		vport->back = hdev;
		vport->vport_id = i;
		vport->mps = HCLGE_MAC_DEFAULT_FRAME;

		if (i == 0)
			ret = hclge_vport_setup(vport, tqp_main_vport);
@@ -1969,10 +1970,7 @@ static int hclge_get_autoneg(struct hnae3_handle *handle)

static int hclge_mac_init(struct hclge_dev *hdev)
{
	struct hnae3_handle *handle = &hdev->vport[0].nic;
	struct net_device *netdev = handle->kinfo.netdev;
	struct hclge_mac *mac = &hdev->hw.mac;
	int mtu;
	int ret;

	hdev->hw.mac.duplex = HCLGE_MAC_FULL;
@@ -1986,15 +1984,16 @@ static int hclge_mac_init(struct hclge_dev *hdev)

	mac->link = 0;

	if (netdev)
		mtu = netdev->mtu;
	else
		mtu = ETH_DATA_LEN;
	ret = hclge_set_mac_mtu(hdev, hdev->mps);
	if (ret) {
		dev_err(&hdev->pdev->dev, "set mtu failed ret=%d\n", ret);
		return ret;
	}

	ret = hclge_set_mtu(handle, mtu);
	ret = hclge_buffer_alloc(hdev);
	if (ret)
		dev_err(&hdev->pdev->dev,
			"set mtu failed ret=%d\n", ret);
			"allocate buffer fail, ret=%d\n", ret);

	return ret;
}
@@ -2913,6 +2912,23 @@ static void hclge_mailbox_service_task(struct work_struct *work)
	clear_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state);
}

static void hclge_update_vport_alive(struct hclge_dev *hdev)
{
	int i;

	/* start from vport 1 for PF is always alive */
	for (i = 1; i < hdev->num_alloc_vport; i++) {
		struct hclge_vport *vport = &hdev->vport[i];

		if (time_after(jiffies, vport->last_active_jiffies + 8 * HZ))
			clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);

		/* If vf is not alive, set to default value */
		if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state))
			vport->mps = HCLGE_MAC_DEFAULT_FRAME;
	}
}

static void hclge_service_task(struct work_struct *work)
{
	struct hclge_dev *hdev =
@@ -2925,6 +2941,7 @@ static void hclge_service_task(struct work_struct *work)

	hclge_update_speed_duplex(hdev);
	hclge_update_link_status(hdev);
	hclge_update_vport_alive(hdev);
	hclge_service_complete(hdev);
}

@@ -5210,6 +5227,32 @@ static void hclge_ae_stop(struct hnae3_handle *handle)
	hclge_update_link_status(hdev);
}

int hclge_vport_start(struct hclge_vport *vport)
{
	set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);
	vport->last_active_jiffies = jiffies;
	return 0;
}

void hclge_vport_stop(struct hclge_vport *vport)
{
	clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);
}

static int hclge_client_start(struct hnae3_handle *handle)
{
	struct hclge_vport *vport = hclge_get_vport(handle);

	return hclge_vport_start(vport);
}

static void hclge_client_stop(struct hnae3_handle *handle)
{
	struct hclge_vport *vport = hclge_get_vport(handle);

	hclge_vport_stop(vport);
}

static int hclge_get_mac_vlan_cmd_status(struct hclge_vport *vport,
					 u16 cmdq_resp, u8  resp_code,
					 enum hclge_mac_vlan_tbl_opcode op)
@@ -6357,54 +6400,76 @@ int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
	return hclge_set_vlan_rx_offload_cfg(vport);
}

static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mtu)
static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps)
{
	struct hclge_config_max_frm_size_cmd *req;
	struct hclge_desc desc;
	int max_frm_size;
	int ret;

	max_frm_size = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;

	if (max_frm_size < HCLGE_MAC_MIN_FRAME ||
	    max_frm_size > HCLGE_MAC_MAX_FRAME)
		return -EINVAL;

	max_frm_size = max(max_frm_size, HCLGE_MAC_DEFAULT_FRAME);

	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_MAX_FRM_SIZE, false);

	req = (struct hclge_config_max_frm_size_cmd *)desc.data;
	req->max_frm_size = cpu_to_le16(max_frm_size);
	req->max_frm_size = cpu_to_le16(new_mps);
	req->min_frm_size = HCLGE_MAC_MIN_FRAME;

	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
	if (ret)
		dev_err(&hdev->pdev->dev, "set mtu fail, ret =%d.\n", ret);
	else
		hdev->mps = max_frm_size;

	return ret;
	return hclge_cmd_send(&hdev->hw, &desc, 1);
}

static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu)
{
	struct hclge_vport *vport = hclge_get_vport(handle);

	return hclge_set_vport_mtu(vport, new_mtu);
}

int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu)
{
	struct hclge_dev *hdev = vport->back;
	int ret;
	int i, max_frm_size, ret = 0;

	max_frm_size = new_mtu + ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN;
	if (max_frm_size < HCLGE_MAC_MIN_FRAME ||
	    max_frm_size > HCLGE_MAC_MAX_FRAME)
		return -EINVAL;

	max_frm_size = max(max_frm_size, HCLGE_MAC_DEFAULT_FRAME);
	mutex_lock(&hdev->vport_lock);
	/* VF's mps must fit within hdev->mps */
	if (vport->vport_id && max_frm_size > hdev->mps) {
		mutex_unlock(&hdev->vport_lock);
		return -EINVAL;
	} else if (vport->vport_id) {
		vport->mps = max_frm_size;
		mutex_unlock(&hdev->vport_lock);
		return 0;
	}

	ret = hclge_set_mac_mtu(hdev, new_mtu);
	/* PF's mps must be greater then VF's mps */
	for (i = 1; i < hdev->num_alloc_vport; i++)
		if (max_frm_size < hdev->vport[i].mps) {
			mutex_unlock(&hdev->vport_lock);
			return -EINVAL;
		}

	hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);

	ret = hclge_set_mac_mtu(hdev, max_frm_size);
	if (ret) {
		dev_err(&hdev->pdev->dev,
			"Change mtu fail, ret =%d\n", ret);
		return ret;
		goto out;
	}

	hdev->mps = max_frm_size;
	vport->mps = max_frm_size;

	ret = hclge_buffer_alloc(hdev);
	if (ret)
		dev_err(&hdev->pdev->dev,
			"Allocate buffer fail, ret =%d\n", ret);

out:
	hclge_notify_client(hdev, HNAE3_UP_CLIENT);
	mutex_unlock(&hdev->vport_lock);
	return ret;
}

@@ -7021,6 +7086,9 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
	hdev->reset_type = HNAE3_NONE_RESET;
	hdev->reset_level = HNAE3_FUNC_RESET;
	ae_dev->priv = hdev;
	hdev->mps = ETH_FRAME_LEN + ETH_FCS_LEN + 2 * VLAN_HLEN;

	mutex_init(&hdev->vport_lock);

	ret = hclge_pci_init(hdev);
	if (ret) {
@@ -7197,6 +7265,17 @@ static void hclge_stats_clear(struct hclge_dev *hdev)
	memset(&hdev->hw_stats, 0, sizeof(hdev->hw_stats));
}

static void hclge_reset_vport_state(struct hclge_dev *hdev)
{
	struct hclge_vport *vport = hdev->vport;
	int i;

	for (i = 0; i < hdev->num_alloc_vport; i++) {
		hclge_vport_start(vport);
		vport++;
	}
}

static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
{
	struct hclge_dev *hdev = ae_dev->priv;
@@ -7282,6 +7361,8 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
	if (hclge_enable_tm_hw_error(hdev, true))
		dev_err(&pdev->dev, "failed to enable TM hw error interrupts\n");

	hclge_reset_vport_state(hdev);

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

@@ -7308,6 +7389,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
	hclge_destroy_cmd_queue(&hdev->hw);
	hclge_misc_irq_uninit(hdev);
	hclge_pci_uninit(hdev);
	mutex_destroy(&hdev->vport_lock);
	ae_dev->priv = NULL;
}

@@ -7690,6 +7772,8 @@ static const struct hnae3_ae_ops hclge_ops = {
	.set_loopback = hclge_set_loopback,
	.start = hclge_ae_start,
	.stop = hclge_ae_stop,
	.client_start = hclge_client_start,
	.client_stop = hclge_client_stop,
	.get_status = hclge_get_status,
	.get_ksettings_an_result = hclge_get_ksettings_an_result,
	.update_speed_duplex_h = hclge_update_speed_duplex_h,
Loading