diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlge')
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlge/qlge.h | 59 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlge/qlge_dbg.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlge/qlge_main.c | 169 | 
4 files changed, 149 insertions, 88 deletions
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h index 89943377846..ef332708e5f 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h @@ -18,7 +18,7 @@   */  #define DRV_NAME  	"qlge"  #define DRV_STRING 	"QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION	"v1.00.00.32" +#define DRV_VERSION	"1.00.00.34"  #define WQ_ADDR_ALIGN	0x3	/* 4 byte alignment */ @@ -2206,14 +2206,14 @@ extern char qlge_driver_name[];  extern const char qlge_driver_version[];  extern const struct ethtool_ops qlge_ethtool_ops; -extern int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask); -extern void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask); -extern int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data); -extern int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, -			       u32 *value); -extern int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value); -extern int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, -			u16 q_id); +int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask); +void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask); +int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data); +int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, +			u32 *value); +int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value); +int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, +		 u16 q_id);  void ql_queue_fw_error(struct ql_adapter *qdev);  void ql_mpi_work(struct work_struct *work);  void ql_mpi_reset_work(struct work_struct *work); @@ -2233,10 +2233,9 @@ int ql_unpause_mpi_risc(struct ql_adapter *qdev);  int ql_pause_mpi_risc(struct ql_adapter *qdev);  int ql_hard_reset_mpi_risc(struct ql_adapter *qdev);  int ql_soft_reset_mpi_risc(struct ql_adapter *qdev); -int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, -		u32 ram_addr, int word_count); -int ql_core_dump(struct ql_adapter *qdev, -		struct ql_mpi_coredump *mpi_coredump); +int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, u32 ram_addr, +			  int word_count); +int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump);  int ql_mb_about_fw(struct ql_adapter *qdev);  int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol);  int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol); @@ -2249,8 +2248,6 @@ int ql_mb_get_port_cfg(struct ql_adapter *qdev);  int ql_mb_set_port_cfg(struct ql_adapter *qdev);  int ql_wait_fifo_empty(struct ql_adapter *qdev);  void ql_get_dump(struct ql_adapter *qdev, void *buff); -void ql_gen_reg_dump(struct ql_adapter *qdev, -			struct ql_reg_dump *mpi_coredump);  netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev);  void ql_check_lb_frame(struct ql_adapter *, struct sk_buff *);  int ql_own_firmware(struct ql_adapter *qdev); @@ -2264,9 +2261,9 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget);  /* #define QL_OB_DUMP */  #ifdef QL_REG_DUMP -extern void ql_dump_xgmac_control_regs(struct ql_adapter *qdev); -extern void ql_dump_routing_entries(struct ql_adapter *qdev); -extern void ql_dump_regs(struct ql_adapter *qdev); +void ql_dump_xgmac_control_regs(struct ql_adapter *qdev); +void ql_dump_routing_entries(struct ql_adapter *qdev); +void ql_dump_regs(struct ql_adapter *qdev);  #define QL_DUMP_REGS(qdev) ql_dump_regs(qdev)  #define QL_DUMP_ROUTE(qdev) ql_dump_routing_entries(qdev)  #define QL_DUMP_XGMAC_CONTROL_REGS(qdev) ql_dump_xgmac_control_regs(qdev) @@ -2277,26 +2274,26 @@ extern void ql_dump_regs(struct ql_adapter *qdev);  #endif  #ifdef QL_STAT_DUMP -extern void ql_dump_stat(struct ql_adapter *qdev); +void ql_dump_stat(struct ql_adapter *qdev);  #define QL_DUMP_STAT(qdev) ql_dump_stat(qdev)  #else  #define QL_DUMP_STAT(qdev)  #endif  #ifdef QL_DEV_DUMP -extern void ql_dump_qdev(struct ql_adapter *qdev); +void ql_dump_qdev(struct ql_adapter *qdev);  #define QL_DUMP_QDEV(qdev) ql_dump_qdev(qdev)  #else  #define QL_DUMP_QDEV(qdev)  #endif  #ifdef QL_CB_DUMP -extern void ql_dump_wqicb(struct wqicb *wqicb); -extern void ql_dump_tx_ring(struct tx_ring *tx_ring); -extern void ql_dump_ricb(struct ricb *ricb); -extern void ql_dump_cqicb(struct cqicb *cqicb); -extern void ql_dump_rx_ring(struct rx_ring *rx_ring); -extern void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id); +void ql_dump_wqicb(struct wqicb *wqicb); +void ql_dump_tx_ring(struct tx_ring *tx_ring); +void ql_dump_ricb(struct ricb *ricb); +void ql_dump_cqicb(struct cqicb *cqicb); +void ql_dump_rx_ring(struct rx_ring *rx_ring); +void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id);  #define QL_DUMP_RICB(ricb) ql_dump_ricb(ricb)  #define QL_DUMP_WQICB(wqicb) ql_dump_wqicb(wqicb)  #define QL_DUMP_TX_RING(tx_ring) ql_dump_tx_ring(tx_ring) @@ -2314,9 +2311,9 @@ extern void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id);  #endif  #ifdef QL_OB_DUMP -extern void ql_dump_tx_desc(struct tx_buf_desc *tbd); -extern void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb); -extern void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp); +void ql_dump_tx_desc(struct tx_buf_desc *tbd); +void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb); +void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp);  #define QL_DUMP_OB_MAC_IOCB(ob_mac_iocb) ql_dump_ob_mac_iocb(ob_mac_iocb)  #define QL_DUMP_OB_MAC_RSP(ob_mac_rsp) ql_dump_ob_mac_rsp(ob_mac_rsp)  #else @@ -2325,14 +2322,14 @@ extern void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp);  #endif  #ifdef QL_IB_DUMP -extern void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp); +void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp);  #define QL_DUMP_IB_MAC_RSP(ib_mac_rsp) ql_dump_ib_mac_rsp(ib_mac_rsp)  #else  #define QL_DUMP_IB_MAC_RSP(ib_mac_rsp)  #endif  #ifdef	QL_ALL_DUMP -extern void ql_dump_all(struct ql_adapter *qdev); +void ql_dump_all(struct ql_adapter *qdev);  #define QL_DUMP_ALL(qdev) ql_dump_all(qdev)  #else  #define QL_DUMP_ALL(qdev) diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c index 6bc5db70392..829be21f97b 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c @@ -1242,8 +1242,8 @@ static void ql_get_core_dump(struct ql_adapter *qdev)  	ql_queue_fw_error(qdev);  } -void ql_gen_reg_dump(struct ql_adapter *qdev, -			struct ql_reg_dump *mpi_coredump) +static void ql_gen_reg_dump(struct ql_adapter *qdev, +			    struct ql_reg_dump *mpi_coredump)  {  	int i, status; diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c index 0780e039b27..c3c514e332b 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c @@ -1,5 +1,4 @@  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/types.h>  #include <linux/module.h>  #include <linux/list.h> @@ -181,6 +180,7 @@ static const char ql_gstrings_test[][ETH_GSTRING_LEN] = {  };  #define QLGE_TEST_LEN (sizeof(ql_gstrings_test) / ETH_GSTRING_LEN)  #define QLGE_STATS_LEN ARRAY_SIZE(ql_gstrings_stats) +#define QLGE_RCV_MAC_ERR_STATS	7  static int ql_update_ring_coalescing(struct ql_adapter *qdev)  { @@ -280,6 +280,9 @@ static void ql_update_stats(struct ql_adapter *qdev)  		iter++;  	} +	/* Update receive mac error statistics */ +	iter += QLGE_RCV_MAC_ERR_STATS; +  	/*  	 * Get Per-priority TX pause frame counter statistics.  	 */ diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 2553cf4503b..b40050e03a5 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -6,7 +6,6 @@   *                      Ron Mercer <ron.mercer@qlogic.com>   */  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/bitops.h>  #include <linux/types.h>  #include <linux/module.h> @@ -96,8 +95,10 @@ static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = {  MODULE_DEVICE_TABLE(pci, qlge_pci_tbl); -static int ql_wol(struct ql_adapter *qdev); -static void qlge_set_multicast_list(struct net_device *ndev); +static int ql_wol(struct ql_adapter *); +static void qlge_set_multicast_list(struct net_device *); +static int ql_adapter_down(struct ql_adapter *); +static int ql_adapter_up(struct ql_adapter *);  /* This hardware semaphore causes exclusive access to   * resources shared between the NIC driver, MPI firmware, @@ -1464,6 +1465,29 @@ static void ql_categorize_rx_err(struct ql_adapter *qdev, u8 rx_err,  	}  } +/** + * ql_update_mac_hdr_len - helper routine to update the mac header length + * based on vlan tags if present + */ +static void ql_update_mac_hdr_len(struct ql_adapter *qdev, +				  struct ib_mac_iocb_rsp *ib_mac_rsp, +				  void *page, size_t *len) +{ +	u16 *tags; + +	if (qdev->ndev->features & NETIF_F_HW_VLAN_CTAG_RX) +		return; +	if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) { +		tags = (u16 *)page; +		/* Look for stacked vlan tags in ethertype field */ +		if (tags[6] == ETH_P_8021Q && +		    tags[8] == ETH_P_8021Q) +			*len += 2 * VLAN_HLEN; +		else +			*len += VLAN_HLEN; +	} +} +  /* Process an inbound completion from an rx ring. */  static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,  					struct rx_ring *rx_ring, @@ -1523,6 +1547,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,  	void *addr;  	struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);  	struct napi_struct *napi = &rx_ring->napi; +	size_t hlen = ETH_HLEN;  	skb = netdev_alloc_skb(ndev, length);  	if (!skb) { @@ -1540,25 +1565,28 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,  		goto err_out;  	} +	/* Update the MAC header length*/ +	ql_update_mac_hdr_len(qdev, ib_mac_rsp, addr, &hlen); +  	/* The max framesize filter on this chip is set higher than  	 * MTU since FCoE uses 2k frames.  	 */ -	if (skb->len > ndev->mtu + ETH_HLEN) { +	if (skb->len > ndev->mtu + hlen) {  		netif_err(qdev, drv, qdev->ndev,  			  "Segment too small, dropping.\n");  		rx_ring->rx_dropped++;  		goto err_out;  	} -	memcpy(skb_put(skb, ETH_HLEN), addr, ETH_HLEN); +	memcpy(skb_put(skb, hlen), addr, hlen);  	netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,  		     "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n",  		     length);  	skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, -				lbq_desc->p.pg_chunk.offset+ETH_HLEN, -				length-ETH_HLEN); -	skb->len += length-ETH_HLEN; -	skb->data_len += length-ETH_HLEN; -	skb->truesize += length-ETH_HLEN; +				lbq_desc->p.pg_chunk.offset + hlen, +				length - hlen); +	skb->len += length - hlen; +	skb->data_len += length - hlen; +	skb->truesize += length - hlen;  	rx_ring->rx_packets++;  	rx_ring->rx_bytes += skb->len; @@ -1576,7 +1604,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,  				(ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) {  			/* Unfragmented ipv4 UDP frame. */  			struct iphdr *iph = -				(struct iphdr *) ((u8 *)addr + ETH_HLEN); +				(struct iphdr *)((u8 *)addr + hlen);  			if (!(iph->frag_off &  				htons(IP_MF|IP_OFFSET))) {  				skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -1726,7 +1754,8 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,  	struct bq_desc *sbq_desc;  	struct sk_buff *skb = NULL;  	u32 length = le32_to_cpu(ib_mac_rsp->data_len); -       u32 hdr_len = le32_to_cpu(ib_mac_rsp->hdr_len); +	u32 hdr_len = le32_to_cpu(ib_mac_rsp->hdr_len); +	size_t hlen = ETH_HLEN;  	/*  	 * Handle the header buffer if present. @@ -1853,9 +1882,10 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,  			skb->data_len += length;  			skb->truesize += length;  			length -= length; -			__pskb_pull_tail(skb, -				(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? -				VLAN_ETH_HLEN : ETH_HLEN); +			ql_update_mac_hdr_len(qdev, ib_mac_rsp, +					      lbq_desc->p.pg_chunk.va, +					      &hlen); +			__pskb_pull_tail(skb, hlen);  		}  	} else {  		/* @@ -1910,8 +1940,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,  			length -= size;  			i++;  		} -		__pskb_pull_tail(skb, (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? -				VLAN_ETH_HLEN : ETH_HLEN); +		ql_update_mac_hdr_len(qdev, ib_mac_rsp, lbq_desc->p.pg_chunk.va, +				      &hlen); +		__pskb_pull_tail(skb, hlen);  	}  	return skb;  } @@ -2003,7 +2034,7 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev,  	rx_ring->rx_packets++;  	rx_ring->rx_bytes += skb->len;  	skb_record_rx_queue(skb, rx_ring->cq_id); -	if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && (vlan_id != 0)) +	if (vlan_id != 0xffff)  		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_id);  	if (skb->ip_summed == CHECKSUM_UNNECESSARY)  		napi_gro_receive(&rx_ring->napi, skb); @@ -2017,7 +2048,8 @@ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev,  					struct ib_mac_iocb_rsp *ib_mac_rsp)  {  	u32 length = le32_to_cpu(ib_mac_rsp->data_len); -	u16 vlan_id = (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? +	u16 vlan_id = ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && +			(qdev->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)) ?  			((le16_to_cpu(ib_mac_rsp->vlan_id) &  			IB_MAC_IOCB_RSP_VLAN_MASK)) : 0xffff; @@ -2310,17 +2342,44 @@ static void qlge_vlan_mode(struct net_device *ndev, netdev_features_t features)  	}  } +/** + * qlge_update_hw_vlan_features - helper routine to reinitialize the adapter + * based on the features to enable/disable hardware vlan accel + */ +static int qlge_update_hw_vlan_features(struct net_device *ndev, +					netdev_features_t features) +{ +	struct ql_adapter *qdev = netdev_priv(ndev); +	int status = 0; + +	status = ql_adapter_down(qdev); +	if (status) { +		netif_err(qdev, link, qdev->ndev, +			  "Failed to bring down the adapter\n"); +		return status; +	} + +	/* update the features with resent change */ +	ndev->features = features; + +	status = ql_adapter_up(qdev); +	if (status) { +		netif_err(qdev, link, qdev->ndev, +			  "Failed to bring up the adapter\n"); +		return status; +	} +	return status; +} +  static netdev_features_t qlge_fix_features(struct net_device *ndev,  	netdev_features_t features)  { -	/* -	 * Since there is no support for separate rx/tx vlan accel -	 * enable/disable make sure tx flag is always in same state as rx. -	 */ -	if (features & NETIF_F_HW_VLAN_CTAG_RX) -		features |= NETIF_F_HW_VLAN_CTAG_TX; -	else -		features &= ~NETIF_F_HW_VLAN_CTAG_TX; +	int err; + +	/* Update the behavior of vlan accel in the adapter */ +	err = qlge_update_hw_vlan_features(ndev, features); +	if (err) +		return err;  	return features;  } @@ -2497,11 +2556,10 @@ static int ql_tso(struct sk_buff *skb, struct ob_mac_tso_iocb_req *mac_iocb_ptr)  	if (skb_is_gso(skb)) {  		int err; -		if (skb_header_cloned(skb)) { -			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); -			if (err) -				return err; -		} + +		err = skb_cow_head(skb, 0); +		if (err < 0) +			return err;  		mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB;  		mac_iocb_ptr->flags3 |= OB_MAC_TSO_IOCB_IC; @@ -3272,24 +3330,16 @@ static void ql_enable_msix(struct ql_adapter *qdev)  		for (i = 0; i < qdev->intr_count; i++)  			qdev->msi_x_entry[i].entry = i; -		/* Loop to get our vectors.  We start with -		 * what we want and settle for what we get. -		 */ -		do { -			err = pci_enable_msix(qdev->pdev, -				qdev->msi_x_entry, qdev->intr_count); -			if (err > 0) -				qdev->intr_count = err; -		} while (err > 0); - +		err = pci_enable_msix_range(qdev->pdev, qdev->msi_x_entry, +					    1, qdev->intr_count);  		if (err < 0) {  			kfree(qdev->msi_x_entry);  			qdev->msi_x_entry = NULL;  			netif_warn(qdev, ifup, qdev->ndev,  				   "MSI-X Enable failed, trying MSI.\n"); -			qdev->intr_count = 1;  			qlge_irq_type = MSI_IRQ; -		} else if (err == 0) { +		} else { +			qdev->intr_count = err;  			set_bit(QL_MSIX_ENABLED, &qdev->flags);  			netif_info(qdev, ifup, qdev->ndev,  				   "MSI-X Enabled, got %d vectors.\n", @@ -3545,7 +3595,7 @@ static int ql_request_irq(struct ql_adapter *qdev)  	}  	return status;  err_irq: -	netif_err(qdev, ifup, qdev->ndev, "Failed to get the interrupts!!!/n"); +	netif_err(qdev, ifup, qdev->ndev, "Failed to get the interrupts!!!\n");  	ql_free_irq(qdev);  	return status;  } @@ -3704,8 +3754,12 @@ static int ql_adapter_initialize(struct ql_adapter *qdev)  	ql_write32(qdev, SYS, mask | value);  	/* Set the default queue, and VLAN behavior. */ -	value = NIC_RCV_CFG_DFQ | NIC_RCV_CFG_RV; -	mask = NIC_RCV_CFG_DFQ_MASK | (NIC_RCV_CFG_RV << 16); +	value = NIC_RCV_CFG_DFQ; +	mask = NIC_RCV_CFG_DFQ_MASK; +	if (qdev->ndev->features & NETIF_F_HW_VLAN_CTAG_RX) { +		value |= NIC_RCV_CFG_RV; +		mask |= (NIC_RCV_CFG_RV << 16); +	}  	ql_write32(qdev, NIC_RCV_CFG, (mask | value));  	/* Set the MPI interrupt to enabled. */ @@ -4505,7 +4559,6 @@ static void ql_release_all(struct pci_dev *pdev)  		iounmap(qdev->doorbell_area);  	vfree(qdev->mpi_coredump);  	pci_release_regions(pdev); -	pci_set_drvdata(pdev, NULL);  }  static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev, @@ -4692,12 +4745,20 @@ static int qlge_probe(struct pci_dev *pdev,  	qdev = netdev_priv(ndev);  	SET_NETDEV_DEV(ndev, &pdev->dev); -	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | -		NETIF_F_TSO | NETIF_F_TSO_ECN | -		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_RXCSUM; -	ndev->features = ndev->hw_features | -		NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; +	ndev->hw_features = NETIF_F_SG | +			    NETIF_F_IP_CSUM | +			    NETIF_F_TSO | +			    NETIF_F_TSO_ECN | +			    NETIF_F_HW_VLAN_CTAG_TX | +			    NETIF_F_HW_VLAN_CTAG_RX | +			    NETIF_F_HW_VLAN_CTAG_FILTER | +			    NETIF_F_RXCSUM; +	ndev->features = ndev->hw_features;  	ndev->vlan_features = ndev->hw_features; +	/* vlan gets same features (except vlan filter) */ +	ndev->vlan_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | +				 NETIF_F_HW_VLAN_CTAG_TX | +				 NETIF_F_HW_VLAN_CTAG_RX);  	if (test_bit(QL_DMA64, &qdev->flags))  		ndev->features |= NETIF_F_HIGHDMA; @@ -4709,7 +4770,7 @@ static int qlge_probe(struct pci_dev *pdev,  	ndev->irq = pdev->irq;  	ndev->netdev_ops = &qlge_netdev_ops; -	SET_ETHTOOL_OPS(ndev, &qlge_ethtool_ops); +	ndev->ethtool_ops = &qlge_ethtool_ops;  	ndev->watchdog_timeo = 10 * HZ;  	err = register_netdev(ndev);  | 
