diff options
| author | Takashi Iwai <tiwai@suse.de> | 2011-08-08 14:30:29 +0200 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2011-08-08 14:30:29 +0200 | 
| commit | 0a2d31b62dba9b5b92a38c67c9cc42630513662a (patch) | |
| tree | f755d74ec85248de645e10c45ed1a2ed467530f6 /drivers/net/benet | |
| parent | 8039290a91c5dc4414093c086987a5d7738fe2fd (diff) | |
| parent | df944f66784e6d4f2f50739263a4947885d8b6ae (diff) | |
Merge branch 'fix/kconfig' into for-linus
Diffstat (limited to 'drivers/net/benet')
| -rw-r--r-- | drivers/net/benet/be.h | 16 | ||||
| -rw-r--r-- | drivers/net/benet/be_cmds.c | 142 | ||||
| -rw-r--r-- | drivers/net/benet/be_cmds.h | 29 | ||||
| -rw-r--r-- | drivers/net/benet/be_ethtool.c | 55 | ||||
| -rw-r--r-- | drivers/net/benet/be_main.c | 430 | 
5 files changed, 429 insertions, 243 deletions
| diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index a7db870d1641..c85768cd1b18 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -20,7 +20,6 @@  #include <linux/pci.h>  #include <linux/etherdevice.h> -#include <linux/version.h>  #include <linux/delay.h>  #include <net/tcp.h>  #include <net/ip.h> @@ -87,6 +86,7 @@ static inline char *nic_name(struct pci_dev *pdev)  #define MAX_RSS_QS		4	/* BE limit is 4 queues/port */  #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 BE_NAPI_WEIGHT		64  #define MAX_RX_POST 		BE_NAPI_WEIGHT /* Frags posted at a time */ @@ -170,7 +170,6 @@ struct be_tx_stats {  	u32 be_tx_reqs;		/* number of TX requests initiated */  	u32 be_tx_stops;	/* number of times TX Q was stopped */  	u32 be_tx_wrbs;		/* number of tx WRBs used */ -	u32 be_tx_events;	/* number of tx completion events  */  	u32 be_tx_compl;	/* number of tx completion entries processed */  	ulong be_tx_jiffies;  	u64 be_tx_bytes; @@ -184,6 +183,7 @@ struct be_tx_obj {  	struct be_queue_info cq;  	/* Remember the skbs that were transmitted */  	struct sk_buff *sent_skb_list[TX_Q_LEN]; +	struct be_tx_stats stats;  };  /* Struct to remember the pages posted for rx frags */ @@ -199,6 +199,7 @@ struct be_rx_stats {  	u32 rx_polls;	/* number of times NAPI called poll function */  	u32 rx_events;	/* number of ucast rx completion events  */  	u32 rx_compl;	/* number of rx completion entries processed */ +	ulong rx_dropped; /* number of skb allocation errors */  	ulong rx_jiffies;  	u64 rx_bytes;  	u64 rx_bytes_prev; @@ -319,8 +320,8 @@ struct be_adapter {  	/* TX Rings */  	struct be_eq_obj tx_eq; -	struct be_tx_obj tx_obj; -	struct be_tx_stats tx_stats; +	struct be_tx_obj tx_obj[MAX_TX_QS]; +	u8 num_tx_qs;  	u32 cache_line_break[8]; @@ -332,7 +333,6 @@ struct be_adapter {  	u8 eq_next_idx;  	struct be_drv_stats drv_stats; -	struct vlan_group *vlan_grp;  	u16 vlans_added;  	u16 max_vlans;	/* Number of vlans supported */  	u8 vlan_tag[VLAN_N_VID]; @@ -391,7 +391,7 @@ struct be_adapter {  extern const struct ethtool_ops be_ethtool_ops;  #define msix_enabled(adapter)		(adapter->num_msix_vec > 0) -#define tx_stats(adapter)		(&adapter->tx_stats) +#define tx_stats(txo)			(&txo->stats)  #define rx_stats(rxo)			(&rxo->stats)  #define BE_SET_NETDEV_OPS(netdev, ops)	(netdev->netdev_ops = ops) @@ -405,6 +405,10 @@ extern const struct ethtool_ops be_ethtool_ops;  	for (i = 0, rxo = &adapter->rx_obj[i+1]; 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 PAGE_SHIFT_4K		12  #define PAGE_SIZE_4K		(1 << PAGE_SHIFT_4K) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 81654ae16c63..054fa67bc4e3 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -106,14 +106,24 @@ static int be_mcc_compl_process(struct be_adapter *adapter,  			netdev_stats_update(adapter);  			adapter->stats_cmd_sent = false;  		} -	} else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) && -		   (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) { -		extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & -				CQE_STATUS_EXTD_MASK; -		dev_warn(&adapter->pdev->dev, -		"Error in cmd completion - opcode %d, compl %d, extd %d\n", -			compl->tag0, compl_status, extd_status); +	} else { +		if (compl_status == MCC_STATUS_NOT_SUPPORTED || +			compl_status == MCC_STATUS_ILLEGAL_REQUEST) +			goto done; + +		if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { +			dev_warn(&adapter->pdev->dev, "This domain(VM) is not " +				"permitted to execute this cmd (opcode %d)\n", +				compl->tag0); +		} else { +			extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & +					CQE_STATUS_EXTD_MASK; +			dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:" +				"status %d, extd-status %d\n", +				compl->tag0, compl_status, extd_status); +		}  	} +done:  	return compl_status;  } @@ -799,12 +809,12 @@ static u32 be_encoded_q_len(int q_len)  	return len_encoded;  } -int be_cmd_mccq_create(struct be_adapter *adapter, +int be_cmd_mccq_ext_create(struct be_adapter *adapter,  			struct be_queue_info *mccq,  			struct be_queue_info *cq)  {  	struct be_mcc_wrb *wrb; -	struct be_cmd_req_mcc_create *req; +	struct be_cmd_req_mcc_ext_create *req;  	struct be_dma_mem *q_mem = &mccq->dma_mem;  	void *ctxt;  	int status; @@ -859,6 +869,67 @@ int be_cmd_mccq_create(struct be_adapter *adapter,  	return status;  } +int be_cmd_mccq_org_create(struct be_adapter *adapter, +			struct be_queue_info *mccq, +			struct be_queue_info *cq) +{ +	struct be_mcc_wrb *wrb; +	struct be_cmd_req_mcc_create *req; +	struct be_dma_mem *q_mem = &mccq->dma_mem; +	void *ctxt; +	int status; + +	if (mutex_lock_interruptible(&adapter->mbox_lock)) +		return -1; + +	wrb = wrb_from_mbox(adapter); +	req = embedded_payload(wrb); +	ctxt = &req->context; + +	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, +			OPCODE_COMMON_MCC_CREATE); + +	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, +			OPCODE_COMMON_MCC_CREATE, sizeof(*req)); + +	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + +	AMAP_SET_BITS(struct amap_mcc_context_be, valid, ctxt, 1); +	AMAP_SET_BITS(struct amap_mcc_context_be, ring_size, ctxt, +			be_encoded_q_len(mccq->len)); +	AMAP_SET_BITS(struct amap_mcc_context_be, cq_id, ctxt, cq->id); + +	be_dws_cpu_to_le(ctxt, sizeof(req->context)); + +	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + +	status = be_mbox_notify_wait(adapter); +	if (!status) { +		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); +		mccq->id = le16_to_cpu(resp->id); +		mccq->created = true; +	} + +	mutex_unlock(&adapter->mbox_lock); +	return status; +} + +int be_cmd_mccq_create(struct be_adapter *adapter, +			struct be_queue_info *mccq, +			struct be_queue_info *cq) +{ +	int status; + +	status = be_cmd_mccq_ext_create(adapter, mccq, cq); +	if (status && !lancer_chip(adapter)) { +		dev_warn(&adapter->pdev->dev, "Upgrade to F/W ver 2.102.235.0 " +			"or newer to avoid conflicting priorities between NIC " +			"and FCoE traffic"); +		status = be_cmd_mccq_org_create(adapter, mccq, cq); +	} +	return status; +} +  int be_cmd_txq_create(struct be_adapter *adapter,  			struct be_queue_info *txq,  			struct be_queue_info *cq) @@ -913,7 +984,7 @@ int be_cmd_txq_create(struct be_adapter *adapter,  	return status;  } -/* Uses mbox */ +/* 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) @@ -923,10 +994,13 @@ int be_cmd_rxq_create(struct be_adapter *adapter,  	struct be_dma_mem *q_mem = &rxq->dma_mem;  	int status; -	if (mutex_lock_interruptible(&adapter->mbox_lock)) -		return -1; +	spin_lock_bh(&adapter->mcc_lock); -	wrb = wrb_from_mbox(adapter); +	wrb = wrb_from_mccq(adapter); +	if (!wrb) { +		status = -EBUSY; +		goto err; +	}  	req = embedded_payload(wrb);  	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, @@ -943,7 +1017,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,  	req->max_frame_size = cpu_to_le16(max_frame_size);  	req->rss_queue = cpu_to_le32(rss); -	status = be_mbox_notify_wait(adapter); +	status = be_mcc_notify_wait(adapter);  	if (!status) {  		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);  		rxq->id = le16_to_cpu(resp->id); @@ -951,8 +1025,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter,  		*rss_id = resp->rss_id;  	} -	mutex_unlock(&adapter->mbox_lock); - +err: +	spin_unlock_bh(&adapter->mcc_lock);  	return status;  } @@ -1007,9 +1081,40 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,  	req->id = cpu_to_le16(q->id);  	status = be_mbox_notify_wait(adapter); +	if (!status) +		q->created = false;  	mutex_unlock(&adapter->mbox_lock); +	return status; +} + +/* Uses MCC */ +int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) +{ +	struct be_mcc_wrb *wrb; +	struct be_cmd_req_q_destroy *req; +	int status; +	spin_lock_bh(&adapter->mcc_lock); + +	wrb = wrb_from_mccq(adapter); +	if (!wrb) { +		status = -EBUSY; +		goto err; +	} +	req = embedded_payload(wrb); + +	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_RX_DESTROY); +	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_DESTROY, +		sizeof(*req)); +	req->id = cpu_to_le16(q->id); + +	status = be_mcc_notify_wait(adapter); +	if (!status) +		q->created = false; + +err: +	spin_unlock_bh(&adapter->mcc_lock);  	return status;  } @@ -2273,8 +2378,7 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)  	status = be_mbox_notify_wait(adapter);  	if (!status) { -		attribs = (struct mgmt_controller_attrib *)( attribs_cmd.va + -					sizeof(struct be_cmd_resp_hdr)); +		attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);  		adapter->hba_port_num = attribs->hba_attribs.phy_port;  	} @@ -2286,7 +2390,7 @@ err:  }  /* Uses mbox */ -int be_cmd_check_native_mode(struct be_adapter *adapter) +int be_cmd_req_native_mode(struct be_adapter *adapter)  {  	struct be_mcc_wrb *wrb;  	struct be_cmd_req_set_func_cap *req; diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 8148cc66cbe9..8e4d48824fe9 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -51,17 +51,12 @@ struct be_mcc_wrb {  /* Completion Status */  enum { -	MCC_STATUS_SUCCESS = 0x0, -/* The client does not have sufficient privileges to execute the command */ -	MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1, -/* A parameter in the command was invalid. */ -	MCC_STATUS_INVALID_PARAMETER = 0x2, -/* There are insufficient chip resources to execute the command */ -	MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3, -/* The command is completing because the queue was getting flushed */ -	MCC_STATUS_QUEUE_FLUSHING = 0x4, -/* The command is completing with a DMA error */ -	MCC_STATUS_DMA_FAILED = 0x5, +	MCC_STATUS_SUCCESS = 0, +	MCC_STATUS_FAILED = 1, +	MCC_STATUS_ILLEGAL_REQUEST = 2, +	MCC_STATUS_ILLEGAL_FIELD = 3, +	MCC_STATUS_INSUFFICIENT_BUFFER = 4, +	MCC_STATUS_UNAUTHORIZED_REQUEST = 5,  	MCC_STATUS_NOT_SUPPORTED = 66  }; @@ -434,6 +429,14 @@ struct be_cmd_req_mcc_create {  	struct be_cmd_req_hdr hdr;  	u16 num_pages;  	u16 cq_id; +	u8 context[sizeof(struct amap_mcc_context_be) / 8]; +	struct phys_addr pages[8]; +} __packed; + +struct be_cmd_req_mcc_ext_create { +	struct be_cmd_req_hdr hdr; +	u16 num_pages; +	u16 cq_id;  	u32 async_event_bitmap[1];  	u8 context[sizeof(struct amap_mcc_context_be) / 8];  	struct phys_addr pages[8]; @@ -1479,6 +1482,8 @@ extern int be_cmd_rxq_create(struct be_adapter *adapter,  			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, +			struct be_queue_info *q);  extern int be_cmd_link_status_query(struct be_adapter *adapter,  			bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom);  extern int be_cmd_reset(struct be_adapter *adapter); @@ -1540,7 +1545,7 @@ extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);  extern void be_detect_dump_ue(struct be_adapter *adapter);  extern int be_cmd_get_die_temperature(struct be_adapter *adapter);  extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); -extern int be_cmd_check_native_mode(struct be_adapter *adapter); +extern int be_cmd_req_native_mode(struct be_adapter *adapter);  extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);  extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index facfe3ca5c40..7fd8130d86ea 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -52,12 +52,7 @@ static const struct be_ethtool_stat et_stats[] = {  	{NETSTAT_INFO(tx_errors)},  	{NETSTAT_INFO(rx_dropped)},  	{NETSTAT_INFO(tx_dropped)}, -	{DRVSTAT_TX_INFO(be_tx_rate)}, -	{DRVSTAT_TX_INFO(be_tx_reqs)}, -	{DRVSTAT_TX_INFO(be_tx_wrbs)}, -	{DRVSTAT_TX_INFO(be_tx_stops)}, -	{DRVSTAT_TX_INFO(be_tx_events)}, -	{DRVSTAT_TX_INFO(be_tx_compl)}, +	{DRVSTAT_INFO(be_tx_events)},  	{DRVSTAT_INFO(rx_crc_errors)},  	{DRVSTAT_INFO(rx_alignment_symbol_errors)},  	{DRVSTAT_INFO(rx_pause_frames)}, @@ -107,10 +102,21 @@ static const struct be_ethtool_stat et_rx_stats[] = {  	{DRVSTAT_RX_INFO(rx_compl)},  	{DRVSTAT_RX_INFO(rx_mcast_pkts)},  	{DRVSTAT_RX_INFO(rx_post_fail)}, +	{DRVSTAT_RX_INFO(rx_dropped)},  	{ERXSTAT_INFO(rx_drops_no_fragments)}  };  #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) +/* Stats related to multi TX queues */ +static const struct be_ethtool_stat et_tx_stats[] = { +	{DRVSTAT_TX_INFO(be_tx_rate)}, +	{DRVSTAT_TX_INFO(be_tx_reqs)}, +	{DRVSTAT_TX_INFO(be_tx_wrbs)}, +	{DRVSTAT_TX_INFO(be_tx_stops)}, +	{DRVSTAT_TX_INFO(be_tx_compl)} +}; +#define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) +  static const char et_self_tests[][ETH_GSTRING_LEN] = {  	"MAC Loopback test",  	"PHY Loopback test", @@ -253,17 +259,15 @@ be_get_ethtool_stats(struct net_device *netdev,  {  	struct be_adapter *adapter = netdev_priv(netdev);  	struct be_rx_obj *rxo; +	struct be_tx_obj *txo;  	void *p = NULL; -	int i, j; +	int i, j, base;  	for (i = 0; i < ETHTOOL_STATS_NUM; i++) {  		switch (et_stats[i].type) {  		case NETSTAT:  			p = &netdev->stats;  			break; -		case DRVSTAT_TX: -			p = &adapter->tx_stats; -			break;  		case DRVSTAT:  			p = &adapter->drv_stats;  			break; @@ -274,6 +278,7 @@ be_get_ethtool_stats(struct net_device *netdev,  				*(u64 *)p: *(u32 *)p;  	} +	base = ETHTOOL_STATS_NUM;  	for_all_rx_queues(adapter, rxo, j) {  		for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) {  			switch (et_rx_stats[i].type) { @@ -285,11 +290,21 @@ be_get_ethtool_stats(struct net_device *netdev,  								rxo->q.id;  				break;  			} -			data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] = +			data[base + j * ETHTOOL_RXSTATS_NUM + i] =  				(et_rx_stats[i].size == sizeof(u64)) ?  					*(u64 *)p: *(u32 *)p;  		}  	} + +	base = ETHTOOL_STATS_NUM + adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM; +	for_all_tx_queues(adapter, txo, j) { +		for (i = 0; i < ETHTOOL_TXSTATS_NUM; i++) { +			p = (u8 *)&txo->stats + et_tx_stats[i].offset; +			data[base + j * ETHTOOL_TXSTATS_NUM + i] = +				(et_tx_stats[i].size == sizeof(u64)) ? +					*(u64 *)p: *(u32 *)p; +		} +	}  }  static void @@ -312,6 +327,13 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset,  				data += ETH_GSTRING_LEN;  			}  		} +		for (i = 0; i < adapter->num_tx_qs; i++) { +			for (j = 0; j < ETHTOOL_TXSTATS_NUM; j++) { +				sprintf(data, "txq%d: %s", i, +					et_tx_stats[j].desc); +				data += ETH_GSTRING_LEN; +			} +		}  		break;  	case ETH_SS_TEST:  		for (i = 0; i < ETHTOOL_TESTS_NUM; i++) { @@ -331,7 +353,8 @@ static int be_get_sset_count(struct net_device *netdev, int stringset)  		return ETHTOOL_TESTS_NUM;  	case ETH_SS_STATS:  		return ETHTOOL_STATS_NUM + -			adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM; +			adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM + +			adapter->num_tx_qs * ETHTOOL_TXSTATS_NUM;  	default:  		return -EINVAL;  	} @@ -386,7 +409,7 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)  		}  		status = be_cmd_get_phy_info(adapter, &phy_cmd);  		if (!status) { -			resp = (struct be_cmd_resp_get_phy_info *) phy_cmd.va; +			resp = phy_cmd.va;  			intf_type = le16_to_cpu(resp->interface_type);  			switch (intf_type) { @@ -457,10 +480,10 @@ be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)  	struct be_adapter *adapter = netdev_priv(netdev);  	ring->rx_max_pending = adapter->rx_obj[0].q.len; -	ring->tx_max_pending = adapter->tx_obj.q.len; +	ring->tx_max_pending = adapter->tx_obj[0].q.len;  	ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used); -	ring->tx_pending = atomic_read(&adapter->tx_obj.q.used); +	ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used);  }  static void @@ -690,7 +713,7 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,  	status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd);  	if (!status) { -		resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va; +		resp = eeprom_cmd.va;  		memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);  	}  	dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va, diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a485f7fdaf37..c411bb1845fd 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -33,10 +33,6 @@ module_param(num_vfs, uint, S_IRUGO);  MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");  MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize"); -static bool multi_rxq = true; -module_param(multi_rxq, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(multi_rxq, "Multi Rx Queue support. Enabled by default"); -  static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {  	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },  	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, @@ -48,7 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {  };  MODULE_DEVICE_TABLE(pci, be_dev_ids);  /* UE Status Low CSR */ -static char *ue_status_low_desc[] = { +static const char * const ue_status_low_desc[] = {  	"CEV",  	"CTX",  	"DBUF", @@ -83,7 +79,7 @@ static char *ue_status_low_desc[] = {  	"MPU_INTPEND"  };  /* UE Status High CSR */ -static char *ue_status_hi_desc[] = { +static const char * const ue_status_hi_desc[] = {  	"LPCMEMHOST",  	"MGMT_MAC",  	"PCS0ONLINE", @@ -107,7 +103,7 @@ static char *ue_status_hi_desc[] = {  	"HOST7",  	"HOST8",  	"HOST9", -	"NETC" +	"NETC",  	"Unknown",  	"Unknown",  	"Unknown", @@ -362,8 +358,8 @@ static void populate_lancer_stats(struct be_adapter *adapter)  	drvs->rx_priority_pause_frames = 0;  	drvs->pmem_fifo_overflow_drop = 0;  	drvs->rx_pause_frames = -		make_64bit_val(pport_stats->rx_pause_frames_lo, -				 pport_stats->rx_pause_frames_hi); +		make_64bit_val(pport_stats->rx_pause_frames_hi, +				 pport_stats->rx_pause_frames_lo);  	drvs->rx_crc_errors = make_64bit_val(pport_stats->rx_crc_errors_hi,  						pport_stats->rx_crc_errors_lo);  	drvs->rx_control_frames = @@ -427,31 +423,40 @@ void netdev_stats_update(struct be_adapter *adapter)  	struct be_drv_stats *drvs = &adapter->drv_stats;  	struct net_device_stats *dev_stats = &adapter->netdev->stats;  	struct be_rx_obj *rxo; +	struct be_tx_obj *txo; +	unsigned long pkts = 0, bytes = 0, mcast = 0, drops = 0;  	int i; -	memset(dev_stats, 0, sizeof(*dev_stats));  	for_all_rx_queues(adapter, rxo, i) { -		dev_stats->rx_packets += rx_stats(rxo)->rx_pkts; -		dev_stats->rx_bytes += rx_stats(rxo)->rx_bytes; -		dev_stats->multicast += rx_stats(rxo)->rx_mcast_pkts; +		pkts += rx_stats(rxo)->rx_pkts; +		bytes += rx_stats(rxo)->rx_bytes; +		mcast += rx_stats(rxo)->rx_mcast_pkts; +		drops += rx_stats(rxo)->rx_dropped;  		/*  no space in linux buffers: best possible approximation */  		if (adapter->generation == BE_GEN3) {  			if (!(lancer_chip(adapter))) { -				struct be_erx_stats_v1 *erx_stats = +				struct be_erx_stats_v1 *erx =  					be_erx_stats_from_cmd(adapter); -				dev_stats->rx_dropped += -				erx_stats->rx_drops_no_fragments[rxo->q.id]; +				drops += erx->rx_drops_no_fragments[rxo->q.id];  			}  		} else { -			struct be_erx_stats_v0 *erx_stats = +			struct be_erx_stats_v0 *erx =  					be_erx_stats_from_cmd(adapter); -			dev_stats->rx_dropped += -				erx_stats->rx_drops_no_fragments[rxo->q.id]; +			drops += erx->rx_drops_no_fragments[rxo->q.id];  		}  	} +	dev_stats->rx_packets = pkts; +	dev_stats->rx_bytes = bytes; +	dev_stats->multicast = mcast; +	dev_stats->rx_dropped = drops; -	dev_stats->tx_packets = tx_stats(adapter)->be_tx_pkts; -	dev_stats->tx_bytes = tx_stats(adapter)->be_tx_bytes; +	pkts = bytes = 0; +	for_all_tx_queues(adapter, txo, i) { +		pkts += tx_stats(txo)->be_tx_pkts; +		bytes += tx_stats(txo)->be_tx_bytes; +	} +	dev_stats->tx_packets = pkts; +	dev_stats->tx_bytes = bytes;  	/* bad pkts received */  	dev_stats->rx_errors = drvs->rx_crc_errors + @@ -554,9 +559,9 @@ static u32 be_calc_rate(u64 bytes, unsigned long ticks)  	return rate;  } -static void be_tx_rate_update(struct be_adapter *adapter) +static void be_tx_rate_update(struct be_tx_obj *txo)  { -	struct be_tx_stats *stats = tx_stats(adapter); +	struct be_tx_stats *stats = tx_stats(txo);  	ulong now = jiffies;  	/* Wrapped around? */ @@ -575,10 +580,11 @@ static void be_tx_rate_update(struct be_adapter *adapter)  	}  } -static void be_tx_stats_update(struct be_adapter *adapter, +static void be_tx_stats_update(struct be_tx_obj *txo,  			u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped)  { -	struct be_tx_stats *stats = tx_stats(adapter); +	struct be_tx_stats *stats = tx_stats(txo); +  	stats->be_tx_reqs++;  	stats->be_tx_wrbs += wrb_cnt;  	stats->be_tx_bytes += copied; @@ -648,7 +654,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,  			AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1);  	} -	if (adapter->vlan_grp && vlan_tx_tag_present(skb)) { +	if (vlan_tx_tag_present(skb)) {  		AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1);  		vlan_tag = vlan_tx_tag_get(skb);  		vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; @@ -682,14 +688,13 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,  	}  } -static int make_tx_wrbs(struct be_adapter *adapter, +static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq,  		struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb)  {  	dma_addr_t busaddr;  	int i, copied = 0;  	struct device *dev = &adapter->pdev->dev;  	struct sk_buff *first_skb = skb; -	struct be_queue_info *txq = &adapter->tx_obj.q;  	struct be_eth_wrb *wrb;  	struct be_eth_hdr_wrb *hdr;  	bool map_single = false; @@ -753,19 +758,19 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,  			struct net_device *netdev)  {  	struct be_adapter *adapter = netdev_priv(netdev); -	struct be_tx_obj *tx_obj = &adapter->tx_obj; -	struct be_queue_info *txq = &tx_obj->q; +	struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; +	struct be_queue_info *txq = &txo->q;  	u32 wrb_cnt = 0, copied = 0;  	u32 start = txq->head;  	bool dummy_wrb, stopped = false;  	wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); -	copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb); +	copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb);  	if (copied) {  		/* record the sent skb in the sent_skb table */ -		BUG_ON(tx_obj->sent_skb_list[start]); -		tx_obj->sent_skb_list[start] = skb; +		BUG_ON(txo->sent_skb_list[start]); +		txo->sent_skb_list[start] = skb;  		/* Ensure txq has space for the next skb; Else stop the queue  		 * *BEFORE* ringing the tx doorbell, so that we serialze the @@ -774,13 +779,13 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,  		atomic_add(wrb_cnt, &txq->used);  		if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >=  								txq->len) { -			netif_stop_queue(netdev); +			netif_stop_subqueue(netdev, skb_get_queue_mapping(skb));  			stopped = true;  		}  		be_txq_notify(adapter, txq->id, wrb_cnt); -		be_tx_stats_update(adapter, wrb_cnt, copied, +		be_tx_stats_update(txo, wrb_cnt, copied,  				skb_shinfo(skb)->gso_segs, stopped);  	} else {  		txq->head = start; @@ -842,13 +847,6 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num)  	return status;  } -static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) -{ -	struct be_adapter *adapter = netdev_priv(netdev); - -	adapter->vlan_grp = grp; -} -  static void be_vlan_add_vid(struct net_device *netdev, u16 vid)  {  	struct be_adapter *adapter = netdev_priv(netdev); @@ -867,7 +865,6 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)  	struct be_adapter *adapter = netdev_priv(netdev);  	adapter->vlans_added--; -	vlan_group_set_device(adapter->vlan_grp, vid, NULL);  	if (!be_physfn(adapter))  		return; @@ -1177,8 +1174,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,  	skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN);  	if (unlikely(!skb)) { -		if (net_ratelimit()) -			dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); +		rxo->stats.rx_dropped++;  		be_rx_compl_discard(adapter, rxo, rxcp);  		return;  	} @@ -1196,16 +1192,10 @@ static void be_rx_compl_process(struct be_adapter *adapter,  		skb->rxhash = rxcp->rss_hash; -	if (unlikely(rxcp->vlanf)) { -		if (!adapter->vlan_grp || adapter->vlans_added == 0) { -			kfree_skb(skb); -			return; -		} -		vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, -					rxcp->vlan_tag); -	} else { -		netif_receive_skb(skb); -	} +	if (unlikely(rxcp->vlanf)) +		__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + +	netif_receive_skb(skb);  }  /* Process the RX completion indicated by rxcp when GRO is enabled */ @@ -1259,11 +1249,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,  	if (adapter->netdev->features & NETIF_F_RXHASH)  		skb->rxhash = rxcp->rss_hash; -	if (likely(!rxcp->vlanf)) -		napi_gro_frags(&eq_obj->napi); -	else -		vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, -				rxcp->vlan_tag); +	if (unlikely(rxcp->vlanf)) +		__vlan_hwaccel_put_tag(skb, rxcp->vlan_tag); + +	napi_gro_frags(&eq_obj->napi);  }  static void be_parse_rx_compl_v1(struct be_adapter *adapter, @@ -1459,11 +1448,12 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq)  	return txcp;  } -static u16 be_tx_compl_process(struct be_adapter *adapter, u16 last_index) +static u16 be_tx_compl_process(struct be_adapter *adapter, +		struct be_tx_obj *txo, u16 last_index)  { -	struct be_queue_info *txq = &adapter->tx_obj.q; +	struct be_queue_info *txq = &txo->q;  	struct be_eth_wrb *wrb; -	struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; +	struct sk_buff **sent_skbs = txo->sent_skb_list;  	struct sk_buff *sent_skb;  	u16 cur_index, num_wrbs = 1; /* account for hdr wrb */  	bool unmap_skb_hdr = true; @@ -1504,7 +1494,8 @@ static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)  }  static int event_handle(struct be_adapter *adapter, -			struct be_eq_obj *eq_obj) +			struct be_eq_obj *eq_obj, +			bool rearm)  {  	struct be_eq_entry *eqe;  	u16 num = 0; @@ -1517,7 +1508,10 @@ static int event_handle(struct be_adapter *adapter,  	/* Deal with any spurious interrupts that come  	 * without events  	 */ -	be_eq_notify(adapter, eq_obj->q.id, true, true, num); +	if (!num) +		rearm = true; + +	be_eq_notify(adapter, eq_obj->q.id, rearm, true, num);  	if (num)  		napi_schedule(&eq_obj->napi); @@ -1563,15 +1557,17 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)  		memset(page_info, 0, sizeof(*page_info));  	}  	BUG_ON(atomic_read(&rxq->used)); +	rxq->tail = rxq->head = 0;  } -static void be_tx_compl_clean(struct be_adapter *adapter) +static void be_tx_compl_clean(struct be_adapter *adapter, +				struct be_tx_obj *txo)  { -	struct be_queue_info *tx_cq = &adapter->tx_obj.cq; -	struct be_queue_info *txq = &adapter->tx_obj.q; +	struct be_queue_info *tx_cq = &txo->cq; +	struct be_queue_info *txq = &txo->q;  	struct be_eth_tx_compl *txcp;  	u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0; -	struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; +	struct sk_buff **sent_skbs = txo->sent_skb_list;  	struct sk_buff *sent_skb;  	bool dummy_wrb; @@ -1580,7 +1576,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter)  		while ((txcp = be_tx_compl_get(tx_cq))) {  			end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,  					wrb_index, txcp); -			num_wrbs += be_tx_compl_process(adapter, end_idx); +			num_wrbs += be_tx_compl_process(adapter, txo, end_idx);  			cmpl++;  		}  		if (cmpl) { @@ -1607,7 +1603,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter)  		index_adv(&end_idx,  			wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,  			txq->len); -		num_wrbs = be_tx_compl_process(adapter, end_idx); +		num_wrbs = be_tx_compl_process(adapter, txo, end_idx);  		atomic_sub(num_wrbs, &txq->used);  	}  } @@ -1666,16 +1662,20 @@ err:  static void be_tx_queues_destroy(struct be_adapter *adapter)  {  	struct be_queue_info *q; +	struct be_tx_obj *txo; +	u8 i; -	q = &adapter->tx_obj.q; -	if (q->created) -		be_cmd_q_destroy(adapter, q, QTYPE_TXQ); -	be_queue_free(adapter, q); +	for_all_tx_queues(adapter, txo, i) { +		q = &txo->q; +		if (q->created) +			be_cmd_q_destroy(adapter, q, QTYPE_TXQ); +		be_queue_free(adapter, q); -	q = &adapter->tx_obj.cq; -	if (q->created) -		be_cmd_q_destroy(adapter, q, QTYPE_CQ); -	be_queue_free(adapter, q); +		q = &txo->cq; +		if (q->created) +			be_cmd_q_destroy(adapter, q, QTYPE_CQ); +		be_queue_free(adapter, q); +	}  	/* Clear any residual events */  	be_eq_clean(adapter, &adapter->tx_eq); @@ -1686,56 +1686,48 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)  	be_queue_free(adapter, q);  } +/* One TX event queue is shared by all TX compl qs */  static int be_tx_queues_create(struct be_adapter *adapter)  {  	struct be_queue_info *eq, *q, *cq; +	struct be_tx_obj *txo; +	u8 i;  	adapter->tx_eq.max_eqd = 0;  	adapter->tx_eq.min_eqd = 0;  	adapter->tx_eq.cur_eqd = 96;  	adapter->tx_eq.enable_aic = false; -	/* Alloc Tx Event queue */ +  	eq = &adapter->tx_eq.q; -	if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, sizeof(struct be_eq_entry))) +	if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, +		sizeof(struct be_eq_entry)))  		return -1; -	/* Ask BE to create Tx Event queue */  	if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd)) -		goto tx_eq_free; - +		goto err;  	adapter->tx_eq.eq_idx = adapter->eq_next_idx++; - -	/* Alloc TX eth compl queue */ -	cq = &adapter->tx_obj.cq; -	if (be_queue_alloc(adapter, cq, TX_CQ_LEN, +	for_all_tx_queues(adapter, txo, i) { +		cq = &txo->cq; +		if (be_queue_alloc(adapter, cq, TX_CQ_LEN,  			sizeof(struct be_eth_tx_compl))) -		goto tx_eq_destroy; +			goto err; -	/* Ask BE to create Tx eth compl queue */ -	if (be_cmd_cq_create(adapter, cq, eq, false, false, 3)) -		goto tx_cq_free; +		if (be_cmd_cq_create(adapter, cq, eq, false, false, 3)) +			goto err; -	/* Alloc TX eth queue */ -	q = &adapter->tx_obj.q; -	if (be_queue_alloc(adapter, q, TX_Q_LEN, sizeof(struct be_eth_wrb))) -		goto tx_cq_destroy; +		q = &txo->q; +		if (be_queue_alloc(adapter, q, TX_Q_LEN, +			sizeof(struct be_eth_wrb))) +			goto err; -	/* Ask BE to create Tx eth queue */ -	if (be_cmd_txq_create(adapter, q, cq)) -		goto tx_q_free; +		if (be_cmd_txq_create(adapter, q, cq)) +			goto err; +	}  	return 0; -tx_q_free: -	be_queue_free(adapter, q); -tx_cq_destroy: -	be_cmd_q_destroy(adapter, cq, QTYPE_CQ); -tx_cq_free: -	be_queue_free(adapter, cq); -tx_eq_destroy: -	be_cmd_q_destroy(adapter, eq, QTYPE_EQ); -tx_eq_free: -	be_queue_free(adapter, eq); +err: +	be_tx_queues_destroy(adapter);  	return -1;  } @@ -1746,36 +1738,23 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)  	int i;  	for_all_rx_queues(adapter, rxo, i) { -		q = &rxo->q; -		if (q->created) { -			be_cmd_q_destroy(adapter, q, QTYPE_RXQ); -			/* After the rxq is invalidated, wait for a grace time -			 * of 1ms for all dma to end and the flush compl to -			 * arrive -			 */ -			mdelay(1); -			be_rx_q_clean(adapter, rxo); -		} -		be_queue_free(adapter, q); +		be_queue_free(adapter, &rxo->q);  		q = &rxo->cq;  		if (q->created)  			be_cmd_q_destroy(adapter, q, QTYPE_CQ);  		be_queue_free(adapter, q); -		/* Clear any residual events */  		q = &rxo->rx_eq.q; -		if (q->created) { -			be_eq_clean(adapter, &rxo->rx_eq); +		if (q->created)  			be_cmd_q_destroy(adapter, q, QTYPE_EQ); -		}  		be_queue_free(adapter, q);  	}  }  static u32 be_num_rxqs_want(struct be_adapter *adapter)  { -	if (multi_rxq && (adapter->function_caps & BE_FUNCTION_CAPS_RSS) && +	if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&  		!adapter->sriov_enabled && !(adapter->function_mode & 0x400)) {  		return 1 + MAX_RSS_QS; /* one default non-RSS queue */  	} else { @@ -1827,30 +1806,14 @@ static int be_rx_queues_create(struct be_adapter *adapter)  		rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);  		if (rc)  			goto err; -		/* Rx Q */ + +		/* Rx Q - will be created in be_open() */  		q = &rxo->q;  		rc = be_queue_alloc(adapter, q, RX_Q_LEN,  				sizeof(struct be_eth_rx_d));  		if (rc)  			goto err; -		rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size, -			BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, -			(i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id); -		if (rc) -			goto err; -	} - -	if (be_multi_rxq(adapter)) { -		u8 rsstable[MAX_RSS_QS]; - -		for_all_rss_queues(adapter, rxo, i) -			rsstable[i] = rxo->rss_id; - -		rc = be_cmd_rss_config(adapter, rsstable, -			adapter->num_rx_qs - 1); -		if (rc) -			goto err;  	}  	return 0; @@ -1876,10 +1839,10 @@ static irqreturn_t be_intx(int irq, void *dev)  	if (lancer_chip(adapter)) {  		if (event_peek(&adapter->tx_eq)) -			tx = event_handle(adapter, &adapter->tx_eq); +			tx = event_handle(adapter, &adapter->tx_eq, false);  		for_all_rx_queues(adapter, rxo, i) {  			if (event_peek(&rxo->rx_eq)) -				rx |= event_handle(adapter, &rxo->rx_eq); +				rx |= event_handle(adapter, &rxo->rx_eq, true);  		}  		if (!(tx || rx)) @@ -1892,11 +1855,11 @@ static irqreturn_t be_intx(int irq, void *dev)  			return IRQ_NONE;  		if ((1 << adapter->tx_eq.eq_idx & isr)) -			event_handle(adapter, &adapter->tx_eq); +			event_handle(adapter, &adapter->tx_eq, false);  		for_all_rx_queues(adapter, rxo, i) {  			if ((1 << rxo->rx_eq.eq_idx & isr)) -				event_handle(adapter, &rxo->rx_eq); +				event_handle(adapter, &rxo->rx_eq, true);  		}  	} @@ -1908,7 +1871,7 @@ static irqreturn_t be_msix_rx(int irq, void *dev)  	struct be_rx_obj *rxo = dev;  	struct be_adapter *adapter = rxo->adapter; -	event_handle(adapter, &rxo->rx_eq); +	event_handle(adapter, &rxo->rx_eq, true);  	return IRQ_HANDLED;  } @@ -1917,7 +1880,7 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev)  {  	struct be_adapter *adapter = dev; -	event_handle(adapter, &adapter->tx_eq); +	event_handle(adapter, &adapter->tx_eq, false);  	return IRQ_HANDLED;  } @@ -1978,45 +1941,48 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)  	struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi);  	struct be_adapter *adapter =  		container_of(tx_eq, struct be_adapter, tx_eq); -	struct be_queue_info *txq = &adapter->tx_obj.q; -	struct be_queue_info *tx_cq = &adapter->tx_obj.cq; +	struct be_tx_obj *txo;  	struct be_eth_tx_compl *txcp; -	int tx_compl = 0, mcc_compl, status = 0; -	u16 end_idx, num_wrbs = 0; +	int tx_compl, mcc_compl, status = 0; +	u8 i; +	u16 num_wrbs; + +	for_all_tx_queues(adapter, txo, i) { +		tx_compl = 0; +		num_wrbs = 0; +		while ((txcp = be_tx_compl_get(&txo->cq))) { +			num_wrbs += be_tx_compl_process(adapter, txo, +				AMAP_GET_BITS(struct amap_eth_tx_compl, +					wrb_index, txcp)); +			tx_compl++; +		} +		if (tx_compl) { +			be_cq_notify(adapter, txo->cq.id, true, tx_compl); -	while ((txcp = be_tx_compl_get(tx_cq))) { -		end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, -				wrb_index, txcp); -		num_wrbs += be_tx_compl_process(adapter, end_idx); -		tx_compl++; +			atomic_sub(num_wrbs, &txo->q.used); + +			/* As Tx wrbs have been freed up, wake up netdev queue +			 * if it was stopped due to lack of tx wrbs.  */ +			if (__netif_subqueue_stopped(adapter->netdev, i) && +				atomic_read(&txo->q.used) < txo->q.len / 2) { +				netif_wake_subqueue(adapter->netdev, i); +			} + +			adapter->drv_stats.be_tx_events++; +			txo->stats.be_tx_compl += tx_compl; +		}  	}  	mcc_compl = be_process_mcc(adapter, &status); -	napi_complete(napi); -  	if (mcc_compl) {  		struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;  		be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl);  	} -	if (tx_compl) { -		be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl); - -		atomic_sub(num_wrbs, &txq->used); - -		/* As Tx wrbs have been freed up, wake up netdev queue if -		 * it was stopped due to lack of tx wrbs. -		 */ -		if (netif_queue_stopped(adapter->netdev) && -			atomic_read(&txq->used) < txq->len / 2) { -			netif_wake_queue(adapter->netdev); -		} - -		tx_stats(adapter)->be_tx_events++; -		tx_stats(adapter)->be_tx_compl += tx_compl; -	} +	napi_complete(napi); +	be_eq_notify(adapter, tx_eq->q.id, true, false, 0);  	return 1;  } @@ -2065,6 +2031,7 @@ static void be_worker(struct work_struct *work)  	struct be_adapter *adapter =  		container_of(work, struct be_adapter, work.work);  	struct be_rx_obj *rxo; +	struct be_tx_obj *txo;  	int i;  	if (!adapter->ue_detected && !lancer_chip(adapter)) @@ -2092,7 +2059,9 @@ static void be_worker(struct work_struct *work)  		else  			be_cmd_get_stats(adapter, &adapter->stats_cmd);  	} -	be_tx_rate_update(adapter); + +	for_all_tx_queues(adapter, txo, i) +		be_tx_rate_update(txo);  	for_all_rx_queues(adapter, rxo, i) {  		be_rx_rate_update(rxo); @@ -2290,10 +2259,36 @@ done:  	adapter->isr_registered = false;  } +static void be_rx_queues_clear(struct be_adapter *adapter) +{ +	struct be_queue_info *q; +	struct be_rx_obj *rxo; +	int i; + +	for_all_rx_queues(adapter, rxo, i) { +		q = &rxo->q; +		if (q->created) { +			be_cmd_rxq_destroy(adapter, q); +			/* After the rxq is invalidated, wait for a grace time +			 * of 1ms for all dma to end and the flush compl to +			 * arrive +			 */ +			mdelay(1); +			be_rx_q_clean(adapter, rxo); +		} + +		/* Clear any residual events */ +		q = &rxo->rx_eq.q; +		if (q->created) +			be_eq_clean(adapter, &rxo->rx_eq); +	} +} +  static int be_close(struct net_device *netdev)  {  	struct be_adapter *adapter = netdev_priv(netdev);  	struct be_rx_obj *rxo; +	struct be_tx_obj *txo;  	struct be_eq_obj *tx_eq = &adapter->tx_eq;  	int vec, i; @@ -2311,10 +2306,11 @@ static int be_close(struct net_device *netdev)  	napi_disable(&tx_eq->napi);  	if (lancer_chip(adapter)) { -		be_cq_notify(adapter, adapter->tx_obj.cq.id, false, 0);  		be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);  		for_all_rx_queues(adapter, rxo, i)  			 be_cq_notify(adapter, rxo->cq.id, false, 0); +		for_all_tx_queues(adapter, txo, i) +			 be_cq_notify(adapter, txo->cq.id, false, 0);  	}  	if (msix_enabled(adapter)) { @@ -2333,8 +2329,43 @@ static int be_close(struct net_device *netdev)  	/* Wait for all pending tx completions to arrive so that  	 * all tx skbs are freed.  	 */ -	be_tx_compl_clean(adapter); +	for_all_tx_queues(adapter, txo, i) +		be_tx_compl_clean(adapter, txo); + +	be_rx_queues_clear(adapter); +	return 0; +} + +static int be_rx_queues_setup(struct be_adapter *adapter) +{ +	struct be_rx_obj *rxo; +	int rc, i; +	u8 rsstable[MAX_RSS_QS]; + +	for_all_rx_queues(adapter, rxo, i) { +		rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, +			rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE, +			adapter->if_handle, +			(i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id); +		if (rc) +			return rc; +	} + +	if (be_multi_rxq(adapter)) { +		for_all_rss_queues(adapter, rxo, i) +			rsstable[i] = rxo->rss_id; +		rc = be_cmd_rss_config(adapter, rsstable, +			adapter->num_rx_qs - 1); +		if (rc) +			return rc; +	} + +	/* First time posting */ +	for_all_rx_queues(adapter, rxo, i) { +		be_post_rx_frags(rxo, GFP_KERNEL); +		napi_enable(&rxo->rx_eq.napi); +	}  	return 0;  } @@ -2348,10 +2379,10 @@ static int be_open(struct net_device *netdev)  	u8 mac_speed;  	u16 link_speed; -	for_all_rx_queues(adapter, rxo, i) { -		be_post_rx_frags(rxo, GFP_KERNEL); -		napi_enable(&rxo->rx_eq.napi); -	} +	status = be_rx_queues_setup(adapter); +	if (status) +		goto err; +  	napi_enable(&tx_eq->napi);  	be_irq_register(adapter); @@ -2480,6 +2511,8 @@ static int be_setup(struct be_adapter *adapter)  	int status;  	u8 mac[ETH_ALEN]; +	be_cmd_req_native_mode(adapter); +  	cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |  				BE_IF_FLAGS_BROADCAST |  				BE_IF_FLAGS_MULTICAST; @@ -2539,6 +2572,9 @@ static int be_setup(struct be_adapter *adapter)  	if (status != 0)  		goto tx_qs_destroy; +	/* Allow all priorities by default. A GRP5 evt may modify this */ +	adapter->vlan_prio_bmap = 0xff; +  	status = be_mcc_queues_create(adapter);  	if (status != 0)  		goto rx_qs_destroy; @@ -2584,6 +2620,8 @@ static int be_clear(struct be_adapter *adapter)  	be_cmd_if_destroy(adapter, adapter->if_handle,  0); +	adapter->be3_native = 0; +  	/* tell fw we're done with firing cmds */  	be_cmd_fw_clean(adapter);  	return 0; @@ -2901,7 +2939,6 @@ static struct net_device_ops be_netdev_ops = {  	.ndo_set_mac_address	= be_mac_addr_set,  	.ndo_change_mtu		= be_change_mtu,  	.ndo_validate_addr	= eth_validate_addr, -	.ndo_vlan_rx_register	= be_vlan_register,  	.ndo_vlan_rx_add_vid	= be_vlan_add_vid,  	.ndo_vlan_rx_kill_vid	= be_vlan_rem_vid,  	.ndo_set_vf_mac		= be_set_vf_mac, @@ -2925,12 +2962,9 @@ static void be_netdev_init(struct net_device *netdev)  	netdev->features |= netdev->hw_features |  		NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; -	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | +	netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |  		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; -	if (lancer_chip(adapter)) -		netdev->vlan_features |= NETIF_F_TSO6; -  	netdev->flags |= IFF_MULTICAST;  	/* Default settings for Rx and Tx flow control */ @@ -3185,7 +3219,16 @@ static int be_get_config(struct be_adapter *adapter)  	if (status)  		return status; -	be_cmd_check_native_mode(adapter); +	if ((num_vfs && adapter->sriov_enabled) || +		(adapter->function_mode & 0x400) || +		lancer_chip(adapter) || !be_physfn(adapter)) { +		adapter->num_tx_qs = 1; +		netif_set_real_num_tx_queues(adapter->netdev, +			adapter->num_tx_qs); +	} else { +		adapter->num_tx_qs = MAX_TX_QS; +	} +  	return 0;  } @@ -3288,7 +3331,7 @@ static int __devinit be_probe(struct pci_dev *pdev,  		goto disable_dev;  	pci_set_master(pdev); -	netdev = alloc_etherdev(sizeof(struct be_adapter)); +	netdev = alloc_etherdev_mq(sizeof(struct be_adapter), MAX_TX_QS);  	if (netdev == NULL) {  		status = -ENOMEM;  		goto rel_reg; @@ -3360,6 +3403,12 @@ static int __devinit be_probe(struct pci_dev *pdev,  	if (status)  		goto stats_clean; +	/* The INTR bit may be set in the card when probed by a kdump kernel +	 * after a crash. +	 */ +	if (!lancer_chip(adapter)) +		be_intr_set(adapter, false); +  	be_msix_enable(adapter);  	INIT_DELAYED_WORK(&adapter->work, be_worker); @@ -3396,6 +3445,7 @@ static int __devinit be_probe(struct pci_dev *pdev,  	}  	dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num); +  	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));  	return 0; | 
