diff options
Diffstat (limited to 'drivers/net')
69 files changed, 768 insertions, 310 deletions
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 98ee4381991..7edadee487b 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1391,7 +1391,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id)   */  static int ican3_reset_module(struct ican3_dev *mod)  { -	u8 val = 1 << mod->num;  	unsigned long start;  	u8 runold, runnew; @@ -1405,8 +1404,7 @@ static int ican3_reset_module(struct ican3_dev *mod)  	runold = ioread8(mod->dpm + TARGET_RUNNING);  	/* reset the module */ -	iowrite8(val, &mod->ctrl->reset_assert); -	iowrite8(val, &mod->ctrl->reset_deassert); +	iowrite8(0x00, &mod->dpmctrl->hwreset);  	/* wait until the module has finished resetting and is running */  	start = jiffies; diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index a580db29e50..26e7129332a 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -83,6 +83,11 @@  #define INSTRUCTION_LOAD_TXB(n)	(0x40 + 2 * (n))  #define INSTRUCTION_READ_RXB(n)	(((n) == 0) ? 0x90 : 0x94)  #define INSTRUCTION_RESET	0xC0 +#define RTS_TXB0		0x01 +#define RTS_TXB1		0x02 +#define RTS_TXB2		0x04 +#define INSTRUCTION_RTS(n)	(0x80 | ((n) & 0x07)) +  /* MPC251x registers */  #define CANSTAT	      0x0e @@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,  static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,  			  int tx_buf_idx)  { +	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);  	u32 sid, eid, exide, rtr;  	u8 buf[SPI_TRANSFER_BUF_LEN]; @@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,  	buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;  	memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);  	mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); -	mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); + +	/* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ +	priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); +	mcp251x_spi_trans(priv->spi, 1);  }  static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 527dbcf9533..9ded21e79db 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -984,12 +984,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev)  	struct net_device *ndev = platform_get_drvdata(pdev);  	struct ti_hecc_priv *priv = netdev_priv(ndev); +	unregister_candev(ndev);  	clk_disable(priv->clk);  	clk_put(priv->clk);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	iounmap(priv->base);  	release_mem_region(res->start, resource_size(res)); -	unregister_candev(ndev);  	free_candev(ndev);  	platform_set_drvdata(pdev, NULL); 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; diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c index 256eddf1f75..79510942556 100644 --- a/drivers/net/irda/sh_sir.c +++ b/drivers/net/irda/sh_sir.c @@ -280,7 +280,7 @@ static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate)  	}  	clk = clk_get(NULL, "irda_clk"); -	if (!clk) { +	if (IS_ERR(clk)) {  		dev_err(dev, "can not get irda_clk\n");  		return -EIO;  	} diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c index 2346b38b983..799789518e8 100644 --- a/drivers/net/phy/bcm87xx.c +++ b/drivers/net/phy/bcm87xx.c @@ -229,3 +229,5 @@ static void __exit bcm87xx_exit(void)  		ARRAY_SIZE(bcm87xx_driver));  }  module_exit(bcm87xx_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index cf287e0eb40..2165d5fdb8c 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -21,6 +21,12 @@  #include <linux/phy.h>  #include <linux/micrel_phy.h> +/* Operation Mode Strap Override */ +#define MII_KSZPHY_OMSO				0x16 +#define KSZPHY_OMSO_B_CAST_OFF			(1 << 9) +#define KSZPHY_OMSO_RMII_OVERRIDE		(1 << 1) +#define KSZPHY_OMSO_MII_OVERRIDE		(1 << 0) +  /* general Interrupt control/status reg in vendor specific block. */  #define MII_KSZPHY_INTCS			0x1B  #define	KSZPHY_INTCS_JABBER			(1 << 15) @@ -101,6 +107,13 @@ static int kszphy_config_init(struct phy_device *phydev)  	return 0;  } +static int ksz8021_config_init(struct phy_device *phydev) +{ +	const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE; +	phy_write(phydev, MII_KSZPHY_OMSO, val); +	return 0; +} +  static int ks8051_config_init(struct phy_device *phydev)  {  	int regval; @@ -128,9 +141,22 @@ static struct phy_driver ksphy_driver[] = {  	.config_intr	= ks8737_config_intr,  	.driver		= { .owner = THIS_MODULE,},  }, { -	.phy_id		= PHY_ID_KS8041, +	.phy_id		= PHY_ID_KSZ8021, +	.phy_id_mask	= 0x00ffffff, +	.name		= "Micrel KSZ8021", +	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause | +			   SUPPORTED_Asym_Pause), +	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, +	.config_init	= ksz8021_config_init, +	.config_aneg	= genphy_config_aneg, +	.read_status	= genphy_read_status, +	.ack_interrupt	= kszphy_ack_interrupt, +	.config_intr	= kszphy_config_intr, +	.driver		= { .owner = THIS_MODULE,}, +}, { +	.phy_id		= PHY_ID_KSZ8041,  	.phy_id_mask	= 0x00fffff0, -	.name		= "Micrel KS8041", +	.name		= "Micrel KSZ8041",  	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause  				| SUPPORTED_Asym_Pause),  	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -141,9 +167,9 @@ static struct phy_driver ksphy_driver[] = {  	.config_intr	= kszphy_config_intr,  	.driver		= { .owner = THIS_MODULE,},  }, { -	.phy_id		= PHY_ID_KS8051, +	.phy_id		= PHY_ID_KSZ8051,  	.phy_id_mask	= 0x00fffff0, -	.name		= "Micrel KS8051", +	.name		= "Micrel KSZ8051",  	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause  				| SUPPORTED_Asym_Pause),  	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -154,8 +180,8 @@ static struct phy_driver ksphy_driver[] = {  	.config_intr	= kszphy_config_intr,  	.driver		= { .owner = THIS_MODULE,},  }, { -	.phy_id		= PHY_ID_KS8001, -	.name		= "Micrel KS8001 or KS8721", +	.phy_id		= PHY_ID_KSZ8001, +	.name		= "Micrel KSZ8001 or KS8721",  	.phy_id_mask	= 0x00ffffff,  	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),  	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, @@ -201,10 +227,11 @@ MODULE_LICENSE("GPL");  static struct mdio_device_id __maybe_unused micrel_tbl[] = {  	{ PHY_ID_KSZ9021, 0x000ffffe }, -	{ PHY_ID_KS8001, 0x00ffffff }, +	{ PHY_ID_KSZ8001, 0x00ffffff },  	{ PHY_ID_KS8737, 0x00fffff0 }, -	{ PHY_ID_KS8041, 0x00fffff0 }, -	{ PHY_ID_KS8051, 0x00fffff0 }, +	{ PHY_ID_KSZ8021, 0x00ffffff }, +	{ PHY_ID_KSZ8041, 0x00fffff0 }, +	{ PHY_ID_KSZ8051, 0x00fffff0 },  	{ }  }; diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index cbf7047decc..20f31d0d153 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -570,7 +570,7 @@ static int pppoe_release(struct socket *sock)  	po = pppox_sk(sk); -	if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { +	if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {  		dev_put(po->pppoe_dev);  		po->pppoe_dev = NULL;  	} diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 341b65dbbcd..3ffe8a6e3c8 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -848,7 +848,7 @@ static struct netpoll_info *team_netpoll_info(struct team *team)  }  #endif -static void __team_port_change_check(struct team_port *port, bool linkup); +static void __team_port_change_port_added(struct team_port *port, bool linkup);  static int team_port_add(struct team *team, struct net_device *port_dev)  { @@ -948,7 +948,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev)  	team_port_enable(team, port);  	list_add_tail_rcu(&port->list, &team->port_list);  	__team_compute_features(team); -	__team_port_change_check(port, !!netif_carrier_ok(port_dev)); +	__team_port_change_port_added(port, !!netif_carrier_ok(port_dev));  	__team_options_change_check(team);  	netdev_info(dev, "Port device %s added\n", portname); @@ -983,6 +983,8 @@ err_set_mtu:  	return err;  } +static void __team_port_change_port_removed(struct team_port *port); +  static int team_port_del(struct team *team, struct net_device *port_dev)  {  	struct net_device *dev = team->dev; @@ -999,8 +1001,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev)  	__team_option_inst_mark_removed_port(team, port);  	__team_options_change_check(team);  	__team_option_inst_del_port(team, port); -	port->removed = true; -	__team_port_change_check(port, false); +	__team_port_change_port_removed(port);  	team_port_disable(team, port);  	list_del_rcu(&port->list);  	netdev_rx_handler_unregister(port_dev); @@ -2251,13 +2252,11 @@ static void __team_options_change_check(struct team *team)  }  /* rtnl lock is held */ -static void __team_port_change_check(struct team_port *port, bool linkup) + +static void __team_port_change_send(struct team_port *port, bool linkup)  {  	int err; -	if (!port->removed && port->state.linkup == linkup) -		return; -  	port->changed = true;  	port->state.linkup = linkup;  	team_refresh_port_linkup(port); @@ -2282,6 +2281,23 @@ send_event:  } +static void __team_port_change_check(struct team_port *port, bool linkup) +{ +	if (port->state.linkup != linkup) +		__team_port_change_send(port, linkup); +} + +static void __team_port_change_port_added(struct team_port *port, bool linkup) +{ +	__team_port_change_send(port, linkup); +} + +static void __team_port_change_port_removed(struct team_port *port) +{ +	port->removed = true; +	__team_port_change_send(port, false); +} +  static void team_port_change_check(struct team_port *port, bool linkup)  {  	struct team *team = port->team; diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 4fd48df6b98..32e31c5c5dc 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -962,6 +962,10 @@ static const struct usb_device_id	products [] = {  	USB_DEVICE (0x2001, 0x3c05),  	.driver_info = (unsigned long) &ax88772_info,  }, { +       // DLink DUB-E100 H/W Ver C1 +       USB_DEVICE (0x2001, 0x1a02), +       .driver_info = (unsigned long) &ax88772_info, +}, {  	// Linksys USB1000  	USB_DEVICE (0x1737, 0x0039),  	.driver_info = (unsigned long) &ax88178_info, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index adfab3fc547..3543c9e5782 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -297,7 +297,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)  	if (ret < 0)  		goto err; -	if (info->subdriver && info->subdriver->suspend) +	if (intf == info->control && info->subdriver && info->subdriver->suspend)  		ret = info->subdriver->suspend(intf, message);  	if (ret < 0)  		usbnet_resume(intf); @@ -310,13 +310,14 @@ static int qmi_wwan_resume(struct usb_interface *intf)  	struct usbnet *dev = usb_get_intfdata(intf);  	struct qmi_wwan_state *info = (void *)&dev->data;  	int ret = 0; +	bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume); -	if (info->subdriver && info->subdriver->resume) +	if (callsub)  		ret = info->subdriver->resume(intf);  	if (ret < 0)  		goto err;  	ret = usbnet_resume(intf); -	if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend) +	if (ret < 0 && callsub && info->subdriver->suspend)  		info->subdriver->suspend(intf, PMSG_SUSPEND);  err:  	return ret; @@ -365,16 +366,20 @@ static const struct usb_device_id products[] = {  	},  	/* 2. Combined interface devices matching on class+protocol */ +	{	/* Huawei E367 and possibly others in "Windows mode" */ +		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 7), +		.driver_info        = (unsigned long)&qmi_wwan_info, +	},  	{	/* Huawei E392, E398 and possibly others in "Windows mode" */  		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),  		.driver_info        = (unsigned long)&qmi_wwan_shared,  	}, -	{	/* Pantech UML290 */ -		USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), +	{	/* Pantech UML290, P4200 and more */ +		USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),  		.driver_info        = (unsigned long)&qmi_wwan_shared,  	},  	{	/* Pantech UML290 - newer firmware */ -		USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), +		USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),  		.driver_info        = (unsigned long)&qmi_wwan_shared,  	}, @@ -382,6 +387,7 @@ static const struct usb_device_id products[] = {  	{QMI_FIXED_INTF(0x19d2, 0x0055, 1)},	/* ZTE (Vodafone) K3520-Z */  	{QMI_FIXED_INTF(0x19d2, 0x0063, 4)},	/* ZTE (Vodafone) K3565-Z */  	{QMI_FIXED_INTF(0x19d2, 0x0104, 4)},	/* ZTE (Vodafone) K4505-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x0157, 5)},	/* ZTE MF683 */  	{QMI_FIXED_INTF(0x19d2, 0x0167, 4)},	/* ZTE MF820D */  	{QMI_FIXED_INTF(0x19d2, 0x0326, 4)},	/* ZTE MF821D */  	{QMI_FIXED_INTF(0x19d2, 0x1008, 4)},	/* ZTE (Vodafone) K3570-Z */ @@ -398,7 +404,6 @@ static const struct usb_device_id products[] = {  	/* 4. Gobi 1000 devices */  	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */  	{QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */ -	{QMI_GOBI1K_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */  	{QMI_GOBI1K_DEVICE(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */  	{QMI_GOBI1K_DEVICE(0x413c, 0x8172)},	/* Dell Gobi Modem device */  	{QMI_GOBI1K_DEVICE(0x1410, 0xa001)},	/* Novatel Gobi Modem device */ @@ -440,6 +445,7 @@ static const struct usb_device_id products[] = {  	{QMI_GOBI_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */  	{QMI_GOBI_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */  	{QMI_GOBI_DEVICE(0x1199, 0x9013)},	/* Sierra Wireless Gobi 3000 Modem device (MC8355) */ +	{QMI_GOBI_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */  	{QMI_GOBI_DEVICE(0x1199, 0x9015)},	/* Sierra Wireless Gobi 3000 Modem device */  	{QMI_GOBI_DEVICE(0x1199, 0x9019)},	/* Sierra Wireless Gobi 3000 Modem device */  	{QMI_GOBI_DEVICE(0x1199, 0x901b)},	/* Sierra Wireless MC7770 */ diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index 7be49ea60b6..8e22417fa6c 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -656,7 +656,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)  		return -EIO;  	} -	*datap = *attrdata; +	*datap = le16_to_cpu(*attrdata);  	kfree(attrdata);  	return result; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index fd4b26d46fd..fc9f578a1e2 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1201,19 +1201,26 @@ deferred:  }  EXPORT_SYMBOL_GPL(usbnet_start_xmit); -static void rx_alloc_submit(struct usbnet *dev, gfp_t flags) +static int rx_alloc_submit(struct usbnet *dev, gfp_t flags)  {  	struct urb	*urb;  	int		i; +	int		ret = 0;  	/* don't refill the queue all at once */  	for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) {  		urb = usb_alloc_urb(0, flags);  		if (urb != NULL) { -			if (rx_submit(dev, urb, flags) == -ENOLINK) -				return; +			ret = rx_submit(dev, urb, flags); +			if (ret) +				goto err; +		} else { +			ret = -ENOMEM; +			goto err;  		}  	} +err: +	return ret;  }  /*-------------------------------------------------------------------------*/ @@ -1257,7 +1264,8 @@ static void usbnet_bh (unsigned long param)  		int	temp = dev->rxq.qlen;  		if (temp < RX_QLEN(dev)) { -			rx_alloc_submit(dev, GFP_ATOMIC); +			if (rx_alloc_submit(dev, GFP_ATOMIC) == -ENOLINK) +				return;  			if (temp != dev->rxq.qlen)  				netif_dbg(dev, link, dev->net,  					  "rxqlen %d --> %d\n", diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index aaaca9aa229..3f575afd8cf 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -10,6 +10,7 @@  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/module.h>  #include <linux/bitops.h>  #include <linux/cdev.h>  #include <linux/dma-mapping.h> diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 2588848f4a8..d066f2516e4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -2982,6 +2982,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,  	case EEP_RX_MASK:  		return pBase->txrxMask & 0xf;  	case EEP_PAPRD: +		if (AR_SREV_9462(ah)) +			return false; +		if (!ah->config.enable_paprd); +			return false;  		return !!(pBase->featureEnable & BIT(5));  	case EEP_CHAIN_MASK_REDUCE:  		return (pBase->miscConfiguration >> 0x3) & 0x1; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 2c9f7d7ed4c..0ed3846f9cb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)  	};  	int training_power;  	int i, val; +	u32 am2pm_mask = ah->paprd_ratemask;  	if (IS_CHAN_2GHZ(ah->curchan))  		training_power = ar9003_get_training_power_2g(ah); @@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)  	}  	ah->paprd_training_power = training_power; +	if (AR_SREV_9330(ah)) +		am2pm_mask = 0; +  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,  		      ah->paprd_ratemask);  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, -		      ah->paprd_ratemask); +		      am2pm_mask);  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,  		      ah->paprd_ratemask_ht40); @@ -782,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)  }  EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); +static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah, +				       struct ath9k_hw_cal_data *caldata, +				       int chain) +{ +	u32 *pa_in = caldata->pa_table[chain]; +	int capdiv_offset, quick_drop_offset; +	int capdiv2g, quick_drop; +	int count = 0; +	int i; + +	if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah)) +		return false; + +	capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, +				  AR_PHY_65NM_CH0_TXRF3_CAPDIV2G); + +	quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, +				    AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP); + +	if (quick_drop) +		quick_drop -= 0x40; + +	for (i = 0; i < NUM_BIN + 1; i++) { +		if (pa_in[i] == 1400) +			count++; +	} + +	if (AR_SREV_9485(ah)) { +		if (pa_in[23] < 800) { +			capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150); +			capdiv2g += capdiv_offset; +			if (capdiv2g > 7) { +				capdiv2g = 7; +				if (pa_in[23] < 600) { +					quick_drop++; +					if (quick_drop > 0) +						quick_drop = 0; +				} +			} +		} else if (pa_in[23] == 1400) { +			quick_drop_offset = min_t(int, count / 3, 2); +			quick_drop += quick_drop_offset; +			capdiv2g += quick_drop_offset / 2; + +			if (capdiv2g > 7) +				capdiv2g = 7; + +			if (quick_drop > 0) { +				quick_drop = 0; +				capdiv2g -= quick_drop_offset; +				if (capdiv2g < 0) +					capdiv2g = 0; +			} +		} else { +			return false; +		} +	} else if (AR_SREV_9330(ah)) { +		if (pa_in[23] < 1000) { +			capdiv_offset = (1000 - pa_in[23]) / 100; +			capdiv2g += capdiv_offset; +			if (capdiv_offset > 3) { +				capdiv_offset = 1; +				quick_drop--; +			} + +			capdiv2g += capdiv_offset; +			if (capdiv2g > 6) +				capdiv2g = 6; +			if (quick_drop < -4) +				quick_drop = -4; +		} else if (pa_in[23] == 1400) { +			if (count > 3) { +				quick_drop++; +				capdiv2g -= count / 4; +				if (quick_drop > -2) +					quick_drop = -2; +			} else { +				capdiv2g--; +			} + +			if (capdiv2g < 0) +				capdiv2g = 0; +		} else { +			return false; +		} +	} + +	REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, +		      AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g); +	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, +		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, +		      quick_drop); + +	return true; +} +  int ar9003_paprd_create_curve(struct ath_hw *ah,  			      struct ath9k_hw_cal_data *caldata, int chain)  { @@ -817,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath_hw *ah,  	if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))  		status = -2; +	if (ar9003_paprd_retrain_pa_in(ah, caldata, chain)) +		status = -EINPROGRESS; +  	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,  		    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 7bfbaf065a4..84d3d495686 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -625,6 +625,10 @@  #define AR_PHY_AIC_CTRL_4_B0	(AR_SM_BASE + 0x4c0)  #define AR_PHY_AIC_STAT_2_B0	(AR_SM_BASE + 0x4cc) +#define AR_PHY_65NM_CH0_TXRF3       0x16048 +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G		0x0000001e +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S	1 +  #define AR_PHY_65NM_CH0_SYNTH4      0x1608c  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 68b643c8943..c8ef30127ad 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1577,6 +1577,8 @@ int ath9k_init_debug(struct ath_hw *ah)  			    sc->debug.debugfs_phy, sc, &fops_tx_chainmask);  	debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,  			    sc->debug.debugfs_phy, sc, &fops_disable_ani); +	debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, +			    &sc->sc_ah->config.enable_paprd);  	debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,  			    sc, &fops_regidx);  	debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index bacdb8fb4ef..9f83f71742a 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -341,7 +341,8 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)  {  	struct ath_btcoex *btcoex = &sc->btcoex; -	ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); +	if (btcoex->hw_timer_enabled) +		ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);  }  u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 60b6a9daff7..4faf0a39587 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)  		ah->config.spurchans[i][1] = AR_NO_SPUR;  	} -	/* PAPRD needs some more work to be enabled */ -	ah->config.paprd_disable = 1; -  	ah->config.rx_intr_mitigation = true;  	ah->config.pcieSerDesWrite = true; @@ -978,9 +975,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,  	else  		imr_reg |= AR_IMR_TXOK; -	if (opmode == NL80211_IFTYPE_AP) -		imr_reg |= AR_IMR_MIB; -  	ENABLE_REGWRITE_BUFFER(ah);  	REG_WRITE(ah, AR_IMR, imr_reg); @@ -1778,6 +1772,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  		/* Operating channel changed, reset channel calibration data */  		memset(caldata, 0, sizeof(*caldata));  		ath9k_init_nfcal_hist_buffer(ah, chan); +	} else if (caldata) { +		caldata->paprd_packet_sent = false;  	}  	ah->noise = ath9k_hw_getchan_noise(ah, chan); @@ -2501,9 +2497,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)  		pCap->rx_status_len = sizeof(struct ar9003_rxs);  		pCap->tx_desc_len = sizeof(struct ar9003_txc);  		pCap->txs_len = sizeof(struct ar9003_txs); -		if (!ah->config.paprd_disable && -		    ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) -			pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;  	} else {  		pCap->tx_desc_len = sizeof(struct ath_desc);  		if (AR_SREV_9280_20(ah)) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ce7332c64ef..de6968fc64f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -236,7 +236,6 @@ enum ath9k_hw_caps {  	ATH9K_HW_CAP_LDPC			= BIT(6),  	ATH9K_HW_CAP_FASTCLOCK			= BIT(7),  	ATH9K_HW_CAP_SGI_20			= BIT(8), -	ATH9K_HW_CAP_PAPRD			= BIT(9),  	ATH9K_HW_CAP_ANT_DIV_COMB		= BIT(10),  	ATH9K_HW_CAP_2GHZ			= BIT(11),  	ATH9K_HW_CAP_5GHZ			= BIT(12), @@ -287,12 +286,12 @@ struct ath9k_ops_config {  	u8 pcie_clock_req;  	u32 pcie_waen;  	u8 analog_shiftreg; -	u8 paprd_disable;  	u32 ofdm_trig_low;  	u32 ofdm_trig_high;  	u32 cck_trig_high;  	u32 cck_trig_low;  	u32 enable_ani; +	u32 enable_paprd;  	int serialize_regmode;  	bool rx_intr_mitigation;  	bool tx_intr_mitigation; @@ -405,6 +404,7 @@ struct ath9k_hw_cal_data {  	int8_t iCoff;  	int8_t qCoff;  	bool rtt_done; +	bool paprd_packet_sent;  	bool paprd_done;  	bool nfcal_pending;  	bool nfcal_interference; diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index d4549e9aac5..7b88b9c39cc 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -254,8 +254,9 @@ void ath_paprd_calibrate(struct work_struct *work)  	int chain_ok = 0;  	int chain;  	int len = 1800; +	int ret; -	if (!caldata) +	if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)  		return;  	ath9k_ps_wakeup(sc); @@ -282,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work)  			continue;  		chain_ok = 0; - -		ath_dbg(common, CALIBRATE, -			"Sending PAPRD frame for thermal measurement on chain %d\n", -			chain); -		if (!ath_paprd_send_frame(sc, skb, chain)) -			goto fail_paprd; -  		ar9003_paprd_setup_gain_table(ah, chain);  		ath_dbg(common, CALIBRATE, @@ -302,7 +296,13 @@ void ath_paprd_calibrate(struct work_struct *work)  			break;  		} -		if (ar9003_paprd_create_curve(ah, caldata, chain)) { +		ret = ar9003_paprd_create_curve(ah, caldata, chain); +		if (ret == -EINPROGRESS) { +			ath_dbg(common, CALIBRATE, +				"PAPRD curve on chain %d needs to be re-trained\n", +				chain); +			break; +		} else if (ret) {  			ath_dbg(common, CALIBRATE,  				"PAPRD create curve failed on chain %d\n",  				chain); @@ -423,7 +423,7 @@ set_timer:  		cal_interval = min(cal_interval, (u32)short_cal_interval);  	mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); -	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { +	if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) {  		if (!ah->caldata->paprd_done)  			ieee80211_queue_work(sc->hw, &sc->paprd_work);  		else if (!ah->paprd_table_write_done) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2c9da6b2ecb..0d4155aec48 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2018,6 +2018,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,  	ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); +	if (sc->sc_ah->caldata) +		sc->sc_ah->caldata->paprd_packet_sent = true; +  	if (!(tx_flags & ATH_TX_ERROR))  		/* Frame was ACKed */  		tx_info->flags |= IEEE80211_TX_STAT_ACK; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 49765d34b4e..7c4ee72f9d5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -638,6 +638,8 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev)  		oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),  				       GFP_KERNEL); +		if (!oobirq_entry) +			return -ENOMEM;  		oobirq_entry->irq = res->start;  		oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;  		list_add_tail(&oobirq_entry->list, &oobirq_lh); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 2621dd3d7dc..6f70953f0ba 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -764,8 +764,11 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)  {  	char iovbuf[32];  	int retcode; +	__le32 arp_mode_le; -	brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); +	arp_mode_le = cpu_to_le32(arp_mode); +	brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, +			sizeof(iovbuf));  	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,  				   iovbuf, sizeof(iovbuf));  	retcode = retcode >= 0 ? 0 : retcode; @@ -781,8 +784,11 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)  {  	char iovbuf[32];  	int retcode; +	__le32 arp_enable_le; -	brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, +	arp_enable_le = cpu_to_le32(arp_enable); + +	brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4,  			iovbuf, sizeof(iovbuf));  	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,  				   iovbuf, sizeof(iovbuf)); @@ -800,10 +806,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  	char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];	/*  Room for  				 "event_msgs" + '\0' + bitvec  */  	char buf[128], *ptr; -	u32 roaming = 1; -	uint bcn_timeout = 3; -	int scan_assoc_time = 40; -	int scan_unassoc_time = 40; +	__le32 roaming_le = cpu_to_le32(1); +	__le32 bcn_timeout_le = cpu_to_le32(3); +	__le32 scan_assoc_time_le = cpu_to_le32(40); +	__le32 scan_unassoc_time_le = cpu_to_le32(40);  	int i;  	struct brcmf_bus_dcmd *cmdlst;  	struct list_head *cur, *q; @@ -829,14 +835,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  	/* Setup timeout if Beacons are lost and roam is off to report  		 link down */ -	brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, +	brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,  		    sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,  				  sizeof(iovbuf));  	/* Enable/Disable build-in roaming to allowed ext supplicant to take  		 of romaing */ -	brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, +	brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4,  		      iovbuf, sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,  				  sizeof(iovbuf)); @@ -848,9 +854,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  				  sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, -			 (char *)&scan_assoc_time, sizeof(scan_assoc_time)); +		 (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, -			 (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); +		 (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le));  	/* Set and enable ARP offload feature */  	brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a299d42da8e..58f89fa9c9f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -519,7 +519,7 @@ static void brcmf_usb_tx_complete(struct urb *urb)  	else  		devinfo->bus_pub.bus->dstats.tx_errors++; -	dev_kfree_skb(req->skb); +	brcmu_pkt_buf_free_skb(req->skb);  	req->skb = NULL;  	brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); @@ -540,7 +540,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)  		devinfo->bus_pub.bus->dstats.rx_packets++;  	} else {  		devinfo->bus_pub.bus->dstats.rx_errors++; -		dev_kfree_skb(skb); +		brcmu_pkt_buf_free_skb(skb);  		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  		return;  	} @@ -550,13 +550,15 @@ static void brcmf_usb_rx_complete(struct urb *urb)  		if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {  			brcmf_dbg(ERROR, "rx protocol error\n");  			brcmu_pkt_buf_free_skb(skb); +			brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  			devinfo->bus_pub.bus->dstats.rx_errors++;  		} else {  			brcmf_rx_packet(devinfo->dev, ifidx, skb);  			brcmf_usb_rx_refill(devinfo, req);  		}  	} else { -		dev_kfree_skb(skb); +		brcmu_pkt_buf_free_skb(skb); +		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  	}  	return; @@ -581,14 +583,13 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,  	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,  			  skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,  			  req); -	req->urb->transfer_flags |= URB_ZERO_PACKET;  	req->devinfo = devinfo; +	brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);  	ret = usb_submit_urb(req->urb, GFP_ATOMIC); -	if (ret == 0) { -		brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); -	} else { -		dev_kfree_skb(req->skb); +	if (ret) { +		brcmf_usb_del_fromq(devinfo, req); +		brcmu_pkt_buf_free_skb(req->skb);  		req->skb = NULL;  		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  	} @@ -683,23 +684,22 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)  	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);  	if (!req) { +		brcmu_pkt_buf_free_skb(skb);  		brcmf_dbg(ERROR, "no req to send\n");  		return -ENOMEM;  	} -	if (!req->urb) { -		brcmf_dbg(ERROR, "no urb for req %p\n", req); -		return -ENOBUFS; -	}  	req->skb = skb;  	req->devinfo = devinfo;  	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,  			  skb->data, skb->len, brcmf_usb_tx_complete, req);  	req->urb->transfer_flags |= URB_ZERO_PACKET; +	brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);  	ret = usb_submit_urb(req->urb, GFP_ATOMIC); -	if (!ret) { -		brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); -	} else { +	if (ret) { +		brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n"); +		brcmf_usb_del_fromq(devinfo, req); +		brcmu_pkt_buf_free_skb(req->skb);  		req->skb = NULL;  		brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);  	} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 28c5fbb4af2..50b5553b696 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -500,8 +500,10 @@ static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,  	params_le->active_time = cpu_to_le32(-1);  	params_le->passive_time = cpu_to_le32(-1);  	params_le->home_time = cpu_to_le32(-1); -	if (ssid && ssid->SSID_len) -		memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); +	if (ssid && ssid->SSID_len) { +		params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len); +		memcpy(¶ms_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len); +	}  }  static s32 @@ -1876,16 +1878,17 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,  	}  	if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { -		scb_val.val = cpu_to_le32(0); +		memset(&scb_val, 0, sizeof(scb_val));  		err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,  				      sizeof(struct brcmf_scb_val_le)); -		if (err) +		if (err) {  			WL_ERR("Could not get rssi (%d)\n", err); - -		rssi = le32_to_cpu(scb_val.val); -		sinfo->filled |= STATION_INFO_SIGNAL; -		sinfo->signal = rssi; -		WL_CONN("RSSI %d dBm\n", rssi); +		} else { +			rssi = le32_to_cpu(scb_val.val); +			sinfo->filled |= STATION_INFO_SIGNAL; +			sinfo->signal = rssi; +			WL_CONN("RSSI %d dBm\n", rssi); +		}  	}  done: diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 7ed7d757702..64a48f06d68 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -77,7 +77,7 @@  					 NL80211_RRF_NO_IBSS)  static const struct ieee80211_regdomain brcms_regdom_x2 = { -	.n_reg_rules = 7, +	.n_reg_rules = 6,  	.alpha2 = "X2",  	.reg_rules = {  		BRCM_2GHZ_2412_2462, diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 1e86ea2266d..dbeebef562d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1442,6 +1442,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)  	return err;  err_free_irq: +	trans_pcie->irq_requested = false;  	free_irq(trans_pcie->irq, trans);  error:  	iwl_free_isr_ict(trans); diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index e970897f6ab..4cb234349fb 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -1326,6 +1326,11 @@ static int if_sdio_suspend(struct device *dev)  	mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); +	/* If we're powered off anyway, just let the mmc layer remove the +	 * card. */ +	if (!lbs_iface_active(card->priv)) +		return -ENOSYS; +  	dev_info(dev, "%s: suspend: PM flags = 0x%x\n",  		 sdio_func_id(func), flags); diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index c68adec3cc8..565527aee0e 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,  	cmd_code = le16_to_cpu(host_cmd->command);  	cmd_size = le16_to_cpu(host_cmd->size); -	skb_trim(cmd_node->cmd_skb, cmd_size); +	/* Adjust skb length */ +	if (cmd_node->cmd_skb->len > cmd_size) +		/* +		 * cmd_size is less than sizeof(struct host_cmd_ds_command). +		 * Trim off the unused portion. +		 */ +		skb_trim(cmd_node->cmd_skb, cmd_size); +	else if (cmd_node->cmd_skb->len < cmd_size) +		/* +		 * cmd_size is larger than sizeof(struct host_cmd_ds_command) +		 * because we have appended custom IE TLV. Increase skb length +		 * accordingly. +		 */ +		skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);  	do_gettimeofday(&tstamp);  	dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 8b9dbd76a25..64328af496f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -1624,6 +1625,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); +	rt2x00_set_field32(®, GPIOCSR_BIT8, 1); +	rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2400pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc43..7564ae992b7 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,6 +670,7 @@  #define GPIOCSR_BIT5			FIELD32(0x00000020)  #define GPIOCSR_BIT6			FIELD32(0x00000040)  #define GPIOCSR_BIT7			FIELD32(0x00000080) +#define GPIOCSR_BIT8			FIELD32(0x00000100)  /*   * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d2cf8a4bc8b..3de0406735f 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -1942,6 +1943,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); +	rt2x00_set_field32(®, GPIOCSR_DIR0, 1); +	rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2500pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3aae36bb0a9..89fee311d8f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)  	u16 reg;  	rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); -	return rt2x00_get_field32(reg, MAC_CSR19_BIT7); +	return rt2x00_get_field16(reg, MAC_CSR19_BIT7);  }  #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u16 reg;  	/*  	 * Allocate eeprom data. @@ -1781,6 +1782,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); +	rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); +	rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2500usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7ee..196bd5103e4 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,14 +189,15 @@   * MAC_CSR19: GPIO control register.   */  #define MAC_CSR19			0x0426 -#define MAC_CSR19_BIT0			FIELD32(0x0001) -#define MAC_CSR19_BIT1			FIELD32(0x0002) -#define MAC_CSR19_BIT2			FIELD32(0x0004) -#define MAC_CSR19_BIT3			FIELD32(0x0008) -#define MAC_CSR19_BIT4			FIELD32(0x0010) -#define MAC_CSR19_BIT5			FIELD32(0x0020) -#define MAC_CSR19_BIT6			FIELD32(0x0040) -#define MAC_CSR19_BIT7			FIELD32(0x0080) +#define MAC_CSR19_BIT0			FIELD16(0x0001) +#define MAC_CSR19_BIT1			FIELD16(0x0002) +#define MAC_CSR19_BIT2			FIELD16(0x0004) +#define MAC_CSR19_BIT3			FIELD16(0x0008) +#define MAC_CSR19_BIT4			FIELD16(0x0010) +#define MAC_CSR19_BIT5			FIELD16(0x0020) +#define MAC_CSR19_BIT6			FIELD16(0x0040) +#define MAC_CSR19_BIT7			FIELD16(0x0080) +#define MAC_CSR19_BIT8			FIELD16(0x0100)  /*   * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index cb8c2aca54e..b93516d832f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4089,6 +4089,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);  		msleep(1);  		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0);  		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);  		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);  	} diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 98aa426a356..4765bbd654c 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -983,6 +983,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -996,6 +997,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); +	rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); +	rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2800_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6cf336595e2..6b4226b7161 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,  	skb_pull(entry->skb, RXINFO_DESC_SIZE);  	/* -	 * FIXME: we need to check for rx_pkt_len validity +	 * Check for rx_pkt_len validity. Return if invalid, leaving +	 * rxdesc->size zeroed out by the upper level.  	 */ +	if (unlikely(rx_pkt_len == 0 || +			rx_pkt_len > entry->queue->data_size)) { +		ERROR(entry->queue->rt2x00dev, +			"Bad frame size %d, forcing to 0\n", rx_pkt_len); +		return; +	} +  	rxd = (__le32 *)(entry->skb->data + rx_pkt_len);  	/* @@ -736,6 +744,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -749,6 +758,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); +	rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); +	rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2800_probe_hw_mode(rt2x00dev); @@ -1157,6 +1174,8 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x1690, 0x0744) },  	{ USB_DEVICE(0x1690, 0x0761) },  	{ USB_DEVICE(0x1690, 0x0764) }, +	/* ASUS */ +	{ USB_DEVICE(0x0b05, 0x179d) },  	/* Cisco */  	{ USB_DEVICE(0x167b, 0x4001) },  	/* EnGenius */ @@ -1222,7 +1241,6 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x0b05, 0x1760) },  	{ USB_DEVICE(0x0b05, 0x1761) },  	{ USB_DEVICE(0x0b05, 0x1790) }, -	{ USB_DEVICE(0x0b05, 0x179d) },  	/* AzureWave */  	{ USB_DEVICE(0x13d3, 0x3262) },  	{ USB_DEVICE(0x13d3, 0x3284) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a6b88bd4a1a..3f07e36f462 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)  	 */  	if (unlikely(rxdesc.size == 0 ||  		     rxdesc.size > entry->queue->data_size)) { -		WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", +		ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",  			rxdesc.size, entry->queue->data_size);  		dev_kfree_skb(entry->skb);  		goto renew_skb; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3f7bc5cadf9..b8ec9616392 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Disable power saving. @@ -2850,6 +2851,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); +	rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt61pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db76b0..8f3da5a5676 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry {  #define MAC_CSR13_BIT10			FIELD32(0x00000400)  #define MAC_CSR13_BIT11			FIELD32(0x00000800)  #define MAC_CSR13_BIT12			FIELD32(0x00001000) +#define MAC_CSR13_BIT13			FIELD32(0x00002000)  /*   * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ba6e434b859..248436c13ce 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -2190,6 +2191,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); +	rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt73usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470414d..df1cc116b83 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry {  #define MAC_CSR13_BIT10			FIELD32(0x00000400)  #define MAC_CSR13_BIT11			FIELD32(0x00000800)  #define MAC_CSR13_BIT12			FIELD32(0x00001000) +#define MAC_CSR13_BIT13			FIELD32(0x00002000) +#define MAC_CSR13_BIT14			FIELD32(0x00004000) +#define MAC_CSR13_BIT15			FIELD32(0x00008000)  /*   * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 04c3aef8a4f..2925094b2d9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -117,6 +117,7 @@  #define CHIP_VER_B			BIT(4)  #define CHIP_92C_BITMASK		BIT(0) +#define CHIP_UNKNOWN			BIT(7)  #define CHIP_92C_1T2R			0x03  #define CHIP_92C			0x01  #define CHIP_88C			0x00 diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index bd0da7ef290..dd4bb0950a5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -994,8 +994,16 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)  		version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C :  			   VERSION_A_CHIP_88C;  	} else { -		version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C : -			   VERSION_B_CHIP_88C; +		version = (enum version_8192c) (CHIP_VER_B | +				((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | +				((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); +		if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & +		     CHIP_VER_RTL_MASK)) { +			version = (enum version_8192c)(version | +				   ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) +				   ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | +				   CHIP_VENDOR_UMC)); +		}  	}  	switch (version) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 3aa927f8b9b..7d8f96405f4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -162,10 +162,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)  	/* request fw */  	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && -	    !IS_92C_SERIAL(rtlhal->version)) +	    !IS_92C_SERIAL(rtlhal->version)) {  		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; -	else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) +	} else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {  		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; +		pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); +	}  	rtlpriv->max_fw_size = 0x4000;  	pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);  |