Commit edd572d7 authored by Felix Manlunas's avatar Felix Manlunas Committed by David S. Miller
Browse files

liquidio: change octnic_ctrl_pkt to do synchronous soft commands



1. Change struct octnic_ctrl_pkt to support synchronous operation.
2. Change code which use structure octnic_ctrl_pkt to send sc's
   synchronously.

Signed-off-by: default avatarWeilin Chang <weilin.chang@cavium.com>
Signed-off-by: default avatarFelix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6870957e
Loading
Loading
Loading
Loading
+4 −11
Original line number Diff line number Diff line
@@ -198,14 +198,15 @@ int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1)
	nctrl.ncmd.s.cmd = cmd;
	nctrl.ncmd.s.param1 = param1;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "Feature change failed in core (ret: 0x%x)\n",
			ret);
		if (ret > 0)
			ret = -EIO;
	}
	return ret;
}
@@ -285,15 +286,7 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
	struct octeon_device *oct = lio->oct_dev;
	u8 *mac;

	if (nctrl->completion && nctrl->response_code) {
		/* Signal whoever is interested that the response code from the
		 * firmware has arrived.
		 */
		WRITE_ONCE(*nctrl->response_code, nctrl->status);
		complete(nctrl->completion);
	}

	if (nctrl->status)
	if (nctrl->sc_status)
		return;

	switch (nctrl->ncmd.s.cmd) {
+10 −11
Original line number Diff line number Diff line
@@ -472,12 +472,11 @@ lio_send_queue_count_update(struct net_device *netdev, uint32_t num_queues)
	nctrl.ncmd.s.param1 = num_queues;
	nctrl.ncmd.s.param2 = num_queues;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "Failed to send Queue reset command (ret: 0x%x)\n",
			ret);
		return -1;
@@ -708,13 +707,13 @@ static int octnet_gpio_access(struct net_device *netdev, int addr, int val)
	nctrl.ncmd.s.param1 = addr;
	nctrl.ncmd.s.param2 = val;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
		dev_err(&oct->pci_dev->dev, "Failed to configure gpio value\n");
	if (ret) {
		dev_err(&oct->pci_dev->dev,
			"Failed to configure gpio value, ret=%d\n", ret);
		return -EINVAL;
	}

@@ -734,13 +733,13 @@ static int octnet_id_active(struct net_device *netdev, int val)
	nctrl.ncmd.s.cmd = OCTNET_CMD_ID_ACTIVE;
	nctrl.ncmd.s.param1 = val;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
		dev_err(&oct->pci_dev->dev, "Failed to configure gpio value\n");
	if (ret) {
		dev_err(&oct->pci_dev->dev,
			"Failed to configure gpio value, ret=%d\n", ret);
		return -EINVAL;
	}

@@ -1412,7 +1411,6 @@ lio_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
	nctrl.ncmd.u64 = 0;
	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_FLOW_CTL;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

@@ -1433,8 +1431,9 @@ lio_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
	}

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
		dev_err(&oct->pci_dev->dev, "Failed to set pause parameter\n");
	if (ret) {
		dev_err(&oct->pci_dev->dev,
			"Failed to set pause parameter, ret=%d\n", ret);
		return -EINVAL;
	}

+45 −24
Original line number Diff line number Diff line
@@ -2039,10 +2039,9 @@ static void liquidio_set_mcast_list(struct net_device *netdev)
	/* Apparently, any activity in this call from the kernel has to
	 * be atomic. So we won't wait for response.
	 */
	nctrl.wait_time = 0;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "DEVFLAGS change failed in core (ret: 0x%x)\n",
			ret);
	}
@@ -2071,8 +2070,6 @@ static int liquidio_set_mac(struct net_device *netdev, void *p)
	nctrl.ncmd.s.more = 1;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
	nctrl.wait_time = 100;

	nctrl.udd[0] = 0;
	/* The MAC Address is presented in network byte order. */
@@ -2083,6 +2080,14 @@ static int liquidio_set_mac(struct net_device *netdev, void *p)
		dev_err(&oct->pci_dev->dev, "MAC Address change failed\n");
		return -ENOMEM;
	}

	if (nctrl.sc_status) {
		dev_err(&oct->pci_dev->dev,
			"%s: MAC Address change failed. sc return=%x\n",
			 __func__, nctrl.sc_status);
		return -EIO;
	}

	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
	memcpy(((u8 *)&lio->linfo.hw_addr) + 2, addr->sa_data, ETH_ALEN);

@@ -2623,14 +2628,15 @@ static int liquidio_vlan_rx_add_vid(struct net_device *netdev,
	nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER;
	nctrl.ncmd.s.param1 = vid;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n",
			ret);
		if (ret > 0)
			ret = -EIO;
	}

	return ret;
@@ -2651,14 +2657,15 @@ static int liquidio_vlan_rx_kill_vid(struct net_device *netdev,
	nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER;
	nctrl.ncmd.s.param1 = vid;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "Del VLAN filter failed in core (ret: 0x%x)\n",
			ret);
		if (ret > 0)
			ret = -EIO;
	}
	return ret;
}
@@ -2684,15 +2691,16 @@ static int liquidio_set_rxcsum_command(struct net_device *netdev, int command,
	nctrl.ncmd.s.cmd = command;
	nctrl.ncmd.s.param1 = rx_cmd;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev,
			"DEVFLAGS RXCSUM change failed in core(ret:0x%x)\n",
			ret);
		if (ret > 0)
			ret = -EIO;
	}
	return ret;
}
@@ -2720,15 +2728,16 @@ static int liquidio_vxlan_port_command(struct net_device *netdev, int command,
	nctrl.ncmd.s.more = vxlan_cmd_bit;
	nctrl.ncmd.s.param1 = vxlan_port;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev,
			"VxLAN port add/delete failed in core (ret:0x%x)\n",
			ret);
		if (ret > 0)
			ret = -EIO;
	}
	return ret;
}
@@ -2851,6 +2860,7 @@ static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx,
	struct lio *lio = GET_LIO(netdev);
	struct octeon_device *oct = lio->oct_dev;
	struct octnic_ctrl_pkt nctrl;
	int ret = 0;

	if (!is_valid_ether_addr(mac))
		return -EINVAL;
@@ -2864,12 +2874,13 @@ static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx,
	nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR;
	/* vfidx is 0 based, but vf_num (param1) is 1 based */
	nctrl.ncmd.s.param1 = vfidx + 1;
	nctrl.ncmd.s.param2 = (is_admin_assigned ? 1 : 0);
	nctrl.ncmd.s.more = 1;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.netpndev = (u64)netdev;
	if (is_admin_assigned) {
		nctrl.ncmd.s.param2 = true;
		nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
	nctrl.wait_time = LIO_CMD_WAIT_TM;
	}

	nctrl.udd[0] = 0;
	/* The MAC Address is presented in network byte order. */
@@ -2877,9 +2888,11 @@ static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx,

	oct->sriov_info.vf_macaddr[vfidx] = nctrl.udd[0];

	octnet_send_nic_ctrl_pkt(oct, &nctrl);
	ret = octnet_send_nic_ctrl_pkt(oct, &nctrl);
	if (ret > 0)
		ret = -EIO;

	return 0;
	return ret;
}

static int liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac)
@@ -2905,6 +2918,7 @@ static int liquidio_set_vf_vlan(struct net_device *netdev, int vfidx,
	struct octeon_device *oct = lio->oct_dev;
	struct octnic_ctrl_pkt nctrl;
	u16 vlantci;
	int ret = 0;

	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
		return -EINVAL;
@@ -2936,13 +2950,17 @@ static int liquidio_set_vf_vlan(struct net_device *netdev, int vfidx,
	nctrl.ncmd.s.more = 0;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.cb_fn = NULL;
	nctrl.wait_time = LIO_CMD_WAIT_TM;

	octnet_send_nic_ctrl_pkt(oct, &nctrl);
	ret = octnet_send_nic_ctrl_pkt(oct, &nctrl);
	if (ret) {
		if (ret > 0)
			ret = -EIO;
		return ret;
	}

	oct->sriov_info.vf_vlantci[vfidx] = vlantci;

	return 0;
	return ret;
}

static int liquidio_get_vf_config(struct net_device *netdev, int vfidx,
@@ -3063,6 +3081,7 @@ static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx,
	struct lio *lio = GET_LIO(netdev);
	struct octeon_device *oct = lio->oct_dev;
	struct octnic_ctrl_pkt nctrl;
	int ret = 0;

	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
		return -EINVAL;
@@ -3078,13 +3097,15 @@ static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx,
	nctrl.ncmd.s.more = 0;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.cb_fn = NULL;
	nctrl.wait_time = LIO_CMD_WAIT_TM;

	octnet_send_nic_ctrl_pkt(oct, &nctrl);
	ret = octnet_send_nic_ctrl_pkt(oct, &nctrl);

	if (!ret)
		oct->sriov_info.vf_linkstate[vfidx] = linkstate;
	else if (ret > 0)
		ret = -EIO;

	return 0;
	return ret;
}

static int
+13 −25
Original line number Diff line number Diff line
@@ -1119,10 +1119,9 @@ static void liquidio_set_mcast_list(struct net_device *netdev)
	/* Apparently, any activity in this call from the kernel has to
	 * be atomic. So we won't wait for response.
	 */
	nctrl.wait_time = 0;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "DEVFLAGS change failed in core (ret: 0x%x)\n",
			ret);
	}
@@ -1159,8 +1158,6 @@ static int liquidio_set_mac(struct net_device *netdev, void *p)
	nctrl.ncmd.s.more = 1;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
	nctrl.wait_time = 100;

	nctrl.udd[0] = 0;
	/* The MAC Address is presented in network byte order. */
@@ -1171,6 +1168,7 @@ static int liquidio_set_mac(struct net_device *netdev, void *p)
		dev_err(&oct->pci_dev->dev, "MAC Address change failed\n");
		return -ENOMEM;
	}

	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
	ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, addr->sa_data);

@@ -1664,8 +1662,6 @@ liquidio_vlan_rx_add_vid(struct net_device *netdev,
	struct lio *lio = GET_LIO(netdev);
	struct octeon_device *oct = lio->oct_dev;
	struct octnic_ctrl_pkt nctrl;
	struct completion compl;
	u16 response_code;
	int ret = 0;

	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
@@ -1674,26 +1670,15 @@ liquidio_vlan_rx_add_vid(struct net_device *netdev,
	nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER;
	nctrl.ncmd.s.param1 = vid;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
	init_completion(&compl);
	nctrl.completion = &compl;
	nctrl.response_code = &response_code;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n",
			ret);
		return -EIO;
	}

	if (!wait_for_completion_timeout(&compl,
					 msecs_to_jiffies(nctrl.wait_time)))
		return -EPERM;

	if (READ_ONCE(response_code))
		return -EPERM;
	}

	return 0;
}
@@ -1713,14 +1698,15 @@ liquidio_vlan_rx_kill_vid(struct net_device *netdev,
	nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER;
	nctrl.ncmd.s.param1 = vid;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "Del VLAN filter failed in core (ret: 0x%x)\n",
			ret);
		if (ret > 0)
			ret = -EIO;
	}
	return ret;
}
@@ -1746,14 +1732,15 @@ static int liquidio_set_rxcsum_command(struct net_device *netdev, int command,
	nctrl.ncmd.s.cmd = command;
	nctrl.ncmd.s.param1 = rx_cmd;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev, "DEVFLAGS RXCSUM change failed in core (ret:0x%x)\n",
			ret);
		if (ret > 0)
			ret = -EIO;
	}
	return ret;
}
@@ -1781,15 +1768,16 @@ static int liquidio_vxlan_port_command(struct net_device *netdev, int command,
	nctrl.ncmd.s.more = vxlan_cmd_bit;
	nctrl.ncmd.s.param1 = vxlan_port;
	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
	nctrl.wait_time = 100;
	nctrl.netpndev = (u64)netdev;
	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
	if (ret < 0) {
	if (ret) {
		dev_err(&oct->pci_dev->dev,
			"DEVFLAGS VxLAN port add/delete failed in core (ret : 0x%x)\n",
			ret);
		if (ret > 0)
			ret = -EIO;
	}
	return ret;
}
+25 −31
Original line number Diff line number Diff line
@@ -91,29 +91,6 @@ int octnet_send_nic_data_pkt(struct octeon_device *oct,
				   ndata->reqtype);
}

static void octnet_link_ctrl_callback(struct octeon_device *oct,
				      u32 status,
				      void *sc_ptr)
{
	struct octeon_soft_command *sc = (struct octeon_soft_command *)sc_ptr;
	struct octnic_ctrl_pkt *nctrl;

	nctrl = (struct octnic_ctrl_pkt *)sc->ctxptr;

	/* Call the callback function if status is zero (meaning OK) or status
	 * contains a firmware status code bigger than zero (meaning the
	 * firmware is reporting an error).
	 * If no response was expected, status is OK if the command was posted
	 * successfully.
	 */
	if ((!status || status > FIRMWARE_STATUS_CODE(0)) && nctrl->cb_fn) {
		nctrl->status = status;
		nctrl->cb_fn(nctrl);
	}

	octeon_free_soft_command(oct, sc);
}

static inline struct octeon_soft_command
*octnic_alloc_ctrl_pkt_sc(struct octeon_device *oct,
			  struct octnic_ctrl_pkt *nctrl)
@@ -126,17 +103,14 @@ static inline struct octeon_soft_command
	uddsize = (u32)(nctrl->ncmd.s.more * 8);

	datasize = OCTNET_CMD_SIZE + uddsize;
	rdatasize = (nctrl->wait_time) ? 16 : 0;
	rdatasize = 16;

	sc = (struct octeon_soft_command *)
		octeon_alloc_soft_command(oct, datasize, rdatasize,
					  sizeof(struct octnic_ctrl_pkt));
		octeon_alloc_soft_command(oct, datasize, rdatasize, 0);

	if (!sc)
		return NULL;

	memcpy(sc->ctxptr, nctrl, sizeof(struct octnic_ctrl_pkt));

	data = (u8 *)sc->virtdptr;

	memcpy(data, &nctrl->ncmd, OCTNET_CMD_SIZE);
@@ -153,9 +127,8 @@ static inline struct octeon_soft_command
	octeon_prepare_soft_command(oct, sc, OPCODE_NIC, OPCODE_NIC_CMD,
				    0, 0, 0);

	sc->callback = octnet_link_ctrl_callback;
	sc->callback_arg = sc;
	sc->wait_time = nctrl->wait_time;
	init_completion(&sc->complete);
	sc->sc_status = OCTEON_REQUEST_PENDING;

	return sc;
}
@@ -198,5 +171,26 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct,
	}

	spin_unlock_bh(&oct->cmd_resp_wqlock);

	switch (nctrl->ncmd.s.cmd) {
		/* caller holds lock, can not sleep */
	case OCTNET_CMD_CHANGE_DEVFLAGS:
	case OCTNET_CMD_SET_MULTI_LIST:
	case OCTNET_CMD_SET_UC_LIST:
		WRITE_ONCE(sc->caller_is_done, true);
		return retval;
	}

	retval = wait_for_sc_completion_timeout(oct, sc, 0);
	if (retval)
		return (retval);

	nctrl->sc_status = sc->sc_status;
	retval = nctrl->sc_status;
	if (nctrl->cb_fn)
		nctrl->cb_fn(nctrl);

	WRITE_ONCE(sc->caller_is_done, true);

	return retval;
}
Loading