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

Commit 10ef9ab4 authored by Sathya Perla's avatar Sathya Perla Committed by David S. Miller
Browse files

be2net: event queue re-design



v2: Fixed up the bad typecasting pointed out by David...

In the current design 8 TXQs are serviced by 1 EQ, while each RSS queue
is serviced by a separate EQ. This is being changed as follows:

- Upto 8 EQs will be used (based on the availabilty of msix vectors).
Each EQ will handle 1 RSS and 1 TX ring. The default non-RSS RX queue and
MCC queue are handled by the last EQ.

- On cards which provide support, upto 8 RSS rings will be used, instead
of the current limit of 4.

The new design allows spreading the TX multi-queue completion processing
across multiple CPUs unlike the previous design.

Signed-off-by: default avatarSathya Perla <sathya.perla@emulex.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 23677ce3
Loading
Loading
Loading
Loading
+38 −27
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ static inline char *nic_name(struct pci_dev *pdev)
#define BE_MIN_MTU		256

#define BE_NUM_VLANS_SUPPORTED	64
#define BE_MAX_EQD		96
#define BE_MAX_EQD		96u
#define	BE_MAX_TX_FRAG_COUNT	30

#define EVNT_Q_LEN		1024
@@ -92,10 +92,14 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MCC_Q_LEN		128	/* total size not to exceed 8 pages */
#define MCC_CQ_LEN		256

#define MAX_RSS_QS		4	/* BE limit is 4 queues/port */
#define BE3_MAX_RSS_QS		8
#define BE2_MAX_RSS_QS		4
#define MAX_RSS_QS		BE3_MAX_RSS_QS
#define MAX_RX_QS		(MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */

#define MAX_TX_QS		8
#define BE_MAX_MSIX_VECTORS	(MAX_RX_QS + 1)/* RX + TX */
#define MAX_MSIX_VECTORS	MAX_RSS_QS
#define BE_TX_BUDGET		256
#define BE_NAPI_WEIGHT		64
#define MAX_RX_POST		BE_NAPI_WEIGHT /* Frags posted at a time */
#define RX_FRAGS_REFILL_WM	(RX_Q_LEN - MAX_RX_POST)
@@ -165,13 +169,16 @@ struct be_eq_obj {

	/* Adaptive interrupt coalescing (AIC) info */
	bool enable_aic;
	u16 min_eqd;		/* in usecs */
	u16 max_eqd;		/* in usecs */
	u16 cur_eqd;		/* in usecs */
	u8  eq_idx;
	u32 min_eqd;		/* in usecs */
	u32 max_eqd;		/* in usecs */
	u32 eqd;		/* configured val when aic is off */
	u32 cur_eqd;		/* in usecs */

	u8 idx;			/* array index */
	u16 tx_budget;
	struct napi_struct napi;
};
	struct be_adapter *adapter;
} ____cacheline_aligned_in_smp;

struct be_mcc_obj {
	struct be_queue_info q;
@@ -197,7 +204,7 @@ struct be_tx_obj {
	/* Remember the skbs that were transmitted */
	struct sk_buff *sent_skb_list[TX_Q_LEN];
	struct be_tx_stats stats;
};
} ____cacheline_aligned_in_smp;

/* Struct to remember the pages posted for rx frags */
struct be_rx_page_info {
@@ -215,8 +222,6 @@ struct be_rx_stats {
	u32 rx_drops_no_skbs;	/* skb allocation errors */
	u32 rx_drops_no_frags;	/* HW has no fetched frags */
	u32 rx_post_fail;	/* page post alloc failures */
	u32 rx_polls;		/* NAPI calls */
	u32 rx_events;
	u32 rx_compl;
	u32 rx_mcast_pkts;
	u32 rx_compl_err;	/* completions with err set */
@@ -249,16 +254,13 @@ struct be_rx_obj {
	struct be_queue_info cq;
	struct be_rx_compl_info rxcp;
	struct be_rx_page_info page_info_tbl[RX_Q_LEN];
	struct be_eq_obj rx_eq;
	struct be_rx_stats stats;
	u8 rss_id;
	bool rx_post_starved;	/* Zero rx frags have been posted to BE */
	u32 cache_line_barrier[16];
};
} ____cacheline_aligned_in_smp;

struct be_drv_stats {
	u32 be_on_die_temperature;
	u32 tx_events;
	u32 eth_red_drops;
	u32 rx_drops_no_pbuf;
	u32 rx_drops_no_txpb;
@@ -320,20 +322,19 @@ struct be_adapter {
	spinlock_t mcc_lock;	/* For serializing mcc cmds to BE card */
	spinlock_t mcc_cq_lock;

	struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
	u32 num_msix_vec;
	u32 num_evt_qs;
	struct be_eq_obj eq_obj[MAX_MSIX_VECTORS];
	struct msix_entry msix_entries[MAX_MSIX_VECTORS];
	bool isr_registered;

	/* TX Rings */
	struct be_eq_obj tx_eq;
	u32 num_tx_qs;
	struct be_tx_obj tx_obj[MAX_TX_QS];
	u8 num_tx_qs;

	u32 cache_line_break[8];

	/* Rx rings */
	struct be_rx_obj rx_obj[MAX_RX_QS];
	u32 num_rx_qs;
	struct be_rx_obj rx_obj[MAX_RX_QS];
	u32 big_page_size;	/* Compounded page size shared by rx wrbs */

	u8 eq_next_idx;
@@ -404,24 +405,34 @@ struct be_adapter {
extern const struct ethtool_ops be_ethtool_ops;

#define msix_enabled(adapter)		(adapter->num_msix_vec > 0)
#define tx_stats(txo)			(&txo->stats)
#define rx_stats(rxo)			(&rxo->stats)
#define num_irqs(adapter)		(msix_enabled(adapter) ?	\
						adapter->num_msix_vec : 1)
#define tx_stats(txo)			(&(txo)->stats)
#define rx_stats(rxo)			(&(rxo)->stats)

#define BE_SET_NETDEV_OPS(netdev, ops)	(netdev->netdev_ops = ops)
/* The default RXQ is the last RXQ */
#define default_rxo(adpt)		(&adpt->rx_obj[adpt->num_rx_qs - 1])

#define for_all_rx_queues(adapter, rxo, i)				\
	for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs;	\
		i++, rxo++)

/* Just skip the first default non-rss queue */
/* Skip the default non-rss queue (last one)*/
#define for_all_rss_queues(adapter, rxo, i)				\
	for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\
	for (i = 0, rxo = &adapter->rx_obj[i]; i < (adapter->num_rx_qs - 1);\
		i++, rxo++)

#define for_all_tx_queues(adapter, txo, i)				\
	for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs;	\
		i++, txo++)

#define for_all_evt_queues(adapter, eqo, i)				\
	for (i = 0, eqo = &adapter->eq_obj[i]; i < adapter->num_evt_qs; \
		i++, eqo++)

#define is_mcc_eqo(eqo)			(eqo->idx == 0)
#define mcc_eqo(adapter)		(&adapter->eq_obj[0])

#define PAGE_SHIFT_4K		12
#define PAGE_SIZE_4K		(1 << PAGE_SHIFT_4K)

+13 −18
Original line number Diff line number Diff line
@@ -235,10 +235,10 @@ void be_async_mcc_disable(struct be_adapter *adapter)
	adapter->mcc_obj.rearm_cq = false;
}

int be_process_mcc(struct be_adapter *adapter, int *status)
int be_process_mcc(struct be_adapter *adapter)
{
	struct be_mcc_compl *compl;
	int num = 0;
	int num = 0, status = 0;
	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;

	spin_lock_bh(&adapter->mcc_cq_lock);
@@ -252,32 +252,32 @@ int be_process_mcc(struct be_adapter *adapter, int *status)
				be_async_grp5_evt_process(adapter,
				compl->flags, compl);
		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
				*status = be_mcc_compl_process(adapter, compl);
				status = be_mcc_compl_process(adapter, compl);
				atomic_dec(&mcc_obj->q.used);
		}
		be_mcc_compl_use(compl);
		num++;
	}

	if (num)
		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);

	spin_unlock_bh(&adapter->mcc_cq_lock);
	return num;
	return status;
}

/* Wait till no more pending mcc requests are present */
static int be_mcc_wait_compl(struct be_adapter *adapter)
{
#define mcc_timeout		120000 /* 12s timeout */
	int i, num, status = 0;
	int i, status = 0;
	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;

	for (i = 0; i < mcc_timeout; i++) {
		if (be_error(adapter))
			return -EIO;

		num = be_process_mcc(adapter, &status);
		if (num)
			be_cq_notify(adapter, mcc_obj->cq.id,
				mcc_obj->rearm_cq, num);
		status = be_process_mcc(adapter);

		if (atomic_read(&mcc_obj->q.used) == 0)
			break;
@@ -726,9 +726,8 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
}

/* Uses Mbox */
int be_cmd_cq_create(struct be_adapter *adapter,
		struct be_queue_info *cq, struct be_queue_info *eq,
		bool sol_evts, bool no_delay, int coalesce_wm)
int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
		struct be_queue_info *eq, bool no_delay, int coalesce_wm)
{
	struct be_mcc_wrb *wrb;
	struct be_cmd_req_cq_create *req;
@@ -759,7 +758,6 @@ int be_cmd_cq_create(struct be_adapter *adapter,
								ctxt, 1);
		AMAP_SET_BITS(struct amap_cq_context_lancer, eqid,
								ctxt, eq->id);
		AMAP_SET_BITS(struct amap_cq_context_lancer, armed, ctxt, 1);
	} else {
		AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
								coalesce_wm);
@@ -768,11 +766,8 @@ int be_cmd_cq_create(struct be_adapter *adapter,
		AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
						__ilog2_u32(cq->len/256));
		AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
		AMAP_SET_BITS(struct amap_cq_context_be, solevent,
								ctxt, sol_evts);
		AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
		AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
		AMAP_SET_BITS(struct amap_cq_context_be, armed, ctxt, 1);
	}

	be_dws_cpu_to_le(ctxt, sizeof(req->context));
@@ -973,7 +968,7 @@ int be_cmd_txq_create(struct be_adapter *adapter,
/* Uses MCC */
int be_cmd_rxq_create(struct be_adapter *adapter,
		struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
		u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id)
		u32 if_id, u32 rss, u8 *rss_id)
{
	struct be_mcc_wrb *wrb;
	struct be_cmd_req_eth_rx_create *req;
@@ -997,7 +992,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
	req->num_pages = 2;
	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
	req->interface_id = cpu_to_le32(if_id);
	req->max_frame_size = cpu_to_le16(max_frame_size);
	req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
	req->rss_queue = cpu_to_le32(rss);

	status = be_mcc_notify_wait(adapter);
+3 −5
Original line number Diff line number Diff line
@@ -1506,8 +1506,7 @@ extern int be_cmd_eq_create(struct be_adapter *adapter,
			struct be_queue_info *eq, int eq_delay);
extern int be_cmd_cq_create(struct be_adapter *adapter,
			struct be_queue_info *cq, struct be_queue_info *eq,
			bool sol_evts, bool no_delay,
			int num_cqe_dma_coalesce);
			bool no_delay, int num_cqe_dma_coalesce);
extern int be_cmd_mccq_create(struct be_adapter *adapter,
			struct be_queue_info *mccq,
			struct be_queue_info *cq);
@@ -1516,8 +1515,7 @@ extern int be_cmd_txq_create(struct be_adapter *adapter,
			struct be_queue_info *cq);
extern int be_cmd_rxq_create(struct be_adapter *adapter,
			struct be_queue_info *rxq, u16 cq_id,
			u16 frag_size, u16 max_frame_size, u32 if_id,
			u32 rss, u8 *rss_id);
			u16 frag_size, u32 if_id, u32 rss, u8 *rss_id);
extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
			int type);
extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
@@ -1546,7 +1544,7 @@ extern int be_cmd_query_fw_cfg(struct be_adapter *adapter,
extern int be_cmd_reset_function(struct be_adapter *adapter);
extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
			u16 table_size);
extern int be_process_mcc(struct be_adapter *adapter, int *status);
extern int be_process_mcc(struct be_adapter *adapter);
extern int be_cmd_set_beacon_state(struct be_adapter *adapter,
			u8 port_num, u8 beacon, u8 status, u8 state);
extern int be_cmd_get_beacon_state(struct be_adapter *adapter,
+24 −72
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};
					FIELDINFO(struct be_drv_stats, field)

static const struct be_ethtool_stat et_stats[] = {
	{DRVSTAT_INFO(tx_events)},
	{DRVSTAT_INFO(rx_crc_errors)},
	{DRVSTAT_INFO(rx_alignment_symbol_errors)},
	{DRVSTAT_INFO(rx_pause_frames)},
@@ -126,8 +125,6 @@ static const struct be_ethtool_stat et_stats[] = {
static const struct be_ethtool_stat et_rx_stats[] = {
	{DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */
	{DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */
	{DRVSTAT_RX_INFO(rx_polls)},
	{DRVSTAT_RX_INFO(rx_events)},
	{DRVSTAT_RX_INFO(rx_compl)},
	{DRVSTAT_RX_INFO(rx_mcast_pkts)},
	/* Number of page allocation failures while posting receive buffers
@@ -154,7 +151,6 @@ static const struct be_ethtool_stat et_tx_stats[] = {
	{DRVSTAT_TX_INFO(tx_reqs)},
	/* Number of TX work request blocks DMAed to HW */
	{DRVSTAT_TX_INFO(tx_wrbs)},
	{DRVSTAT_TX_INFO(tx_compl)},
	/* Number of times the TX queue was stopped due to lack
	 * of spaces in the TXQ.
	 */
@@ -290,86 +286,42 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
	}
}

static int
be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
static int be_get_coalesce(struct net_device *netdev,
			   struct ethtool_coalesce *et)
{
	struct be_adapter *adapter = netdev_priv(netdev);
	struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq;
	struct be_eq_obj *tx_eq = &adapter->tx_eq;
	struct be_eq_obj *eqo = &adapter->eq_obj[0];


	coalesce->rx_coalesce_usecs = rx_eq->cur_eqd;
	coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd;
	coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd;
	et->rx_coalesce_usecs = eqo->cur_eqd;
	et->rx_coalesce_usecs_high = eqo->max_eqd;
	et->rx_coalesce_usecs_low = eqo->min_eqd;

	coalesce->tx_coalesce_usecs = tx_eq->cur_eqd;
	coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd;
	coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd;
	et->tx_coalesce_usecs = eqo->cur_eqd;
	et->tx_coalesce_usecs_high = eqo->max_eqd;
	et->tx_coalesce_usecs_low = eqo->min_eqd;

	coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic;
	coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic;
	et->use_adaptive_rx_coalesce = eqo->enable_aic;
	et->use_adaptive_tx_coalesce = eqo->enable_aic;

	return 0;
}

/*
 * This routine is used to set interrup coalescing delay
/* TX attributes are ignored. Only RX attributes are considered
 * eqd cmd is issued in the worker thread.
 */
static int
be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
static int be_set_coalesce(struct net_device *netdev,
			   struct ethtool_coalesce *et)
{
	struct be_adapter *adapter = netdev_priv(netdev);
	struct be_rx_obj *rxo;
	struct be_eq_obj *rx_eq;
	struct be_eq_obj *tx_eq = &adapter->tx_eq;
	u32 rx_max, rx_min, rx_cur;
	int status = 0, i;
	u32 tx_cur;

	if (coalesce->use_adaptive_tx_coalesce == 1)
		return -EINVAL;

	for_all_rx_queues(adapter, rxo, i) {
		rx_eq = &rxo->rx_eq;

		if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
			rx_eq->cur_eqd = 0;
		rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;

		rx_max = coalesce->rx_coalesce_usecs_high;
		rx_min = coalesce->rx_coalesce_usecs_low;
		rx_cur = coalesce->rx_coalesce_usecs;

		if (rx_eq->enable_aic) {
			if (rx_max > BE_MAX_EQD)
				rx_max = BE_MAX_EQD;
			if (rx_min > rx_max)
				rx_min = rx_max;
			rx_eq->max_eqd = rx_max;
			rx_eq->min_eqd = rx_min;
			if (rx_eq->cur_eqd > rx_max)
				rx_eq->cur_eqd = rx_max;
			if (rx_eq->cur_eqd < rx_min)
				rx_eq->cur_eqd = rx_min;
		} else {
			if (rx_cur > BE_MAX_EQD)
				rx_cur = BE_MAX_EQD;
			if (rx_eq->cur_eqd != rx_cur) {
				status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
						rx_cur);
				if (!status)
					rx_eq->cur_eqd = rx_cur;
			}
		}
	}

	tx_cur = coalesce->tx_coalesce_usecs;

	if (tx_cur > BE_MAX_EQD)
		tx_cur = BE_MAX_EQD;
	if (tx_eq->cur_eqd != tx_cur) {
		status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur);
		if (!status)
			tx_eq->cur_eqd = tx_cur;
	struct be_eq_obj *eqo;
	int i;

	for_all_evt_queues(adapter, eqo, i) {
		eqo->enable_aic = et->use_adaptive_rx_coalesce;
		eqo->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD);
		eqo->min_eqd = min(et->rx_coalesce_usecs_low, eqo->max_eqd);
		eqo->eqd = et->rx_coalesce_usecs;
	}

	return 0;
+356 −456

File changed.

Preview size limit exceeded, changes collapsed.