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

Commit a514722a authored by Himanshu Madhani's avatar Himanshu Madhani Committed by David S. Miller
Browse files

qlcnic: Refactor interrupt coalescing code for all adapters.



o Refactor configuration of interrupt coalescing parameters for
  all supported adapters.

Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2b018ad9
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -369,6 +369,7 @@ struct qlcnic_rx_buffer {
 */
#define QLCNIC_INTR_COAL_TYPE_RX		1
#define QLCNIC_INTR_COAL_TYPE_TX		2
#define QLCNIC_INTR_COAL_TYPE_RX_TX		3

#define QLCNIC_DEF_INTR_COALESCE_RX_TIME_US	3
#define QLCNIC_DEF_INTR_COALESCE_RX_PACKETS	256
@@ -1740,7 +1741,8 @@ struct qlcnic_hardware_ops {
	int (*change_macvlan) (struct qlcnic_adapter *, u8*, u16, u8);
	void (*napi_enable) (struct qlcnic_adapter *);
	void (*napi_disable) (struct qlcnic_adapter *);
	void (*config_intr_coal) (struct qlcnic_adapter *);
	int (*config_intr_coal) (struct qlcnic_adapter *,
				 struct ethtool_coalesce *);
	int (*config_rss) (struct qlcnic_adapter *, int);
	int (*config_hw_lro) (struct qlcnic_adapter *, int);
	int (*config_loopback) (struct qlcnic_adapter *, u8);
@@ -1936,9 +1938,10 @@ static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
	adapter->ahw->hw_ops->napi_disable(adapter);
}

static inline void qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
static inline int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter,
					      struct ethtool_coalesce *ethcoal)
{
	adapter->ahw->hw_ops->config_intr_coal(adapter);
	return adapter->ahw->hw_ops->config_intr_coal(adapter, ethcoal);
}

static inline int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
+113 −20
Original line number Diff line number Diff line
@@ -2102,37 +2102,130 @@ int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac,
	return err;
}

void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
static int qlcnic_83xx_set_rx_intr_coal(struct qlcnic_adapter *adapter)
{
	int err;
	u16 temp;
	struct qlcnic_cmd_args cmd;
	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;

	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
		return;
	struct qlcnic_cmd_args cmd;
	u16 temp;
	int err;

	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
	if (err)
		return;
		return err;

	if (coal->type == QLCNIC_INTR_COAL_TYPE_RX) {
	temp = adapter->recv_ctx->context_id;
	cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_RX | temp << 16;
	temp = coal->rx_time_us;
	cmd.req.arg[2] = coal->rx_packets | temp << 16;
	} else if (coal->type == QLCNIC_INTR_COAL_TYPE_TX) {
	cmd.req.arg[3] = coal->flag;

	err = qlcnic_issue_cmd(adapter, &cmd);
	if (err != QLCNIC_RCODE_SUCCESS)
		netdev_err(adapter->netdev,
			   "failed to set interrupt coalescing parameters\n");

	qlcnic_free_mbx_args(&cmd);

	return err;
}

static int qlcnic_83xx_set_tx_intr_coal(struct qlcnic_adapter *adapter)
{
	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
	struct qlcnic_cmd_args cmd;
	u16 temp;
	int err;

	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
	if (err)
		return err;

	temp = adapter->tx_ring->ctx_id;
	cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_TX | temp << 16;
	temp = coal->tx_time_us;
	cmd.req.arg[2] = coal->tx_packets | temp << 16;
	}
	cmd.req.arg[3] = coal->flag;

	err = qlcnic_issue_cmd(adapter, &cmd);
	if (err != QLCNIC_RCODE_SUCCESS)
		dev_info(&adapter->pdev->dev,
			 "Failed to send interrupt coalescence parameters\n");
		netdev_err(adapter->netdev,
			   "failed to set interrupt coalescing  parameters\n");

	qlcnic_free_mbx_args(&cmd);

	return err;
}

int qlcnic_83xx_set_rx_tx_intr_coal(struct qlcnic_adapter *adapter)
{
	int err = 0;

	err = qlcnic_83xx_set_rx_intr_coal(adapter);
	if (err)
		netdev_err(adapter->netdev,
			   "failed to set Rx coalescing parameters\n");

	err = qlcnic_83xx_set_tx_intr_coal(adapter);
	if (err)
		netdev_err(adapter->netdev,
			   "failed to set Tx coalescing parameters\n");

	return err;
}

int qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter,
				 struct ethtool_coalesce *ethcoal)
{
	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
	u32 rx_coalesce_usecs, rx_max_frames;
	u32 tx_coalesce_usecs, tx_max_frames;
	int err;

	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
		return -EIO;

	tx_coalesce_usecs = ethcoal->tx_coalesce_usecs;
	tx_max_frames = ethcoal->tx_max_coalesced_frames;
	rx_coalesce_usecs = ethcoal->rx_coalesce_usecs;
	rx_max_frames = ethcoal->rx_max_coalesced_frames;
	coal->flag = QLCNIC_INTR_DEFAULT;

	if ((coal->rx_time_us == rx_coalesce_usecs) &&
	    (coal->rx_packets == rx_max_frames)) {
		coal->type = QLCNIC_INTR_COAL_TYPE_TX;
		coal->tx_time_us = tx_coalesce_usecs;
		coal->tx_packets = tx_max_frames;
	} else if ((coal->tx_time_us == tx_coalesce_usecs) &&
		   (coal->tx_packets == tx_max_frames)) {
		coal->type = QLCNIC_INTR_COAL_TYPE_RX;
		coal->rx_time_us = rx_coalesce_usecs;
		coal->rx_packets = rx_max_frames;
	} else {
		coal->type = QLCNIC_INTR_COAL_TYPE_RX_TX;
		coal->rx_time_us = rx_coalesce_usecs;
		coal->rx_packets = rx_max_frames;
		coal->tx_time_us = tx_coalesce_usecs;
		coal->tx_packets = tx_max_frames;
	}

	switch (coal->type) {
	case QLCNIC_INTR_COAL_TYPE_RX:
		err = qlcnic_83xx_set_rx_intr_coal(adapter);
		break;
	case QLCNIC_INTR_COAL_TYPE_TX:
		err = qlcnic_83xx_set_tx_intr_coal(adapter);
		break;
	case QLCNIC_INTR_COAL_TYPE_RX_TX:
		err = qlcnic_83xx_set_rx_tx_intr_coal(adapter);
		break;
	default:
		err = -EINVAL;
		netdev_err(adapter->netdev,
			   "Invalid Interrupt coalescing type\n");
		break;
	}

	return err;
}

static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
+3 −2
Original line number Diff line number Diff line
@@ -547,7 +547,6 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32);
int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32);
int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int);
int qlcnic_83xx_config_rss(struct qlcnic_adapter *, int);
int qlcnic_83xx_config_intr_coalesce(struct qlcnic_adapter *);
void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, u16);
int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
@@ -577,7 +576,9 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *,
void qlcnic_free_mbx_args(struct qlcnic_cmd_args *);
void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *,
			  struct qlcnic_info *);
void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *);
int qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *,
				 struct ethtool_coalesce *);
int qlcnic_83xx_set_rx_tx_intr_coal(struct qlcnic_adapter *);
int qlcnic_83xx_get_port_info(struct qlcnic_adapter *);
void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *);
void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *);
+23 −76
Original line number Diff line number Diff line
@@ -1495,9 +1495,7 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
			struct ethtool_coalesce *ethcoal)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct qlcnic_nic_intr_coalesce *coal;
	u32 rx_coalesce_usecs, rx_max_frames;
	u32 tx_coalesce_usecs, tx_max_frames;
	int err;

	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
		return -EINVAL;
@@ -1529,60 +1527,9 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
	    ethcoal->tx_max_coalesced_frames_high)
		return -EINVAL;

	coal = &adapter->ahw->coal;

	if (qlcnic_83xx_check(adapter)) {
		if (!ethcoal->tx_coalesce_usecs ||
		    !ethcoal->tx_max_coalesced_frames ||
		    !ethcoal->rx_coalesce_usecs ||
		    !ethcoal->rx_max_coalesced_frames) {
			coal->flag = QLCNIC_INTR_DEFAULT;
			coal->type = QLCNIC_INTR_COAL_TYPE_RX;
			coal->rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
			coal->rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
			coal->tx_time_us = QLCNIC_DEF_INTR_COALESCE_TX_TIME_US;
			coal->tx_packets = QLCNIC_DEF_INTR_COALESCE_TX_PACKETS;
		} else {
			tx_coalesce_usecs = ethcoal->tx_coalesce_usecs;
			tx_max_frames = ethcoal->tx_max_coalesced_frames;
			rx_coalesce_usecs = ethcoal->rx_coalesce_usecs;
			rx_max_frames = ethcoal->rx_max_coalesced_frames;
			coal->flag = 0;

			if ((coal->rx_time_us == rx_coalesce_usecs) &&
			    (coal->rx_packets == rx_max_frames)) {
				coal->type = QLCNIC_INTR_COAL_TYPE_TX;
				coal->tx_time_us = tx_coalesce_usecs;
				coal->tx_packets = tx_max_frames;
			} else if ((coal->tx_time_us == tx_coalesce_usecs) &&
				   (coal->tx_packets == tx_max_frames)) {
				coal->type = QLCNIC_INTR_COAL_TYPE_RX;
				coal->rx_time_us = rx_coalesce_usecs;
				coal->rx_packets = rx_max_frames;
			} else {
				coal->type = QLCNIC_INTR_COAL_TYPE_RX;
				coal->rx_time_us = rx_coalesce_usecs;
				coal->rx_packets = rx_max_frames;
				coal->tx_time_us = tx_coalesce_usecs;
				coal->tx_packets = tx_max_frames;
			}
		}
	} else {
		if (!ethcoal->rx_coalesce_usecs ||
		    !ethcoal->rx_max_coalesced_frames) {
			coal->flag = QLCNIC_INTR_DEFAULT;
			coal->rx_time_us = QLCNIC_DEF_INTR_COALESCE_RX_TIME_US;
			coal->rx_packets = QLCNIC_DEF_INTR_COALESCE_RX_PACKETS;
		} else {
			coal->flag = 0;
			coal->rx_time_us = ethcoal->rx_coalesce_usecs;
			coal->rx_packets = ethcoal->rx_max_coalesced_frames;
		}
	}

	qlcnic_config_intr_coalesce(adapter);
	err = qlcnic_config_intr_coalesce(adapter, ethcoal);

	return 0;
	return err;
}

static int qlcnic_get_intr_coalesce(struct net_device *netdev,
+23 −4
Original line number Diff line number Diff line
@@ -755,10 +755,7 @@ int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *adapter)
	return 0;
}

/*
 * Send the interrupt coalescing parameter set by ethtool to the card.
 */
void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
int qlcnic_82xx_set_rx_coalesce(struct qlcnic_adapter *adapter)
{
	struct qlcnic_nic_req req;
	int rv;
@@ -780,6 +777,28 @@ void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
	if (rv != 0)
		dev_err(&adapter->netdev->dev,
			"Could not send interrupt coalescing parameters\n");

	return rv;
}

/* Send the interrupt coalescing parameter set by ethtool to the card. */
int qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter,
				     struct ethtool_coalesce *ethcoal)
{
	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
	int rv;

	coal->flag = QLCNIC_INTR_DEFAULT;
	coal->rx_time_us = ethcoal->rx_coalesce_usecs;
	coal->rx_packets = ethcoal->rx_max_coalesced_frames;

	rv = qlcnic_82xx_set_rx_coalesce(adapter);

	if (rv)
		netdev_err(adapter->netdev,
			   "Failed to set Rx coalescing parametrs\n");

	return rv;
}

#define QLCNIC_ENABLE_IPV4_LRO		BIT_0
Loading