Browse Source

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: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Sathya Perla 13 years ago
parent
commit
10ef9ab432

+ 38 - 27
drivers/net/ethernet/emulex/benet/be.h

@@ -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,12 +92,16 @@ 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 MAX_RX_POST		BE_NAPI_WEIGHT /* Frags posted at a time */
 #define RX_FRAGS_REFILL_WM	(RX_Q_LEN - MAX_RX_POST)
 
 #define FW_VER_LEN		32
@@ -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
drivers/net/ethernet/emulex/benet/be_cmds.c

@@ -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 @@ err:
 }
 
 /* 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 @@ err:
 /* 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
drivers/net/ethernet/emulex/benet/be_cmds.h

@@ -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
drivers/net/ethernet/emulex/benet/be_ethtool.c

@@ -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;

File diff suppressed because it is too large
+ 269 - 351
drivers/net/ethernet/emulex/benet/be_main.c


Some files were not shown because too many files changed in this diff