diff options
Diffstat (limited to 'drivers/net/ethernet')
23 files changed, 356 insertions, 199 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index af20c6ee2cd..e8e97a7d1d0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -662,14 +662,16 @@ void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,  				 struct bnx2x_fastpath *fp,  				 struct bnx2x_eth_q_stats *qstats)  { -	/* Do nothing if no IP/L4 csum validation was done */ - +	/* Do nothing if no L4 csum validation was done. +	 * We do not check whether IP csum was validated. For IPv4 we assume +	 * that if the card got as far as validating the L4 csum, it also +	 * validated the IP csum. IPv6 has no IP csum. +	 */  	if (cqe->fast_path_cqe.status_flags & -	    (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | -	     ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) +	    ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)  		return; -	/* If both IP/L4 validation were done, check if an error was found. */ +	/* If L4 validation was done, check if an error was found. */  	if (cqe->fast_path_cqe.type_error_flags &  	    (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 21b553229ea..dfd86a55f1d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -710,17 +710,15 @@ static inline u16 bnx2x_tx_avail(struct bnx2x *bp,  	prod = txdata->tx_bd_prod;  	cons = txdata->tx_bd_cons; -	/* NUM_TX_RINGS = number of "next-page" entries -	   It will be used as a threshold */ -	used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS; +	used = SUB_S16(prod, cons);  #ifdef BNX2X_STOP_ON_ERROR  	WARN_ON(used < 0); -	WARN_ON(used > bp->tx_ring_size); -	WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL); +	WARN_ON(used > txdata->tx_ring_size); +	WARN_ON((txdata->tx_ring_size - used) > MAX_TX_AVAIL);  #endif -	return (s16)(bp->tx_ring_size) - used; +	return (s16)(txdata->tx_ring_size) - used;  }  static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata) @@ -1088,6 +1086,7 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,  	txdata->txq_index = txq_index;  	txdata->tx_cons_sb = tx_cons_sb;  	txdata->parent_fp = fp; +	txdata->tx_ring_size = IS_FCOE_FP(fp) ? MAX_TX_AVAIL : bp->tx_ring_size;  	DP(NETIF_MSG_IFUP, "created tx data cid %d, txq %d\n",  	   txdata->cid, txdata->txq_index); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h index 3e4cff9b1eb..b926f58e983 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h @@ -401,11 +401,11 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x70000, 8, RI_ALL_ONLINE },  	{ 0x70020, 8184, RI_ALL_OFFLINE },  	{ 0x78000, 8192, RI_E3E3B0_OFFLINE }, -	{ 0x85000, 3, RI_ALL_ONLINE }, -	{ 0x8501c, 7, RI_ALL_ONLINE }, -	{ 0x85048, 1, RI_ALL_ONLINE }, -	{ 0x85200, 32, RI_ALL_ONLINE }, -	{ 0xb0000, 16384, RI_E1H_ONLINE }, +	{ 0x85000, 3, RI_ALL_OFFLINE }, +	{ 0x8501c, 7, RI_ALL_OFFLINE }, +	{ 0x85048, 1, RI_ALL_OFFLINE }, +	{ 0x85200, 32, RI_ALL_OFFLINE }, +	{ 0xb0000, 16384, RI_E1H_OFFLINE },  	{ 0xc1000, 7, RI_ALL_ONLINE },  	{ 0xc103c, 2, RI_E2E3E3B0_ONLINE },  	{ 0xc1800, 2, RI_ALL_ONLINE }, @@ -581,17 +581,12 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x140188, 3, RI_E1E1HE2E3_ONLINE },  	{ 0x140194, 13, RI_ALL_ONLINE },  	{ 0x140200, 6, RI_E1E1HE2E3_ONLINE }, -	{ 0x140220, 4, RI_E2E3_ONLINE }, -	{ 0x140240, 4, RI_E2E3_ONLINE },  	{ 0x140260, 4, RI_E2E3_ONLINE },  	{ 0x140280, 4, RI_E2E3_ONLINE }, -	{ 0x1402a0, 4, RI_E2E3_ONLINE }, -	{ 0x1402c0, 4, RI_E2E3_ONLINE },  	{ 0x1402e0, 2, RI_E2E3_ONLINE },  	{ 0x1402e8, 2, RI_E2E3E3B0_ONLINE },  	{ 0x1402f0, 9, RI_E2E3_ONLINE },  	{ 0x140314, 44, RI_E3B0_ONLINE }, -	{ 0x1403d0, 70, RI_E3B0_ONLINE },  	{ 0x144000, 4, RI_E1E1H_ONLINE },  	{ 0x148000, 4, RI_E1E1H_ONLINE },  	{ 0x14c000, 4, RI_E1E1H_ONLINE }, @@ -704,7 +699,6 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x180398, 1, RI_E2E3E3B0_ONLINE },  	{ 0x1803a0, 5, RI_E2E3E3B0_ONLINE },  	{ 0x1803b4, 2, RI_E3E3B0_ONLINE }, -	{ 0x180400, 1, RI_ALL_ONLINE },  	{ 0x180404, 255, RI_E1E1H_OFFLINE },  	{ 0x181000, 4, RI_ALL_ONLINE },  	{ 0x181010, 1020, RI_ALL_OFFLINE }, @@ -800,9 +794,9 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x1b905c, 1, RI_E3E3B0_ONLINE },  	{ 0x1b9064, 1, RI_E3B0_ONLINE },  	{ 0x1b9080, 10, RI_E3B0_ONLINE }, -	{ 0x1b9400, 14, RI_E2E3E3B0_ONLINE }, -	{ 0x1b943c, 19, RI_E2E3E3B0_ONLINE }, -	{ 0x1b9490, 10, RI_E2E3E3B0_ONLINE }, +	{ 0x1b9400, 14, RI_E2E3E3B0_OFFLINE }, +	{ 0x1b943c, 19, RI_E2E3E3B0_OFFLINE }, +	{ 0x1b9490, 10, RI_E2E3E3B0_OFFLINE },  	{ 0x1c0000, 2, RI_ALL_ONLINE },  	{ 0x200000, 65, RI_ALL_ONLINE },  	{ 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE }, @@ -814,7 +808,6 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x200398, 1, RI_E2E3E3B0_ONLINE },  	{ 0x2003a0, 1, RI_E2E3E3B0_ONLINE },  	{ 0x2003a8, 2, RI_E2E3E3B0_ONLINE }, -	{ 0x200400, 1, RI_ALL_ONLINE },  	{ 0x200404, 255, RI_E1E1H_OFFLINE },  	{ 0x202000, 4, RI_ALL_ONLINE },  	{ 0x202010, 2044, RI_ALL_OFFLINE }, @@ -921,7 +914,6 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x280398, 1, RI_E2E3E3B0_ONLINE },  	{ 0x2803a0, 1, RI_E2E3E3B0_ONLINE },  	{ 0x2803a8, 2, RI_E2E3E3B0_ONLINE }, -	{ 0x280400, 1, RI_ALL_ONLINE },  	{ 0x280404, 255, RI_E1E1H_OFFLINE },  	{ 0x282000, 4, RI_ALL_ONLINE },  	{ 0x282010, 2044, RI_ALL_OFFLINE }, @@ -1031,7 +1023,6 @@ static const struct reg_addr reg_addrs[] = {  	{ 0x300398, 1, RI_E2E3E3B0_ONLINE },  	{ 0x3003a0, 1, RI_E2E3E3B0_ONLINE },  	{ 0x3003a8, 2, RI_E2E3E3B0_ONLINE }, -	{ 0x300400, 1, RI_ALL_ONLINE },  	{ 0x300404, 255, RI_E1E1H_OFFLINE },  	{ 0x302000, 4, RI_ALL_ONLINE },  	{ 0x302010, 2044, RI_ALL_OFFLINE }, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c37a68d6809..ebf40cd7aa1 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -775,7 +775,7 @@ static void bnx2x_get_regs(struct net_device *dev,  	struct bnx2x *bp = netdev_priv(dev);  	struct dump_hdr dump_hdr = {0}; -	regs->version = 0; +	regs->version = 1;  	memset(p, 0, regs->len);  	if (!netif_running(bp->dev)) @@ -1587,6 +1587,12 @@ static int bnx2x_set_pauseparam(struct net_device *dev,  			bp->link_params.req_flow_ctrl[cfg_idx] =  				BNX2X_FLOW_CTRL_AUTO;  		} +		bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_NONE; +		if (epause->rx_pause) +			bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_RX; + +		if (epause->tx_pause) +			bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_TX;  	}  	DP(BNX2X_MSG_ETHTOOL, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index f4beb46c470..b046beb435b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -2667,9 +2667,11 @@ int bnx2x_update_pfc(struct link_params *params,  		return bnx2x_status;  	DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n"); -	if (CHIP_IS_E3(bp)) -		bnx2x_update_pfc_xmac(params, vars, 0); -	else { + +	if (CHIP_IS_E3(bp)) { +		if (vars->mac_type == MAC_TYPE_XMAC) +			bnx2x_update_pfc_xmac(params, vars, 0); +	} else {  		val = REG_RD(bp, MISC_REG_RESET_REG_2);  		if ((val &  		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) @@ -5432,7 +5434,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,  		switch (speed_mask) {  		case GP_STATUS_10M:  			vars->line_speed = SPEED_10; -			if (vars->duplex == DUPLEX_FULL) +			if (is_duplex == DUPLEX_FULL)  				vars->link_status |= LINK_10TFD;  			else  				vars->link_status |= LINK_10THD; @@ -5440,7 +5442,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,  		case GP_STATUS_100M:  			vars->line_speed = SPEED_100; -			if (vars->duplex == DUPLEX_FULL) +			if (is_duplex == DUPLEX_FULL)  				vars->link_status |= LINK_100TXFD;  			else  				vars->link_status |= LINK_100TXHD; @@ -5449,7 +5451,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,  		case GP_STATUS_1G:  		case GP_STATUS_1G_KX:  			vars->line_speed = SPEED_1000; -			if (vars->duplex == DUPLEX_FULL) +			if (is_duplex == DUPLEX_FULL)  				vars->link_status |= LINK_1000TFD;  			else  				vars->link_status |= LINK_1000THD; @@ -5457,7 +5459,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,  		case GP_STATUS_2_5G:  			vars->line_speed = SPEED_2500; -			if (vars->duplex == DUPLEX_FULL) +			if (is_duplex == DUPLEX_FULL)  				vars->link_status |= LINK_2500TFD;  			else  				vars->link_status |= LINK_2500THD; @@ -5531,6 +5533,7 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy,  	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {  		if (SINGLE_MEDIA_DIRECT(params)) { +			vars->duplex = duplex;  			bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);  			if (phy->req_line_speed == SPEED_AUTO_NEG)  				bnx2x_xgxs_an_resolve(phy, params, vars, @@ -5625,6 +5628,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,  					LINK_STATUS_PARALLEL_DETECTION_USED;  			}  			bnx2x_ext_phy_resolve_fc(phy, params, vars); +			vars->duplex = duplex;  		}  	} diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 21054987257..0875ecfe337 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -7561,8 +7561,14 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,  	}  	rc = bnx2x_config_vlan_mac(bp, &ramrod_param); -	if (rc < 0) + +	if (rc == -EEXIST) { +		DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc); +		/* do not treat adding same MAC as error */ +		rc = 0; +	} else if (rc < 0)  		BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del")); +  	return rc;  } @@ -9825,12 +9831,13 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)  	}  #ifdef CONFIG_PCI_MSI -	/* -	 * It's expected that number of CAM entries for this functions is equal -	 * to the number evaluated based on the MSI-X table size. We want a -	 * harsh warning if these values are different! +	/* Due to new PF resource allocation by MFW T7.4 and above, it's +	 * optional that number of CAM entries will not be equal to the value +	 * advertised in PCI. +	 * Driver should use the minimal value of both as the actual status +	 * block count  	 */ -	WARN_ON(bp->igu_sb_cnt != igu_sb_cnt); +	bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt);  #endif  	if (igu_sb_cnt == 0) @@ -10294,13 +10301,11 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)  				dev_info.port_hw_config[port].  				 fcoe_wwn_node_name_lower);  	} else if (!IS_MF_SD(bp)) { -		u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg); -  		/*  		 * Read the WWN info only if the FCoE feature is enabled for  		 * this function.  		 */ -		if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) +		if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp))  			bnx2x_get_ext_wwn_info(bp, func);  	} else if (IS_MF_FCOE_SD(bp)) @@ -11073,7 +11078,14 @@ static int bnx2x_set_uc_list(struct bnx2x *bp)  	netdev_for_each_uc_addr(ha, dev) {  		rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true,  				       BNX2X_UC_LIST_MAC, &ramrod_flags); -		if (rc < 0) { +		if (rc == -EEXIST) { +			DP(BNX2X_MSG_SP, +			   "Failed to schedule ADD operations: %d\n", rc); +			/* do not treat adding same MAC as error */ +			rc = 0; + +		} else if (rc < 0) { +  			BNX2X_ERR("Failed to schedule ADD operations: %d\n",  				  rc);  			return rc; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 332db64dd5b..a1d0446b39b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -101,6 +101,11 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)  	if (CHIP_REV_IS_SLOW(bp))  		return; +	/* Update MCP's statistics if possible */ +	if (bp->func_stx) +		memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, +		       sizeof(bp->func_stats)); +  	/* loader */  	if (bp->executer_idx) {  		int loader_idx = PMF_DMAE_C(bp); @@ -128,8 +133,6 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)  	} else if (bp->func_stx) {  		*stats_comp = 0; -		memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats, -		       sizeof(bp->func_stats));  		bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));  	}  } @@ -1151,9 +1154,11 @@ static void bnx2x_stats_update(struct bnx2x *bp)  	if (bp->port.pmf)  		bnx2x_hw_stats_update(bp); -	if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) { -		BNX2X_ERR("storm stats were not updated for 3 times\n"); -		bnx2x_panic(); +	if (bnx2x_storm_stats_update(bp)) { +		if (bp->stats_pending++ == 3) { +			BNX2X_ERR("storm stats were not updated for 3 times\n"); +			bnx2x_panic(); +		}  		return;  	} diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index 77884191a8c..4e980a7886f 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -1086,7 +1086,7 @@ static int __init at91ether_probe(struct platform_device *pdev)  	/* Clock */  	lp->ether_clk = clk_get(&pdev->dev, "ether_clk");  	if (IS_ERR(lp->ether_clk)) { -		res = -ENODEV; +		res = PTR_ERR(lp->ether_clk);  		goto err_ioumap;  	}  	clk_enable(lp->ether_clk); diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 8971921cc1c..ab6762caa95 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -1773,6 +1773,7 @@ static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,  }  int gfar_phc_index = -1; +EXPORT_SYMBOL(gfar_phc_index);  static int gfar_get_ts_info(struct net_device *dev,  			    struct ethtool_ts_info *info) diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index c08e5d40fec..0daa66b8eca 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -515,7 +515,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)  		err = PTR_ERR(etsects->clock);  		goto no_clock;  	} -	gfar_phc_clock = ptp_clock_index(etsects->clock); +	gfar_phc_index = ptp_clock_index(etsects->clock);  	dev_set_drvdata(&dev->dev, etsects); @@ -539,7 +539,7 @@ static int gianfar_ptp_remove(struct platform_device *dev)  	gfar_write(&etsects->regs->tmr_temask, 0);  	gfar_write(&etsects->regs->tmr_ctrl,   0); -	gfar_phc_clock = -1; +	gfar_phc_index = -1;  	ptp_clock_unregister(etsects->clock);  	iounmap(etsects->regs);  	release_resource(etsects->rsrc); diff --git a/drivers/net/ethernet/i825xx/znet.c b/drivers/net/ethernet/i825xx/znet.c index bd1f1ef91e1..ba4e0cea350 100644 --- a/drivers/net/ethernet/i825xx/znet.c +++ b/drivers/net/ethernet/i825xx/znet.c @@ -139,8 +139,11 @@ struct znet_private {  /* Only one can be built-in;-> */  static struct net_device *znet_dev; +#define NETIDBLK_MAGIC		"NETIDBLK" +#define NETIDBLK_MAGIC_SIZE	8 +  struct netidblk { -	char magic[8];		/* The magic number (string) "NETIDBLK" */ +	char magic[NETIDBLK_MAGIC_SIZE];	/* The magic number (string) "NETIDBLK" */  	unsigned char netid[8]; /* The physical station address */  	char nettype, globalopt;  	char vendor[8];		/* The machine vendor and product name. */ @@ -373,14 +376,16 @@ static int __init znet_probe (void)  	struct znet_private *znet;  	struct net_device *dev;  	char *p; +	char *plast = phys_to_virt(0x100000 - NETIDBLK_MAGIC_SIZE);  	int err = -ENOMEM;  	/* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */ -	for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++) -		if (*p == 'N'  &&  strncmp(p, "NETIDBLK", 8) == 0) +	for(p = (char *)phys_to_virt(0xf0000); p <= plast; p++) +		if (*p == 'N' && +		    strncmp(p, NETIDBLK_MAGIC, NETIDBLK_MAGIC_SIZE) == 0)  			break; -	if (p >= (char *)phys_to_virt(0x100000)) { +	if (p > plast) {  		if (znet_debug > 1)  			printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");  		return -ENODEV; diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 9010cea68bc..b68d28a130e 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)  	}  	if (adapter->rx_queue.queue_addr != NULL) { -		if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { -			dma_unmap_single(dev, -					adapter->rx_queue.queue_dma, -					adapter->rx_queue.queue_len, -					DMA_BIDIRECTIONAL); -			adapter->rx_queue.queue_dma = DMA_ERROR_CODE; -		} -		kfree(adapter->rx_queue.queue_addr); +		dma_free_coherent(dev, adapter->rx_queue.queue_len, +				  adapter->rx_queue.queue_addr, +				  adapter->rx_queue.queue_dma);  		adapter->rx_queue.queue_addr = NULL;  	} @@ -556,10 +551,13 @@ static int ibmveth_open(struct net_device *netdev)  		goto err_out;  	} +	dev = &adapter->vdev->dev; +  	adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) *  						rxq_entries; -	adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, -						GFP_KERNEL); +	adapter->rx_queue.queue_addr = +	    dma_alloc_coherent(dev, adapter->rx_queue.queue_len, +			       &adapter->rx_queue.queue_dma, GFP_KERNEL);  	if (!adapter->rx_queue.queue_addr) {  		netdev_err(netdev, "unable to allocate rx queue pages\n"); @@ -567,19 +565,13 @@ static int ibmveth_open(struct net_device *netdev)  		goto err_out;  	} -	dev = &adapter->vdev->dev; -  	adapter->buffer_list_dma = dma_map_single(dev,  			adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL);  	adapter->filter_list_dma = dma_map_single(dev,  			adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); -	adapter->rx_queue.queue_dma = dma_map_single(dev, -			adapter->rx_queue.queue_addr, -			adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL);  	if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || -	    (dma_mapping_error(dev, adapter->filter_list_dma)) || -	    (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { +	    (dma_mapping_error(dev, adapter->filter_list_dma))) {  		netdev_err(netdev, "unable to map filter or buffer list "  			   "pages\n");  		rc = -ENOMEM; diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 3bfbb8df898..bde337ee1a3 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -3149,6 +3149,17 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,  		return NETDEV_TX_OK;  	} +	/* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, +	 * packets may get corrupted during padding by HW. +	 * To WA this issue, pad all small packets manually. +	 */ +	if (skb->len < ETH_ZLEN) { +		if (skb_pad(skb, ETH_ZLEN - skb->len)) +			return NETDEV_TX_OK; +		skb->len = ETH_ZLEN; +		skb_set_tail_pointer(skb, ETH_ZLEN); +	} +  	mss = skb_shinfo(skb)->gso_size;  	/* The controller does a simple calculation to  	 * make sure there is enough room in the FIFO before diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index daf41792366..31d02649be4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -227,9 +227,10 @@ int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev)  			MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);  } -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) +int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)  { -	int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); +	u32 i = (obj & (table->num_obj - 1)) / +			(MLX4_TABLE_CHUNK_SIZE / table->obj_size);  	int ret = 0;  	mutex_lock(&table->mutex); @@ -262,16 +263,18 @@ out:  	return ret;  } -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) +void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)  { -	int i; +	u32 i; +	u64 offset;  	i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);  	mutex_lock(&table->mutex);  	if (--table->icm[i]->refcount == 0) { -		mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, +		offset = (u64) i * MLX4_TABLE_CHUNK_SIZE; +		mlx4_UNMAP_ICM(dev, table->virt + offset,  			       MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);  		mlx4_free_icm(dev, table->icm[i], table->coherent);  		table->icm[i] = NULL; @@ -280,9 +283,11 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)  	mutex_unlock(&table->mutex);  } -void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle) +void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, +			dma_addr_t *dma_handle)  { -	int idx, offset, dma_offset, i; +	int offset, dma_offset, i; +	u64 idx;  	struct mlx4_icm_chunk *chunk;  	struct mlx4_icm *icm;  	struct page *page = NULL; @@ -292,7 +297,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han  	mutex_lock(&table->mutex); -	idx = (obj & (table->num_obj - 1)) * table->obj_size; +	idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size;  	icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE];  	dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE; @@ -326,10 +331,11 @@ out:  }  int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			 int start, int end) +			 u32 start, u32 end)  {  	int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size; -	int i, err; +	int err; +	u32 i;  	for (i = start; i <= end; i += inc) {  		err = mlx4_table_get(dev, table, i); @@ -349,9 +355,9 @@ fail:  }  void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			  int start, int end) +			  u32 start, u32 end)  { -	int i; +	u32 i;  	for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size)  		mlx4_table_put(dev, table, i); diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h index a67744f5350..dee67fa3910 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/drivers/net/ethernet/mellanox/mlx4/icm.h @@ -71,17 +71,17 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,  				gfp_t gfp_mask, int coherent);  void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); +int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); +void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);  int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			 int start, int end); +			 u32 start, u32 end);  void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			  int start, int end); +			  u32 start, u32 end);  int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,  			u64 virt, int obj_size,	u32 nobj, int reserved,  			int use_lowmem, int use_coherent);  void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); -void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); +void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle);  static inline void mlx4_icm_first(struct mlx4_icm *icm,  				  struct mlx4_icm_iter *iter) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 827b72dfce9..2f816c6aed7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1234,13 +1234,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  				mlx4_info(dev, "non-primary physical function, skipping.\n");  			else  				mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); -			goto unmap_bf; +			return err;  		}  		err = mlx4_load_fw(dev);  		if (err) {  			mlx4_err(dev, "Failed to start FW, aborting.\n"); -			goto unmap_bf; +			return err;  		}  		mlx4_cfg.log_pg_sz_m = 1; @@ -1304,7 +1304,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  		err = mlx4_init_slave(dev);  		if (err) {  			mlx4_err(dev, "Failed to initialize slave\n"); -			goto unmap_bf; +			return err;  		}  		err = mlx4_slave_cap(dev); @@ -1324,7 +1324,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  	err = mlx4_QUERY_ADAPTER(dev, &adapter);  	if (err) {  		mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); -		goto err_close; +		goto unmap_bf;  	}  	priv->eq_table.inta_pin = adapter.inta_pin; @@ -1332,6 +1332,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev)  	return 0; +unmap_bf: +	unmap_bf_area(dev); +  err_close:  	mlx4_close_hca(dev); @@ -1344,8 +1347,6 @@ err_stop_fw:  		mlx4_UNMAP_FA(dev);  		mlx4_free_icm(dev, priv->fw.fw_icm, 0);  	} -unmap_bf: -	unmap_bf_area(dev);  	return err;  } @@ -1996,7 +1997,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)  	}  slave_start: -	if (mlx4_cmd_init(dev)) { +	err = mlx4_cmd_init(dev); +	if (err) {  		mlx4_err(dev, "Failed to init command interface, aborting.\n");  		goto err_sriov;  	} diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index a018ea2a43d..e151c21baf2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -137,11 +137,11 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,  	return err;  } -static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, +static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port,  					      enum mlx4_steer_type steer,  					      u32 qpn)  { -	struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num]; +	struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1];  	struct mlx4_promisc_qp *pqp;  	list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) { @@ -182,7 +182,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port,  	/* If the given qpn is also a promisc qp,  	 * it should be inserted to duplicates list  	 */ -	pqp = get_promisc_qp(dev, 0, steer, qpn); +	pqp = get_promisc_qp(dev, port, steer, qpn);  	if (pqp) {  		dqp = kmalloc(sizeof *dqp, GFP_KERNEL);  		if (!dqp) { @@ -256,7 +256,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,  	s_steer = &mlx4_priv(dev)->steer[port - 1]; -	pqp = get_promisc_qp(dev, 0, steer, qpn); +	pqp = get_promisc_qp(dev, port, steer, qpn);  	if (!pqp)  		return 0; /* nothing to do */ @@ -302,7 +302,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,  	s_steer = &mlx4_priv(dev)->steer[port - 1];  	/* if qp is not promisc, it cannot be duplicated */ -	if (!get_promisc_qp(dev, 0, steer, qpn)) +	if (!get_promisc_qp(dev, port, steer, qpn))  		return false;  	/* The qp is promisc qp so it is a duplicate on this index @@ -352,7 +352,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,  	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;  	for (i = 0;  i < members_count; i++) {  		qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; -		if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { +		if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {  			/* the qp is not promisc, the entry can't be removed */  			goto out;  		} @@ -398,7 +398,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,  	mutex_lock(&priv->mcg_table.mutex); -	if (get_promisc_qp(dev, 0, steer, qpn)) { +	if (get_promisc_qp(dev, port, steer, qpn)) {  		err = 0;  /* Noting to do, already exists */  		goto out_mutex;  	} @@ -503,7 +503,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,  	s_steer = &mlx4_priv(dev)->steer[port - 1];  	mutex_lock(&priv->mcg_table.mutex); -	pqp = get_promisc_qp(dev, 0, steer, qpn); +	pqp = get_promisc_qp(dev, port, steer, qpn);  	if (unlikely(!pqp)) {  		mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);  		/* nothing to do */ @@ -650,13 +650,6 @@ static int find_entry(struct mlx4_dev *dev, u8 port,  	return err;  } -struct mlx4_net_trans_rule_hw_ctrl { -	__be32 ctrl; -	__be32 vf_vep_port; -	__be32 qpn; -	__be32 reserved; -}; -  static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,  				  struct mlx4_net_trans_rule_hw_ctrl *hw)  { @@ -680,87 +673,18 @@ static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,  	hw->qpn = cpu_to_be32(ctrl->qpn);  } -struct mlx4_net_trans_rule_hw_ib { -	u8	size; -	u8	rsvd1; -	__be16	id; -	u32	rsvd2; -	__be32	qpn; -	__be32	qpn_mask; -	u8	dst_gid[16]; -	u8	dst_gid_msk[16]; -} __packed; - -struct mlx4_net_trans_rule_hw_eth { -	u8	size; -	u8	rsvd; -	__be16	id; -	u8	rsvd1[6]; -	u8	dst_mac[6]; -	u16	rsvd2; -	u8	dst_mac_msk[6]; -	u16	rsvd3; -	u8	src_mac[6]; -	u16	rsvd4; -	u8	src_mac_msk[6]; -	u8      rsvd5; -	u8      ether_type_enable; -	__be16  ether_type; -	__be16  vlan_id_msk; -	__be16  vlan_id; -} __packed; - -struct mlx4_net_trans_rule_hw_tcp_udp { -	u8	size; -	u8	rsvd; -	__be16	id; -	__be16	rsvd1[3]; -	__be16	dst_port; -	__be16	rsvd2; -	__be16	dst_port_msk; -	__be16	rsvd3; -	__be16	src_port; -	__be16	rsvd4; -	__be16	src_port_msk; -} __packed; - -struct mlx4_net_trans_rule_hw_ipv4 { -	u8	size; -	u8	rsvd; -	__be16	id; -	__be32	rsvd1; -	__be32	dst_ip; -	__be32	dst_ip_msk; -	__be32	src_ip; -	__be32	src_ip_msk; -} __packed; - -struct _rule_hw { -	union { -		struct { -			u8 size; -			u8 rsvd; -			__be16 id; -		}; -		struct mlx4_net_trans_rule_hw_eth eth; -		struct mlx4_net_trans_rule_hw_ib ib; -		struct mlx4_net_trans_rule_hw_ipv4 ipv4; -		struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; -	}; +const u16 __sw_id_hw[] = { +	[MLX4_NET_TRANS_RULE_ID_ETH]     = 0xE001, +	[MLX4_NET_TRANS_RULE_ID_IB]      = 0xE005, +	[MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003, +	[MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002, +	[MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004, +	[MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006  };  static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,  			    struct _rule_hw *rule_hw)  { -	static const u16 __sw_id_hw[] = { -		[MLX4_NET_TRANS_RULE_ID_ETH]     = 0xE001, -		[MLX4_NET_TRANS_RULE_ID_IB]      = 0xE005, -		[MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003, -		[MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002, -		[MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004, -		[MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006 -	}; -  	static const size_t __rule_hw_sz[] = {  		[MLX4_NET_TRANS_RULE_ID_ETH] =  			sizeof(struct mlx4_net_trans_rule_hw_eth), diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 4d9df8f2a12..dba69d98734 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -690,6 +690,82 @@ struct mlx4_steer {  	struct list_head steer_entries[MLX4_NUM_STEERS];  }; +struct mlx4_net_trans_rule_hw_ctrl { +	__be32 ctrl; +	__be32 vf_vep_port; +	__be32 qpn; +	__be32 reserved; +}; + +struct mlx4_net_trans_rule_hw_ib { +	u8 size; +	u8 rsvd1; +	__be16 id; +	u32 rsvd2; +	__be32 qpn; +	__be32 qpn_mask; +	u8 dst_gid[16]; +	u8 dst_gid_msk[16]; +} __packed; + +struct mlx4_net_trans_rule_hw_eth { +	u8	size; +	u8	rsvd; +	__be16	id; +	u8	rsvd1[6]; +	u8	dst_mac[6]; +	u16	rsvd2; +	u8	dst_mac_msk[6]; +	u16	rsvd3; +	u8	src_mac[6]; +	u16	rsvd4; +	u8	src_mac_msk[6]; +	u8      rsvd5; +	u8      ether_type_enable; +	__be16  ether_type; +	__be16  vlan_id_msk; +	__be16  vlan_id; +} __packed; + +struct mlx4_net_trans_rule_hw_tcp_udp { +	u8	size; +	u8	rsvd; +	__be16	id; +	__be16	rsvd1[3]; +	__be16	dst_port; +	__be16	rsvd2; +	__be16	dst_port_msk; +	__be16	rsvd3; +	__be16	src_port; +	__be16	rsvd4; +	__be16	src_port_msk; +} __packed; + +struct mlx4_net_trans_rule_hw_ipv4 { +	u8	size; +	u8	rsvd; +	__be16	id; +	__be32	rsvd1; +	__be32	dst_ip; +	__be32	dst_ip_msk; +	__be32	src_ip; +	__be32	src_ip_msk; +} __packed; + +struct _rule_hw { +	union { +		struct { +			u8 size; +			u8 rsvd; +			__be16 id; +		}; +		struct mlx4_net_trans_rule_hw_eth eth; +		struct mlx4_net_trans_rule_hw_ib ib; +		struct mlx4_net_trans_rule_hw_ipv4 ipv4; +		struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp; +	}; +}; +  struct mlx4_priv {  	struct mlx4_dev		dev; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 94ceddd17ab..293c9e820c4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -42,6 +42,7 @@  #include <linux/mlx4/cmd.h>  #include <linux/mlx4/qp.h>  #include <linux/if_ether.h> +#include <linux/etherdevice.h>  #include "mlx4.h"  #include "fw.h" @@ -2776,18 +2777,133 @@ ex_put:  	return err;  } +/* + * MAC validation for Flow Steering rules. + * VF can attach rules only with a mac address which is assigned to it. + */ +static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header, +				   struct list_head *rlist) +{ +	struct mac_res *res, *tmp; +	__be64 be_mac; + +	/* make sure it isn't multicast or broadcast mac*/ +	if (!is_multicast_ether_addr(eth_header->eth.dst_mac) && +	    !is_broadcast_ether_addr(eth_header->eth.dst_mac)) { +		list_for_each_entry_safe(res, tmp, rlist, list) { +			be_mac = cpu_to_be64(res->mac << 16); +			if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN)) +				return 0; +		} +		pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n", +		       eth_header->eth.dst_mac, slave); +		return -EINVAL; +	} +	return 0; +} + +/* + * In case of missing eth header, append eth header with a MAC address + * assigned to the VF. + */ +static int add_eth_header(struct mlx4_dev *dev, int slave, +			  struct mlx4_cmd_mailbox *inbox, +			  struct list_head *rlist, int header_id) +{ +	struct mac_res *res, *tmp; +	u8 port; +	struct mlx4_net_trans_rule_hw_ctrl *ctrl; +	struct mlx4_net_trans_rule_hw_eth *eth_header; +	struct mlx4_net_trans_rule_hw_ipv4 *ip_header; +	struct mlx4_net_trans_rule_hw_tcp_udp *l4_header; +	__be64 be_mac = 0; +	__be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16); + +	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; +	port = be32_to_cpu(ctrl->vf_vep_port) & 0xff; +	eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1); + +	/* Clear a space in the inbox for eth header */ +	switch (header_id) { +	case MLX4_NET_TRANS_RULE_ID_IPV4: +		ip_header = +			(struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1); +		memmove(ip_header, eth_header, +			sizeof(*ip_header) + sizeof(*l4_header)); +		break; +	case MLX4_NET_TRANS_RULE_ID_TCP: +	case MLX4_NET_TRANS_RULE_ID_UDP: +		l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *) +			    (eth_header + 1); +		memmove(l4_header, eth_header, sizeof(*l4_header)); +		break; +	default: +		return -EINVAL; +	} +	list_for_each_entry_safe(res, tmp, rlist, list) { +		if (port == res->port) { +			be_mac = cpu_to_be64(res->mac << 16); +			break; +		} +	} +	if (!be_mac) { +		pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n", +		       port); +		return -EINVAL; +	} + +	memset(eth_header, 0, sizeof(*eth_header)); +	eth_header->size = sizeof(*eth_header) >> 2; +	eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]); +	memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN); +	memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN); + +	return 0; + +} +  int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,  					 struct mlx4_vhcr *vhcr,  					 struct mlx4_cmd_mailbox *inbox,  					 struct mlx4_cmd_mailbox *outbox,  					 struct mlx4_cmd_info *cmd)  { + +	struct mlx4_priv *priv = mlx4_priv(dev); +	struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; +	struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];  	int err; +	struct mlx4_net_trans_rule_hw_ctrl *ctrl; +	struct _rule_hw  *rule_header; +	int header_id;  	if (dev->caps.steering_mode !=  	    MLX4_STEERING_MODE_DEVICE_MANAGED)  		return -EOPNOTSUPP; +	ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; +	rule_header = (struct _rule_hw *)(ctrl + 1); +	header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id)); + +	switch (header_id) { +	case MLX4_NET_TRANS_RULE_ID_ETH: +		if (validate_eth_header_mac(slave, rule_header, rlist)) +			return -EINVAL; +		break; +	case MLX4_NET_TRANS_RULE_ID_IPV4: +	case MLX4_NET_TRANS_RULE_ID_TCP: +	case MLX4_NET_TRANS_RULE_ID_UDP: +		pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n"); +		if (add_eth_header(dev, slave, inbox, rlist, header_id)) +			return -EINVAL; +		vhcr->in_modifier += +			sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2; +		break; +	default: +		pr_err("Corrupted mailbox.\n"); +		return -EINVAL; +	} +  	err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,  			   vhcr->in_modifier, 0,  			   MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A, diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 342b3a79bd0..a77c558d8f4 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1378,6 +1378,10 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)  	struct pci_dev *root = pdev->bus->self;  	u32 aer_pos; +	/* root bus? */ +	if (!root) +		return; +  	if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM &&  		adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)  		return; diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c index bb8c8222122..4d15bf413bd 100644 --- a/drivers/net/ethernet/seeq/sgiseeq.c +++ b/drivers/net/ethernet/seeq/sgiseeq.c @@ -751,6 +751,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev)  	sp->srings = sr;  	sp->rx_desc = sp->srings->rxvector;  	sp->tx_desc = sp->srings->txvector; +	spin_lock_init(&sp->tx_lock);  	/* A couple calculations now, saves many cycles later. */  	setup_rx_ring(dev, sp->rx_desc, SEEQ_RX_BUFFERS); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c136162e647..3be88331d17 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1066,7 +1066,7 @@ static int stmmac_open(struct net_device *dev)  	} else  		priv->tm->enable = 1;  #endif -	clk_enable(priv->stmmac_clk); +	clk_prepare_enable(priv->stmmac_clk);  	stmmac_check_ether_addr(priv); @@ -1188,7 +1188,7 @@ open_error:  	if (priv->phydev)  		phy_disconnect(priv->phydev); -	clk_disable(priv->stmmac_clk); +	clk_disable_unprepare(priv->stmmac_clk);  	return ret;  } @@ -1246,7 +1246,7 @@ static int stmmac_release(struct net_device *dev)  #ifdef CONFIG_STMMAC_DEBUG_FS  	stmmac_exit_fs();  #endif -	clk_disable(priv->stmmac_clk); +	clk_disable_unprepare(priv->stmmac_clk);  	return 0;  } @@ -2178,7 +2178,7 @@ int stmmac_suspend(struct net_device *ndev)  	else {  		stmmac_set_mac(priv->ioaddr, false);  		/* Disable clock in case of PWM is off */ -		clk_disable(priv->stmmac_clk); +		clk_disable_unprepare(priv->stmmac_clk);  	}  	spin_unlock_irqrestore(&priv->lock, flags);  	return 0; @@ -2203,7 +2203,7 @@ int stmmac_resume(struct net_device *ndev)  		priv->hw->mac->pmt(priv->ioaddr, 0);  	else  		/* enable the clk prevously disabled */ -		clk_enable(priv->stmmac_clk); +		clk_prepare_enable(priv->stmmac_clk);  	netif_device_attach(ndev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c index 2a0e1abde7e..4ccd4e2977b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c @@ -97,19 +97,19 @@ static struct clk *timer_clock;  static void stmmac_tmu_start(unsigned int new_freq)  {  	clk_set_rate(timer_clock, new_freq); -	clk_enable(timer_clock); +	clk_prepare_enable(timer_clock);  }  static void stmmac_tmu_stop(void)  { -	clk_disable(timer_clock); +	clk_disable_unprepare(timer_clock);  }  int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)  {  	timer_clock = clk_get(NULL, TMU_CHANNEL); -	if (timer_clock == NULL) +	if (IS_ERR(timer_clock))  		return -1;  	if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) { @@ -126,7 +126,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)  int stmmac_close_ext_timer(void)  { -	clk_disable(timer_clock); +	clk_disable_unprepare(timer_clock);  	tmu2_unregister_user();  	clk_put(timer_clock);  	return 0;  |