Netdev List
 help / color / mirror / Atom feed
* [net-next v2 5/9] bnx2x: Change Warpcore MDIO work around mode
From: Yaniv Rosner @ 2011-11-28 10:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Yaniv Rosner, Eilon Greenstein
In-Reply-To: <1322477393-22904-1-git-send-email-yanivr@broadcom.com>

This patch enables the usage of simpler MDC/MDIO work-around when accessing Warpcore registers.

Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 6523723..4ffc75d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -11308,7 +11308,9 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
 				       offsetof(struct shmem_region,
 			dev_info.port_feature_config[port].link_config)) &
 			  PORT_FEATURE_CONNECTED_SWITCH_MASK);
-	chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
+	chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+		((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+
 	DP(NETIF_MSG_LINK, ":chip_id = 0x%x\n", chip_id);
 	if (USES_WARPCORE(bp)) {
 		u32 serdes_net_if;
-- 
1.7.7.1

^ permalink raw reply related

* [net-next v2 6/9] bnx2x: Add known PHY type check
From: Yaniv Rosner @ 2011-11-28 10:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Yaniv Rosner, Eilon Greenstein
In-Reply-To: <1322477393-22904-1-git-send-email-yanivr@broadcom.com>

The populate function will fail in case an unknown external PHY is detected.

Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 4ffc75d..cc7dbbe 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -11489,6 +11489,10 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
 		return -EINVAL;
 	default:
 		*phy = phy_null;
+		/* In case external PHY wasn't found */
+		if ((phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
+		    (phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
+			return -EINVAL;
 		return 0;
 	}
 
-- 
1.7.7.1

^ permalink raw reply related

* [net-next v2 7/9] bnx2x: Fix self test of BCM57800
From: Yaniv Rosner @ 2011-11-28 10:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Yaniv Rosner, Eilon Greenstein
In-Reply-To: <1322477393-22904-1-git-send-email-yanivr@broadcom.com>

Fix the MAC test of the 1G port of the BCM57800 to use the UMAC instead of the XMAC.

Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
 .../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c    |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index ec31871..f1bf1f5 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1749,8 +1749,18 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
 			return -EINVAL;
 		break;
 	case BNX2X_MAC_LOOPBACK:
-		bp->link_params.loopback_mode = CHIP_IS_E3(bp) ?
-						LOOPBACK_XMAC : LOOPBACK_BMAC;
+		if (CHIP_IS_E3(bp)) {
+			int cfg_idx = bnx2x_get_link_cfg_idx(bp);
+			if (bp->port.supported[cfg_idx] &
+			    (SUPPORTED_10000baseT_Full |
+			     SUPPORTED_20000baseMLD2_Full |
+			     SUPPORTED_20000baseKR2_Full))
+				bp->link_params.loopback_mode = LOOPBACK_XMAC;
+			else
+				bp->link_params.loopback_mode = LOOPBACK_UMAC;
+		} else
+			bp->link_params.loopback_mode = LOOPBACK_BMAC;
+
 		bnx2x_phy_init(&bp->link_params, &bp->link_vars);
 		break;
 	default:
-- 
1.7.7.1

^ permalink raw reply related

* [net-next v2 4/9] bnx2x: Fix BCM84833 link and LED behavior
From: Yaniv Rosner @ 2011-11-28 10:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Yaniv Rosner, Eilon Greenstein
In-Reply-To: <1322477393-22904-1-git-send-email-yanivr@broadcom.com>

This patch contain several fixes for the BCM84833. This PHY is still not in bnx2x production, hence this patch can be considered as enhancement.

Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c |  354 ++++++++++++----------
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h  |   53 ++--
 2 files changed, 223 insertions(+), 184 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 7eabcee..6523723 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -4055,13 +4055,11 @@ static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
 
 static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
 					   struct link_params *params,
-					   u8 fiber_mode)
+					   u8 fiber_mode,
+					   u8 always_autoneg)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val16, digctrl_kx1, digctrl_kx2;
-	u8 lane;
-
-	lane = bnx2x_get_warpcore_lane(phy, params);
 
 	/* Clear XFI clock comp in non-10G single lane mode. */
 	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -4069,7 +4067,7 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
 	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
 			 MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
 
-	if (phy->req_line_speed == SPEED_AUTO_NEG) {
+	if (always_autoneg || phy->req_line_speed == SPEED_AUTO_NEG) {
 		/* SGMII Autoneg */
 		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
 				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
@@ -4080,7 +4078,7 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
 	} else {
 		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
 				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-		val16 &= 0xcfbf;
+		val16 &= 0xcebf;
 		switch (phy->req_line_speed) {
 		case SPEED_10:
 			break;
@@ -4363,7 +4361,7 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
 		vars->phy_flags |= PHY_SGMII_FLAG;
 		DP(NETIF_MSG_LINK, "Setting SGMII mode\n");
 		bnx2x_warpcore_clear_regs(phy, params, lane);
-		bnx2x_warpcore_set_sgmii_speed(phy, params, 0);
+		bnx2x_warpcore_set_sgmii_speed(phy, params, 0, 1);
 	} else {
 		switch (serdes_net_if) {
 		case PORT_HW_CFG_NET_SERDES_IF_KR:
@@ -4391,7 +4389,8 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
 				}
 				bnx2x_warpcore_set_sgmii_speed(phy,
 								params,
-								fiber_mode);
+								fiber_mode,
+								0);
 			}
 
 			break;
@@ -4404,7 +4403,8 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
 				bnx2x_warpcore_set_10G_XFI(phy, params, 0);
 			} else if (vars->line_speed == SPEED_1000) {
 				DP(NETIF_MSG_LINK, "Setting 1G Fiber\n");
-				bnx2x_warpcore_set_sgmii_speed(phy, params, 1);
+				bnx2x_warpcore_set_sgmii_speed(
+						phy, params, 1, 0);
 			}
 			/* Issue Module detection */
 			if (bnx2x_is_sfp_module_plugged(phy, params))
@@ -4541,12 +4541,6 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
 
 		/* Switch back to 4-copy registers */
 		bnx2x_set_aer_mmd(params, phy);
-		/* Global loopback, not recommended. */
-		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
-				0x4000);
 	} else {
 		/* 10G & 20G */
 		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -9349,7 +9343,7 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
 				struct bnx2x_phy *phy)
 {
-	u16 val;
+	u16 val, offset;
 
 	/* PHYC_CTL_LED_CTL */
 	bnx2x_cl45_read(bp, phy,
@@ -9384,14 +9378,22 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
 			MDIO_PMA_REG_8481_LED3_BLINK,
 			0);
 
-	bnx2x_cl45_read(bp, phy,
+	/* Configure the blink rate to ~15.9 Hz */
+	bnx2x_cl45_write(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
-	val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
+			MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
+			MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ);
 
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1;
+	else
+		offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
+
+	bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, offset, &val);
+	val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
 	bnx2x_cl45_write(bp, phy,
-			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
+			 MDIO_PMA_DEVAD, offset, val);
 
 	/* 'Interrupt Mask' */
 	bnx2x_cl45_write(bp, phy,
@@ -9404,7 +9406,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 				       struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u16 autoneg_val, an_1000_val, an_10_100_val;
+	u16 autoneg_val, an_1000_val, an_10_100_val, an_10g_val;
 	u16 tmp_req_line_speed;
 
 	tmp_req_line_speed = phy->req_line_speed;
@@ -9499,6 +9501,8 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
 				 (1<<15 | 1<<9 | 7<<0));
+		/* The PHY needs this set even for forced link. */
+		an_10_100_val |= (1<<8) | (1<<7);
 		DP(NETIF_MSG_LINK, "Setting 100M force\n");
 	}
 	if ((phy->req_line_speed == SPEED_10) &&
@@ -9536,9 +9540,17 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 			DP(NETIF_MSG_LINK, "Advertising 10G\n");
 			/* Restart autoneg for 10G*/
 
+			bnx2x_cl45_read(bp, phy,
+					MDIO_AN_DEVAD,
+					MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+					&an_10g_val);
 			bnx2x_cl45_write(bp, phy,
-				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
-				 0x3200);
+					 MDIO_AN_DEVAD,
+					 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+					 an_10g_val | 0x1000);
+			bnx2x_cl45_write(bp, phy,
+					 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
+					 0x3200);
 	} else
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD,
@@ -9570,74 +9582,95 @@ static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
 	return bnx2x_848xx_cmn_config_init(phy, params, vars);
 }
 
-
-#define PHY84833_HDSHK_WAIT 300
-static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
+#define PHY84833_CMDHDLR_WAIT 300
+#define PHY84833_CMDHDLR_MAX_ARGS 5
+static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
 				   struct link_params *params,
-				   struct link_vars *vars)
+		   u16 fw_cmd,
+		   u16 cmd_args[])
 {
 	u32 idx;
-	u32 pair_swap;
 	u16 val;
-	u16 data;
 	struct bnx2x *bp = params->bp;
-	/* Do pair swap */
-
-	/* Check for configuration. */
-	pair_swap = REG_RD(bp, params->shmem_base +
-			   offsetof(struct shmem_region,
-			dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
-		PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
-
-	if (pair_swap == 0)
-		return 0;
-
-	data = (u16)pair_swap;
-
 	/* Write CMD_OPEN_OVERRIDE to STATUS reg */
 	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_84833_TOP_CFG_SCRATCH_REG2,
-			PHY84833_CMD_OPEN_OVERRIDE);
-	for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+			MDIO_84833_CMD_HDLR_STATUS,
+			PHY84833_STATUS_CMD_OPEN_OVERRIDE);
+	for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) {
 		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-		if (val == PHY84833_CMD_OPEN_FOR_CMDS)
+				MDIO_84833_CMD_HDLR_STATUS, &val);
+		if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS)
 			break;
 		msleep(1);
 	}
-	if (idx >= PHY84833_HDSHK_WAIT) {
-		DP(NETIF_MSG_LINK, "Pairswap: FW not ready.\n");
+	if (idx >= PHY84833_CMDHDLR_WAIT) {
+		DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
 		return -EINVAL;
 	}
 
+	/* Prepare argument(s) and issue command */
+	for (idx = 0; idx < PHY84833_CMDHDLR_MAX_ARGS; idx++) {
+		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_CMD_HDLR_DATA1 + idx,
+				cmd_args[idx]);
+	}
 	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_84833_TOP_CFG_SCRATCH_REG4,
-			data);
-	/* Issue pair swap command */
-	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_84833_TOP_CFG_SCRATCH_REG0,
-			PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE);
-	for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
+			MDIO_84833_CMD_HDLR_COMMAND, fw_cmd);
+	for (idx = 0; idx < PHY84833_CMDHDLR_WAIT; idx++) {
 		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-		if ((val == PHY84833_CMD_COMPLETE_PASS) ||
-			(val == PHY84833_CMD_COMPLETE_ERROR))
+				MDIO_84833_CMD_HDLR_STATUS, &val);
+		if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) ||
+			(val == PHY84833_STATUS_CMD_COMPLETE_ERROR))
 			break;
 		msleep(1);
 	}
-	if ((idx >= PHY84833_HDSHK_WAIT) ||
-		(val == PHY84833_CMD_COMPLETE_ERROR)) {
-		DP(NETIF_MSG_LINK, "Pairswap: override failed.\n");
+	if ((idx >= PHY84833_CMDHDLR_WAIT) ||
+		(val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
+		DP(NETIF_MSG_LINK, "FW cmd failed.\n");
 		return -EINVAL;
 	}
+	/* Gather returning data */
+	for (idx = 0; idx < PHY84833_CMDHDLR_MAX_ARGS; idx++) {
+		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+				MDIO_84833_CMD_HDLR_DATA1 + idx,
+				&cmd_args[idx]);
+	}
 	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_84833_TOP_CFG_SCRATCH_REG2,
-			PHY84833_CMD_CLEAR_COMPLETE);
-	DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data);
+			MDIO_84833_CMD_HDLR_STATUS,
+			PHY84833_STATUS_CMD_CLEAR_COMPLETE);
 	return 0;
 }
 
 
+static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
+				   struct link_params *params,
+				   struct link_vars *vars)
+{
+	u32 pair_swap;
+	u16 data[PHY84833_CMDHDLR_MAX_ARGS];
+	int status;
+	struct bnx2x *bp = params->bp;
+
+	/* Check for configuration. */
+	pair_swap = REG_RD(bp, params->shmem_base +
+			   offsetof(struct shmem_region,
+			dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
+		PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
+
+	if (pair_swap == 0)
+		return 0;
+
+	/* Only the second argument is used for this command */
+	data[1] = (u16)pair_swap;
+
+	status = bnx2x_84833_cmd_hdlr(phy, params,
+		PHY84833_CMD_SET_PAIR_SWAP, data);
+	if (status == 0)
+		DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data[1]);
+
+	return status;
+}
+
 static u8 bnx2x_84833_get_reset_gpios(struct bnx2x *bp,
 				      u32 shmem_base_path[],
 				      u32 chip_id)
@@ -9700,24 +9733,6 @@ static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
 	return 0;
 }
 
-static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
-						u32 shmem_base_path[],
-						u32 chip_id)
-{
-	u8 reset_gpios;
-
-	reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
-
-	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
-	udelay(10);
-	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
-	msleep(800);
-	DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
-		reset_gpios);
-
-	return 0;
-}
-
 #define PHY84833_CONSTANT_LATENCY 1193
 static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 				   struct link_params *params,
@@ -9726,8 +9741,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 	struct bnx2x *bp = params->bp;
 	u8 port, initialize = 1;
 	u16 val;
-	u16 temp;
-	u32 actual_phy_selection, cms_enable, idx;
+	u32 actual_phy_selection, cms_enable;
+	u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS];
 	int rc = 0;
 
 	msleep(1);
@@ -9746,6 +9761,13 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 		bnx2x_cl45_write(bp, phy,
 				MDIO_PMA_DEVAD,
 				MDIO_PMA_REG_CTRL, 0x8000);
+	}
+
+	bnx2x_wait_reset_complete(bp, phy, params);
+
+	/* Wait for GPHY to come out of reset */
+	msleep(50);
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
 		/* Bring PHY out of super isolate mode */
 		bnx2x_cl45_read(bp, phy,
 				MDIO_CTL_DEVAD,
@@ -9754,26 +9776,19 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 		bnx2x_cl45_write(bp, phy,
 				MDIO_CTL_DEVAD,
 				MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
-	}
-
-	bnx2x_wait_reset_complete(bp, phy, params);
-
-	/* Wait for GPHY to come out of reset */
-	msleep(50);
-
-	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
 		bnx2x_84833_pair_swap_cfg(phy, params, vars);
-
-	/*
-	 * BCM84823 requires that XGXS links up first @ 10G for normal behavior
-	 */
-	temp = vars->line_speed;
-	vars->line_speed = SPEED_10000;
-	bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
-	bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
-	vars->line_speed = temp;
-
-	/* Set dual-media configuration according to configuration */
+	} else {
+		/*
+		 * BCM84823 requires that XGXS links up first @ 10G for normal
+		 * behavior.
+		 */
+		u16 temp;
+		temp = vars->line_speed;
+		vars->line_speed = SPEED_10000;
+		bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
+		bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
+		vars->line_speed = temp;
+	}
 
 	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
 			MDIO_CTL_REG_84823_MEDIA, &val);
@@ -9821,64 +9836,18 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 
 	/* AutogrEEEn */
 	if (params->feature_config_flags &
-		FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
-		/* Ensure that f/w is ready */
-		for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
-			bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-					MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-			if (val == PHY84833_CMD_OPEN_FOR_CMDS)
-				break;
-			usleep_range(1000, 1000);
-		}
-		if (idx >= PHY84833_HDSHK_WAIT) {
-			DP(NETIF_MSG_LINK, "AutogrEEEn: FW not ready.\n");
-			return -EINVAL;
-		}
-
-		/* Select EEE mode */
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG3,
-				0x2);
-
-		/* Set Idle and Latency */
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG4,
-				PHY84833_CONSTANT_LATENCY + 1);
-
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_DATA3_REG,
-				PHY84833_CONSTANT_LATENCY + 1);
-
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_DATA4_REG,
-				PHY84833_CONSTANT_LATENCY);
-
-		/* Send EEE instruction to command register */
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-				MDIO_84833_TOP_CFG_SCRATCH_REG0,
-				PHY84833_DIAG_CMD_SET_EEE_MODE);
-
-		/* Ensure that the command has completed */
-		for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
-			bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-					MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
-			if ((val == PHY84833_CMD_COMPLETE_PASS) ||
-				(val == PHY84833_CMD_COMPLETE_ERROR))
-				break;
-			usleep_range(1000, 1000);
-		}
-		if ((idx >= PHY84833_HDSHK_WAIT) ||
-			(val == PHY84833_CMD_COMPLETE_ERROR)) {
-			DP(NETIF_MSG_LINK, "AutogrEEEn: command failed.\n");
-			return -EINVAL;
-		}
-
-		/* Reset command handler */
-		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			    MDIO_84833_TOP_CFG_SCRATCH_REG2,
-			    PHY84833_CMD_CLEAR_COMPLETE);
-	}
+		FEATURE_CONFIG_AUTOGREEEN_ENABLED)
+		cmd_args[0] = 0x2;
+	else
+		cmd_args[0] = 0x0;
 
+	cmd_args[1] = 0x0;
+	cmd_args[2] = PHY84833_CONSTANT_LATENCY + 1;
+	cmd_args[3] = PHY84833_CONSTANT_LATENCY;
+	rc = bnx2x_84833_cmd_hdlr(phy, params,
+		PHY84833_CMD_SET_EEE_MODE, cmd_args);
+	if (rc != 0)
+		DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
 	if (initialize)
 		rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
 	else
@@ -12368,6 +12337,63 @@ static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
 	return 0;
 }
 
+static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
+						u32 shmem_base_path[],
+						u32 shmem2_base_path[],
+						u8 phy_index,
+						u32 chip_id)
+{
+	u8 reset_gpios;
+	struct bnx2x_phy phy;
+	u32 shmem_base, shmem2_base, cnt;
+	s8 port = 0;
+	u16 val;
+
+	reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
+	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
+	udelay(10);
+	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
+	DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
+		reset_gpios);
+	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+		/* This PHY is for E2 and E3. */
+		shmem_base = shmem_base_path[port];
+		shmem2_base = shmem2_base_path[port];
+		/* Extract the ext phy address for the port */
+		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
+				       0, &phy) !=
+		    0) {
+			DP(NETIF_MSG_LINK, "populate_phy failed\n");
+			return -EINVAL;
+		}
+
+		/* Wait for FW completing its initialization. */
+		for (cnt = 0; cnt < 1000; cnt++) {
+			bnx2x_cl45_read(bp, &phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_CTRL, &val);
+			if (!(val & (1<<15)))
+				break;
+			msleep(1);
+		}
+		if (cnt >= 1000)
+			DP(NETIF_MSG_LINK,
+				"84833 Cmn reset timeout (%d)\n", port);
+
+		/* Put the port in super isolate mode. */
+		bnx2x_cl45_read(bp, &phy,
+				MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
+		val |= MDIO_84833_SUPER_ISOLATE;
+		bnx2x_cl45_write(bp, &phy,
+				MDIO_CTL_DEVAD,
+				MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+	}
+
+	return 0;
+}
+
+
 static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
 				     u32 shmem2_base_path[], u8 phy_index,
 				     u32 ext_phy_type, u32 chip_id)
@@ -12402,7 +12428,9 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
 		 * GPIO3's are linked, and so both need to be toggled
 		 * to obtain required 2us pulse.
 		 */
-		rc = bnx2x_84833_common_init_phy(bp, shmem_base_path, chip_id);
+		rc = bnx2x_84833_common_init_phy(bp, shmem_base_path,
+						shmem2_base_path,
+						phy_index, chip_id);
 		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
 		rc = -EINVAL;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index d5a0dde..44609de 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -6835,11 +6835,13 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER	0x0000
 #define MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER		0x0100
 #define MDIO_CTL_REG_84823_MEDIA_FIBER_1G			0x1000
-#define MDIO_CTL_REG_84823_USER_CTRL_REG		0x4005
-#define MDIO_CTL_REG_84823_USER_CTRL_CMS		0x0080
-
-#define MDIO_PMA_REG_84823_CTL_LED_CTL_1		0xa8e3
-#define MDIO_PMA_REG_84823_LED3_STRETCH_EN		0x0080
+#define MDIO_CTL_REG_84823_USER_CTRL_REG			0x4005
+#define MDIO_CTL_REG_84823_USER_CTRL_CMS			0x0080
+#define MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH		0xa82b
+#define MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ	0x2f
+#define MDIO_PMA_REG_84823_CTL_LED_CTL_1			0xa8e3
+#define MDIO_PMA_REG_84833_CTL_LED_CTL_1			0xa8ec
+#define MDIO_PMA_REG_84823_LED3_STRETCH_EN			0x0080
 
 /* BCM84833 only */
 #define MDIO_84833_TOP_CFG_XGPHY_STRAP1			0x401a
@@ -6850,26 +6852,35 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_84833_TOP_CFG_SCRATCH_REG2			0x4007
 #define MDIO_84833_TOP_CFG_SCRATCH_REG3			0x4008
 #define MDIO_84833_TOP_CFG_SCRATCH_REG4			0x4009
-#define MDIO_84833_TOP_CFG_DATA3_REG			0x4011
-#define MDIO_84833_TOP_CFG_DATA4_REG			0x4012
+#define MDIO_84833_TOP_CFG_SCRATCH_REG26		0x4037
+#define MDIO_84833_TOP_CFG_SCRATCH_REG27		0x4038
+#define MDIO_84833_TOP_CFG_SCRATCH_REG28		0x4039
+#define MDIO_84833_TOP_CFG_SCRATCH_REG29		0x403a
+#define MDIO_84833_TOP_CFG_SCRATCH_REG30		0x403b
+#define MDIO_84833_TOP_CFG_SCRATCH_REG31		0x403c
+#define MDIO_84833_CMD_HDLR_COMMAND	MDIO_84833_TOP_CFG_SCRATCH_REG0
+#define MDIO_84833_CMD_HDLR_STATUS	MDIO_84833_TOP_CFG_SCRATCH_REG26
+#define MDIO_84833_CMD_HDLR_DATA1	MDIO_84833_TOP_CFG_SCRATCH_REG27
+#define MDIO_84833_CMD_HDLR_DATA2	MDIO_84833_TOP_CFG_SCRATCH_REG28
+#define MDIO_84833_CMD_HDLR_DATA3	MDIO_84833_TOP_CFG_SCRATCH_REG29
+#define MDIO_84833_CMD_HDLR_DATA4	MDIO_84833_TOP_CFG_SCRATCH_REG30
+#define MDIO_84833_CMD_HDLR_DATA5	MDIO_84833_TOP_CFG_SCRATCH_REG31
 
 /* Mailbox command set used by 84833. */
-#define PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE		0x2
+#define PHY84833_CMD_SET_PAIR_SWAP			0x8001
+#define PHY84833_CMD_GET_EEE_MODE			0x8008
+#define PHY84833_CMD_SET_EEE_MODE			0x8009
 /* Mailbox status set used by 84833. */
-#define PHY84833_CMD_RECEIVED				0x0001
-#define PHY84833_CMD_IN_PROGRESS			0x0002
-#define PHY84833_CMD_COMPLETE_PASS			0x0004
-#define PHY84833_CMD_COMPLETE_ERROR			0x0008
-#define PHY84833_CMD_OPEN_FOR_CMDS			0x0010
-#define PHY84833_CMD_SYSTEM_BOOT			0x0020
-#define PHY84833_CMD_NOT_OPEN_FOR_CMDS			0x0040
-#define PHY84833_CMD_CLEAR_COMPLETE			0x0080
-#define PHY84833_CMD_OPEN_OVERRIDE			0xa5a5
-
+#define PHY84833_STATUS_CMD_RECEIVED			0x0001
+#define PHY84833_STATUS_CMD_IN_PROGRESS			0x0002
+#define PHY84833_STATUS_CMD_COMPLETE_PASS		0x0004
+#define PHY84833_STATUS_CMD_COMPLETE_ERROR		0x0008
+#define PHY84833_STATUS_CMD_OPEN_FOR_CMDS		0x0010
+#define PHY84833_STATUS_CMD_SYSTEM_BOOT			0x0020
+#define PHY84833_STATUS_CMD_NOT_OPEN_FOR_CMDS		0x0040
+#define PHY84833_STATUS_CMD_CLEAR_COMPLETE		0x0080
+#define PHY84833_STATUS_CMD_OPEN_OVERRIDE		0xa5a5
 
-/* 84833 F/W Feature Commands */
-#define PHY84833_DIAG_CMD_GET_EEE_MODE			0x27
-#define PHY84833_DIAG_CMD_SET_EEE_MODE			0x28
 
 /* Warpcore clause 45 addressing */
 #define MDIO_WC_DEVAD					0x3
-- 
1.7.7.1

^ permalink raw reply related

* [net-next v2 8/9] bnx2x: Cosmetic changes
From: Yaniv Rosner @ 2011-11-28 10:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Yaniv Rosner, Eilon Greenstein
In-Reply-To: <1322477393-22904-1-git-send-email-yanivr@broadcom.com>

Fix spelling, alignment, empty lines, relocate the is_4_port_mode function, and split bnx2x_link_status_update function.

Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
 .../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c    |    2 +-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c   |  413 ++++++++++----------
 2 files changed, 199 insertions(+), 216 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index f1bf1f5..c679ed9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -352,7 +352,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		DP(NETIF_MSG_LINK, "Unsupported port type\n");
 		return -EINVAL;
 	}
-	/* Save new config in case command complete successuly */
+	/* Save new config in case command complete successully */
 	new_multi_phy_config = bp->link_params.multi_phy_config;
 	/* Get the new cfg_idx */
 	cfg_idx = bnx2x_get_link_cfg_idx(bp);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index cc7dbbe..d745054 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -27,7 +27,6 @@
 #include "bnx2x.h"
 #include "bnx2x_cmn.h"
 
-
 /********************************************************/
 #define ETH_HLEN			14
 /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
@@ -255,17 +254,16 @@
 #define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE		50
 #define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE	384
 
-
 /* only for E3B0*/
 #define PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR			304
 #define PFC_E3B0_4P_BRB_FULL_LB_XON_THR			384
-#define PFC_E3B0_4P_LB_GUART				120
+#define PFC_E3B0_4P_LB_GUART		120
 
 #define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART		120
-#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST		80
+#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST	80
 
 #define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART		80
-#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST		120
+#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST	120
 
 /* Pause defines*/
 #define DEFAULT_E3B0_BRB_FULL_LB_XOFF_THR			330
@@ -906,15 +904,15 @@ static int bnx2x_ets_e3b0_get_total_bw(
 	if ((1 == is_bw_cos_exist) && (100 != *total_bw)) {
 		if (0 == *total_bw) {
 			DP(NETIF_MSG_LINK,
-			   "bnx2x_ets_E3B0_config toatl BW shouldn't be 0\n");
+			   "bnx2x_ets_E3B0_config total BW shouldn't be 0\n");
 			return -EINVAL;
 		}
 		DP(NETIF_MSG_LINK,
-		   "bnx2x_ets_E3B0_config toatl BW should be 100\n");
-		/**
-		*   We can handle a case whre the BW isn't 100 this can happen
-		*   if the TC are joined.
-		*/
+		   "bnx2x_ets_E3B0_config total BW should be 100\n");
+		/*
+		 * We can handle a case whre the BW isn't 100 this can happen
+		 * if the TC are joined.
+		 */
 	}
 	return 0;
 }
@@ -954,7 +952,7 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
 
 	if (pri > max_num_of_cos) {
 		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
-			       "parameter Illegal strict priority\n");
+		   "parameter Illegal strict priority\n");
 	    return -EINVAL;
 	}
 
@@ -1152,9 +1150,9 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
 		return -EINVAL;
 	}
 
-	/**
-	 *  Upper bound is set according to current link speed (min_w_val
-	 *  should be the same for upper bound and COS credit val).
+	/*
+	 * Upper bound is set according to current link speed (min_w_val
+	 * should be the same for upper bound and COS credit val).
 	 */
 	bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
 	bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
@@ -1163,7 +1161,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
 	for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
 		if (bnx2x_cos_state_bw == ets_params->cos[cos_entry].state) {
 			cos_bw_bitmap |= (1 << cos_entry);
-			/**
+			/*
 			 * The function also sets the BW in HW(not the mappin
 			 * yet)
 			 */
@@ -1339,7 +1337,6 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
 /******************************************************************/
 /*			PFC section				  */
 /******************************************************************/
-
 static void bnx2x_update_pfc_xmac(struct link_params *params,
 				  struct link_vars *vars,
 				  u8 is_lb)
@@ -1476,6 +1473,18 @@ static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
 
 	udelay(40);
 }
+static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
+{
+	u32 port4mode_ovwr_val;
+	/* Check 4-port override enabled */
+	port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
+	if (port4mode_ovwr_val & (1<<0)) {
+		/* Return 4-port mode override value */
+		return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
+	}
+	/* Return 4-port mode from input pin */
+	return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
+}
 
 static void bnx2x_emac_init(struct link_params *params,
 			    struct link_vars *vars)
@@ -1642,31 +1651,18 @@ static void bnx2x_umac_enable(struct link_params *params,
 
 }
 
-static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
-{
-	u32 port4mode_ovwr_val;
-	/* Check 4-port override enabled */
-	port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
-	if (port4mode_ovwr_val & (1<<0)) {
-		/* Return 4-port mode override value */
-		return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
-	}
-	/* Return 4-port mode from input pin */
-	return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
-}
-
 /* Define the XMAC mode */
 static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
 {
 	struct bnx2x *bp = params->bp;
 	u32 is_port4mode = bnx2x_is_4_port_mode(bp);
 
-	/**
-	* In 4-port mode, need to set the mode only once, so if XMAC is
-	* already out of reset, it means the mode has already been set,
-	* and it must not* reset the XMAC again, since it controls both
-	* ports of the path
-	**/
+	/*
+	 * In 4-port mode, need to set the mode only once, so if XMAC is
+	 * already out of reset, it means the mode has already been set,
+	 * and it must not* reset the XMAC again, since it controls both
+	 * ports of the path
+	 */
 
 	if ((CHIP_NUM(bp) == CHIP_NUM_57840) &&
 	    (REG_RD(bp, MISC_REG_RESET_REG_2) &
@@ -1784,6 +1780,7 @@ static int bnx2x_xmac_enable(struct link_params *params,
 
 	return 0;
 }
+
 static int bnx2x_emac_enable(struct link_params *params,
 			     struct link_vars *vars, u8 lb)
 {
@@ -2040,7 +2037,6 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
 }
 
-
 /* PFC BRB internal port configuration params */
 struct bnx2x_pfc_brb_threshold_val {
 	u32 pause_xoff;
@@ -2085,57 +2081,57 @@ static int bnx2x_pfc_brb_get_config_params(
 		config_val->default_class0.pause_xoff =
 			DEFAULT0_E2_BRB_MAC_PAUSE_XOFF_THR;
 		config_val->default_class0.pause_xon =
-		    DEFAULT0_E2_BRB_MAC_PAUSE_XON_THR;
+			DEFAULT0_E2_BRB_MAC_PAUSE_XON_THR;
 		config_val->default_class0.full_xoff =
-		    DEFAULT0_E2_BRB_MAC_FULL_XOFF_THR;
+			DEFAULT0_E2_BRB_MAC_FULL_XOFF_THR;
 		config_val->default_class0.full_xon =
-		    DEFAULT0_E2_BRB_MAC_FULL_XON_THR;
+			DEFAULT0_E2_BRB_MAC_FULL_XON_THR;
 		/*  pause able*/
 		config_val->pauseable_th.pause_xoff =
-		    PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+			PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
 		config_val->pauseable_th.pause_xon =
-		    PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
+			PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
 		config_val->pauseable_th.full_xoff =
-		    PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
+			PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
 		config_val->pauseable_th.full_xon =
-		    PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
+			PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
 		/* non pause able*/
 		config_val->non_pauseable_th.pause_xoff =
-		    PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+			PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
 		config_val->non_pauseable_th.pause_xon =
-		    PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+			PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
 		config_val->non_pauseable_th.full_xoff =
-		    PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+			PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
 		config_val->non_pauseable_th.full_xon =
-		    PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+			PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
 	} else if (CHIP_IS_E3A0(bp)) {
 		/*  class0 defaults */
 		config_val->default_class0.pause_xoff =
 			DEFAULT0_E3A0_BRB_MAC_PAUSE_XOFF_THR;
 		config_val->default_class0.pause_xon =
-		    DEFAULT0_E3A0_BRB_MAC_PAUSE_XON_THR;
+			DEFAULT0_E3A0_BRB_MAC_PAUSE_XON_THR;
 		config_val->default_class0.full_xoff =
-		    DEFAULT0_E3A0_BRB_MAC_FULL_XOFF_THR;
+			DEFAULT0_E3A0_BRB_MAC_FULL_XOFF_THR;
 		config_val->default_class0.full_xon =
-		    DEFAULT0_E3A0_BRB_MAC_FULL_XON_THR;
+			DEFAULT0_E3A0_BRB_MAC_FULL_XON_THR;
 		/*  pause able */
 		config_val->pauseable_th.pause_xoff =
-		    PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
+			PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
 		config_val->pauseable_th.pause_xon =
-		    PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
+			PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
 		config_val->pauseable_th.full_xoff =
-		    PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
+			PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
 		config_val->pauseable_th.full_xon =
-		    PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
+			PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
 		/* non pause able*/
 		config_val->non_pauseable_th.pause_xoff =
-		    PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+			PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
 		config_val->non_pauseable_th.pause_xon =
-		    PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+			PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
 		config_val->non_pauseable_th.full_xoff =
-		    PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+			PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
 		config_val->non_pauseable_th.full_xon =
-		    PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+			PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
 	} else if (CHIP_IS_E3B0(bp)) {
 		/*  class0 defaults */
 		config_val->default_class0.pause_xoff =
@@ -2148,7 +2144,7 @@ static int bnx2x_pfc_brb_get_config_params(
 		    DEFAULT0_E3B0_BRB_MAC_FULL_XON_THR;
 
 		if (params->phy[INT_PHY].flags &
-			FLAGS_4_PORT_MODE) {
+		    FLAGS_4_PORT_MODE) {
 			config_val->pauseable_th.pause_xoff =
 				PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
 			config_val->pauseable_th.pause_xon =
@@ -2170,21 +2166,21 @@ static int bnx2x_pfc_brb_get_config_params(
 			config_val->pauseable_th.pause_xoff =
 				PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
 			config_val->pauseable_th.pause_xon =
-		    PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
-		config_val->pauseable_th.full_xoff =
-		    PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
-		config_val->pauseable_th.full_xon =
-			PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
-		/* non pause able*/
-		config_val->non_pauseable_th.pause_xoff =
-		    PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
-		config_val->non_pauseable_th.pause_xon =
-		    PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
-		config_val->non_pauseable_th.full_xoff =
-		    PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
-		config_val->non_pauseable_th.full_xon =
-		    PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
-	    }
+				PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
+			config_val->pauseable_th.full_xoff =
+				PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
+			config_val->pauseable_th.full_xon =
+				PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
+			/* non pause able*/
+			config_val->non_pauseable_th.pause_xoff =
+				PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
+			config_val->non_pauseable_th.pause_xon =
+				PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
+			config_val->non_pauseable_th.full_xoff =
+				PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
+			config_val->non_pauseable_th.full_xon =
+				PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
+		}
 	} else
 	    return -EINVAL;
 
@@ -2278,7 +2274,7 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
 	struct bnx2x *bp = params->bp;
 	struct bnx2x_pfc_brb_th_val config_val = { {0} };
 	struct bnx2x_pfc_brb_threshold_val *reg_th_config =
-	    &config_val.pauseable_th;
+		&config_val.pauseable_th;
 	struct bnx2x_pfc_brb_e3b0_val e3b0_val = {0};
 	const int set_pfc = params->feature_config_flags &
 		FEATURE_CONFIG_PFC_ENABLED;
@@ -2334,34 +2330,35 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
 			reg_th_config = &config_val.non_pauseable_th;
 	} else
 		reg_th_config = &config_val.default_class1;
-		/*
-		 * The number of free blocks below which the pause signal to
-		 * class 1 of MAC #n is asserted. n=0,1
-		**/
-		REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
-		       BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
-		       reg_th_config->pause_xoff);
-		/*
-		 * The number of free blocks above which the pause signal to
-		 * class 1 of MAC #n is de-asserted. n=0,1
-		 */
-		REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
-		       BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
-		       reg_th_config->pause_xon);
-		/*
-		 * The number of free blocks below which the full signal to
-		 * class 1 of MAC #n is asserted. n=0,1
-		 */
-		REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
-		       BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
-		       reg_th_config->full_xoff);
-		/*
-		 * The number of free blocks above which the full signal to
-		 * class 1 of MAC #n is de-asserted. n=0,1
-		 */
-		REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
-		       BRB1_REG_FULL_1_XON_THRESHOLD_0,
-		       reg_th_config->full_xon);
+	/*
+	 * The number of free blocks below which the pause signal to
+	 * class 1 of MAC #n is asserted. n=0,1
+	 */
+	REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
+	       BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
+	       reg_th_config->pause_xoff);
+
+	/*
+	 * The number of free blocks above which the pause signal to
+	 * class 1 of MAC #n is de-asserted. n=0,1
+	 */
+	REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
+	       BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
+	       reg_th_config->pause_xon);
+	/*
+	 * The number of free blocks below which the full signal to
+	 * class 1 of MAC #n is asserted. n=0,1
+	 */
+	REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
+	       BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
+	       reg_th_config->full_xoff);
+	/*
+	 * The number of free blocks above which the full signal to
+	 * class 1 of MAC #n is de-asserted. n=0,1
+	 */
+	REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
+	       BRB1_REG_FULL_1_XON_THRESHOLD_0,
+	       reg_th_config->full_xon);
 
 	if (CHIP_IS_E3B0(bp)) {
 		bnx2x_pfc_brb_get_e3b0_config_params(
@@ -2370,81 +2367,75 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
 			pfc_params,
 			pfc_enabled);
 
-			/*Should be done by init tool */
-			/*
-			* BRB_empty_for_dup = BRB1_REG_BRB_EMPTY_THRESHOLD
-			* reset value
-			* 944
-			*/
 		REG_WR(bp, BRB1_REG_PER_CLASS_GUARANTY_MODE,
 			   e3b0_val.per_class_guaranty_mode);
 
-			/**
-			 * The hysteresis on the guarantied buffer space for the Lb port
-			 * before signaling XON.
-			 **/
+		/*
+		 * The hysteresis on the guarantied buffer space for the Lb
+		 * port before signaling XON.
+		 */
 		REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST,
 			   e3b0_val.lb_guarantied_hyst);
-			/**
-			 * The number of free blocks below which the full signal to the
-			 * LB port is asserted.
-			*/
+
+		/*
+		 * The number of free blocks below which the full signal to the
+		 * LB port is asserted.
+		 */
 		REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
-			e3b0_val.full_lb_xoff_th);
-			/**
-			 * The number of free blocks above which the full signal to the
-			 * LB port is de-asserted.
-			*/
-			REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
-				   e3b0_val.full_lb_xon_threshold);
-			/**
-			* The number of blocks guarantied for the MAC #n port. n=0,1
-			*/
-
-			/*The number of blocks guarantied for the LB port.*/
-			REG_WR(bp, BRB1_REG_LB_GUARANTIED,
-			       e3b0_val.lb_guarantied);
-
-			/**
-			 * The number of blocks guarantied for the MAC #n port.
-			*/
-			REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
-				   2 * e3b0_val.mac_0_class_t_guarantied);
-			REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
-				   2 * e3b0_val.mac_1_class_t_guarantied);
-			/**
-			 * The number of blocks guarantied for class #t in MAC0. t=0,1
-			*/
-			REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
-			       e3b0_val.mac_0_class_t_guarantied);
-			REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
-			       e3b0_val.mac_0_class_t_guarantied);
-			/**
-			 * The hysteresis on the guarantied buffer space for class in
-			 * MAC0.  t=0,1
-			*/
-			REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
-			       e3b0_val.mac_0_class_t_guarantied_hyst);
-			REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
-			       e3b0_val.mac_0_class_t_guarantied_hyst);
-
-			/**
-			 * The number of blocks guarantied for class #t in MAC1.t=0,1
-			*/
-			REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
-			       e3b0_val.mac_1_class_t_guarantied);
-			REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
-			       e3b0_val.mac_1_class_t_guarantied);
-			/**
-			 * The hysteresis on the guarantied buffer space for class #t
-			* in MAC1.  t=0,1
-			*/
-			REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
-			       e3b0_val.mac_1_class_t_guarantied_hyst);
-			REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
-			       e3b0_val.mac_1_class_t_guarantied_hyst);
-
-	    }
+		       e3b0_val.full_lb_xoff_th);
+		/*
+		 * The number of free blocks above which the full signal to the
+		 * LB port is de-asserted.
+		 */
+		REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
+		       e3b0_val.full_lb_xon_threshold);
+		/*
+		 * The number of blocks guarantied for the MAC #n port. n=0,1
+		 */
+
+		/* The number of blocks guarantied for the LB port.*/
+		REG_WR(bp, BRB1_REG_LB_GUARANTIED,
+		       e3b0_val.lb_guarantied);
+
+		/*
+		 * The number of blocks guarantied for the MAC #n port.
+		 */
+		REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
+		       2 * e3b0_val.mac_0_class_t_guarantied);
+		REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
+		       2 * e3b0_val.mac_1_class_t_guarantied);
+		/*
+		 * The number of blocks guarantied for class #t in MAC0. t=0,1
+		 */
+		REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
+		       e3b0_val.mac_0_class_t_guarantied);
+		REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
+		       e3b0_val.mac_0_class_t_guarantied);
+		/*
+		 * The hysteresis on the guarantied buffer space for class in
+		 * MAC0.  t=0,1
+		 */
+		REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
+		       e3b0_val.mac_0_class_t_guarantied_hyst);
+		REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
+		       e3b0_val.mac_0_class_t_guarantied_hyst);
+
+		/*
+		 * The number of blocks guarantied for class #t in MAC1.t=0,1
+		 */
+		REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
+		       e3b0_val.mac_1_class_t_guarantied);
+		REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
+		       e3b0_val.mac_1_class_t_guarantied);
+		/*
+		 * The hysteresis on the guarantied buffer space for class #t
+		 * in MAC1.  t=0,1
+		 */
+		REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
+		       e3b0_val.mac_1_class_t_guarantied_hyst);
+		REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
+		       e3b0_val.mac_1_class_t_guarantied_hyst);
+	}
 
 	return bnx2x_status;
 }
@@ -2646,7 +2637,6 @@ int bnx2x_update_pfc(struct link_params *params,
 			bnx2x_emac_enable(params, vars, 0);
 			return bnx2x_status;
 		}
-
 		if (CHIP_IS_E2(bp))
 			bnx2x_update_pfc_bmac2(params, vars, bmac_loopback);
 		else
@@ -3166,7 +3156,6 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 		DP(NETIF_MSG_LINK, "write phy register failed\n");
 		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 		rc = -EFAULT;
-
 	} else {
 		/* data */
 		tmp = ((phy->addr << 21) | (devad << 16) | val |
@@ -3203,8 +3192,6 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 			       EMAC_MDIO_STATUS_10MB);
 	return rc;
 }
-
-
 /******************************************************************/
 /*			BSC access functions from E3	          */
 /******************************************************************/
@@ -3452,7 +3439,7 @@ static void bnx2x_set_aer_mmd(struct link_params *params,
 		aer_val = 0x3800 + offset - 1;
 	else
 		aer_val = 0x3800 + offset;
-	DP(NETIF_MSG_LINK, "Set AER to 0x%x\n", aer_val);
+
 	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
 			  MDIO_AER_BLOCK_AER_REG, aer_val);
 
@@ -4154,9 +4141,7 @@ static void bnx2x_warpcore_reset_lane(struct bnx2x *bp,
 	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
 			 MDIO_WC_REG_DIGITAL5_MISC6, &val);
 }
-
-
-	/* Clear SFI/XFI link settings registers */
+/* Clear SFI/XFI link settings registers */
 static void bnx2x_warpcore_clear_regs(struct bnx2x_phy *phy,
 				      struct link_params *params,
 				      u16 lane)
@@ -4557,25 +4542,14 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
 }
 
 
-void bnx2x_link_status_update(struct link_params *params,
-			      struct link_vars *vars)
+void bnx2x_sync_link(struct link_params *params,
+			   struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u8 link_10g_plus;
-	u8 port = params->port;
-	u32 sync_offset, media_types;
-	/* Update PHY configuration */
-	set_phy_vars(params, vars);
-
-	vars->link_status = REG_RD(bp, params->shmem_base +
-				   offsetof(struct shmem_region,
-					    port_mb[port].link_status));
-
-	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
-	vars->phy_flags = PHY_XGXS_FLAG;
 	if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
 		vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
-
+	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
 	if (vars->link_up) {
 		DP(NETIF_MSG_LINK, "phy link up\n");
 
@@ -4670,7 +4644,23 @@ void bnx2x_link_status_update(struct link_params *params,
 		if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
 			vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
 	}
+}
 
+void bnx2x_link_status_update(struct link_params *params,
+			      struct link_vars *vars)
+{
+	struct bnx2x *bp = params->bp;
+	u8 port = params->port;
+	u32 sync_offset, media_types;
+	/* Update PHY configuration */
+	set_phy_vars(params, vars);
+
+	vars->link_status = REG_RD(bp, params->shmem_base +
+				   offsetof(struct shmem_region,
+					    port_mb[port].link_status));
+
+	vars->phy_flags = PHY_XGXS_FLAG;
+	bnx2x_sync_link(params, vars);
 	/* Sync media type */
 	sync_offset = params->shmem_base +
 			offsetof(struct shmem_region,
@@ -4709,7 +4699,6 @@ void bnx2x_link_status_update(struct link_params *params,
 		 vars->line_speed, vars->duplex, vars->flow_ctrl);
 }
 
-
 static void bnx2x_set_master_ln(struct link_params *params,
 				struct bnx2x_phy *phy)
 {
@@ -4783,11 +4772,8 @@ static void bnx2x_set_swap_lanes(struct link_params *params,
 	 *  Each two bits represents a lane number:
 	 *  No swap is 0123 => 0x1b no need to enable the swap
 	 */
-	u16 ser_lane, rx_lane_swap, tx_lane_swap;
+	u16 rx_lane_swap, tx_lane_swap;
 
-	ser_lane = ((params->lane_config &
-		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-		    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 	rx_lane_swap = ((params->lane_config &
 			 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
 			PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
@@ -5463,7 +5449,6 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
 				      struct link_params *params,
 				      struct link_vars *vars)
 {
-
 	struct bnx2x *bp = params->bp;
 
 	u16 gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask;
@@ -5510,9 +5495,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
 				     struct link_params *params,
 				     struct link_vars *vars)
 {
-
 	struct bnx2x *bp = params->bp;
-
 	u8 lane;
 	u16 gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL;
 	int rc = 0;
@@ -6785,7 +6768,6 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 	return rc;
 }
 
-
 /*****************************************************************************/
 /*			    External Phy section			     */
 /*****************************************************************************/
@@ -9155,13 +9137,13 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 			DP(NETIF_MSG_LINK,
 			   "8727 Power fault has been detected on port %d\n",
 			   oc_port);
-			netdev_err(bp->dev, "Error:  Power fault on Port %d has"
-					    " been detected and the power to "
-					    "that SFP+ module has been removed"
-					    " to prevent failure of the card."
-					    " Please remove the SFP+ module and"
-					    " restart the system to clear this"
-					    " error.\n",
+			netdev_err(bp->dev, "Error: Power fault on Port %d has "
+					    "been detected and the power to "
+					    "that SFP+ module has been removed "
+					    "to prevent failure of the card. "
+					    "Please remove the SFP+ module and "
+					    "restart the system to clear this "
+					    "error.\n",
 			 oc_port);
 			/* Disable all RX_ALARMs except for mod_abs */
 			bnx2x_cl45_write(bp, phy,
@@ -10234,8 +10216,10 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "54618SE cfg init\n");
 	usleep_range(1000, 1000);
 
-	/* This works with E3 only, no need to check the chip
-	   before determining the port. */
+	/*
+	 * This works with E3 only, no need to check the chip
+	 * before determining the port.
+	 */
 	port = params->port;
 
 	cfg_pin = (REG_RD(bp, params->shmem_base +
@@ -11666,7 +11650,7 @@ u32 bnx2x_phy_selection(struct link_params *params)
 
 int bnx2x_phy_probe(struct link_params *params)
 {
-	u8 phy_index, actual_phy_idx, link_cfg_idx;
+	u8 phy_index, actual_phy_idx;
 	u32 phy_config_swapped, sync_offset, media_types;
 	struct bnx2x *bp = params->bp;
 	struct bnx2x_phy *phy;
@@ -11677,7 +11661,6 @@ int bnx2x_phy_probe(struct link_params *params)
 
 	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
 	      phy_index++) {
-		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
 		actual_phy_idx = phy_index;
 		if (phy_config_swapped) {
 			if (phy_index == EXT_PHY1)
-- 
1.7.7.1

^ permalink raw reply related

* [net-next v2 9/9] bnx2x: Change value comparison order
From: Yaniv Rosner @ 2011-11-28 10:49 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Yaniv Rosner, Eilon Greenstein
In-Reply-To: <1322477393-22904-1-git-send-email-yanivr@broadcom.com>

Change comparison order such that the variable will come before the compared value.

Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c |   46 +++++++++++-----------
 1 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index d745054..4df9505 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -466,7 +466,7 @@ static u32 bnx2x_ets_get_min_w_val_nig(const struct link_vars *vars)
 	u32 min_w_val = 0;
 	/* Calculate min_w_val.*/
 	if (vars->link_up) {
-		if (SPEED_20000 == vars->line_speed)
+		if (vars->line_speed == SPEED_20000)
 			min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
 		else
 			min_w_val = ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
@@ -516,7 +516,7 @@ static void bnx2x_ets_e3b0_set_credit_upper_bound_nig(
 	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 :
 		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5, credit_upper_bound);
 
-	if (0 == port) {
+	if (!port) {
 		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6,
 			credit_upper_bound);
 		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7,
@@ -610,7 +610,7 @@ static void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
 		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4, 0x0);
 	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 :
 		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5, 0x0);
-	if (0 == port) {
+	if (!port) {
 		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6, 0x0);
 		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7, 0x0);
 		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8, 0x0);
@@ -638,7 +638,7 @@ static void bnx2x_ets_e3b0_set_credit_upper_bound_pbf(
 	* In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
 	* port mode port1 has COS0-2 that can be used for WFQ.
 	*/
-	if (0 == port) {
+	if (!port) {
 		base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
 		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
 	} else {
@@ -700,7 +700,7 @@ static void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
 	* In 2 port mode port0 has COS0-5 that can be used for WFQ.
 	* In 4 port mode port1 has COS0-2 that can be used for WFQ.
 	*/
-	if (0 == port) {
+	if (!port) {
 		base_weight = PBF_REG_COS0_WEIGHT_P0;
 		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
 	} else {
@@ -883,7 +883,7 @@ static int bnx2x_ets_e3b0_get_total_bw(
 
 	/* Calculate total BW requested */
 	for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
-		if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
+		if (ets_params->cos[cos_idx].state == bnx2x_cos_state_bw) {
 			is_bw_cos_exist = 1;
 			if (!ets_params->cos[cos_idx].params.bw_params.bw) {
 				DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config BW"
@@ -901,8 +901,8 @@ static int bnx2x_ets_e3b0_get_total_bw(
 	}
 
 	/* Check total BW is valid */
-	if ((1 == is_bw_cos_exist) && (100 != *total_bw)) {
-		if (0 == *total_bw) {
+	if ((is_bw_cos_exist == 1) && (*total_bw != 100)) {
+		if (*total_bw == 0) {
 			DP(NETIF_MSG_LINK,
 			   "bnx2x_ets_E3B0_config total BW shouldn't be 0\n");
 			return -EINVAL;
@@ -943,7 +943,7 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
 	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
 		DCBX_E3B0_MAX_NUM_COS_PORT0;
 
-	if (DCBX_INVALID_COS != sp_pri_to_cos[pri]) {
+	if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) {
 		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
 				   "parameter There can't be two COS's with "
 				   "the same strict pri\n");
@@ -1034,8 +1034,8 @@ static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
 
 	/* Set all the strict priority first */
 	for (i = 0; i < max_num_of_cos; i++) {
-		if (DCBX_INVALID_COS != sp_pri_to_cos[i]) {
-			if (DCBX_MAX_NUM_COS <= sp_pri_to_cos[i]) {
+		if (sp_pri_to_cos[i] != DCBX_INVALID_COS) {
+			if (sp_pri_to_cos[i] >= DCBX_MAX_NUM_COS) {
 				DP(NETIF_MSG_LINK,
 					   "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
 					   "invalid cos entry\n");
@@ -1049,7 +1049,7 @@ static int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
 			    sp_pri_to_cos[i], pri_set);
 			pri_bitmask = 1 << sp_pri_to_cos[i];
 			/* COS is used remove it from bitmap.*/
-			if (0 == (pri_bitmask & cos_bit_to_set)) {
+			if (!(pri_bitmask & cos_bit_to_set)) {
 				DP(NETIF_MSG_LINK,
 					"bnx2x_ets_e3b0_sp_set_pri_cli_reg "
 					"invalid There can't be two COS's with"
@@ -1144,7 +1144,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
 	/* Prepare BW parameters*/
 	bnx2x_status = bnx2x_ets_e3b0_get_total_bw(params, ets_params,
 						   &total_bw);
-	if (0 != bnx2x_status) {
+	if (bnx2x_status) {
 		DP(NETIF_MSG_LINK,
 		   "bnx2x_ets_E3B0_config get_total_bw failed\n");
 		return -EINVAL;
@@ -1185,7 +1185,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
 			   "bnx2x_ets_e3b0_config cos state not valid\n");
 			return -EINVAL;
 		}
-		if (0 != bnx2x_status) {
+		if (bnx2x_status) {
 			DP(NETIF_MSG_LINK,
 			   "bnx2x_ets_e3b0_config set cos bw failed\n");
 			return bnx2x_status;
@@ -1196,7 +1196,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
 	bnx2x_status = bnx2x_ets_e3b0_sp_set_pri_cli_reg(params,
 							 sp_pri_to_cos);
 
-	if (0 != bnx2x_status) {
+	if (bnx2x_status) {
 		DP(NETIF_MSG_LINK,
 		   "bnx2x_ets_E3B0_config set_pri_cli_reg failed\n");
 		return bnx2x_status;
@@ -1207,7 +1207,7 @@ int bnx2x_ets_e3b0_config(const struct link_params *params,
 					      cos_sp_bitmap,
 					      cos_bw_bitmap);
 
-	if (0 != bnx2x_status) {
+	if (bnx2x_status) {
 		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config SP failed\n");
 		return bnx2x_status;
 	}
@@ -1271,9 +1271,9 @@ void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
 
 	DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
 
-	if ((0 == total_bw) ||
-	    (0 == cos0_bw) ||
-	    (0 == cos1_bw)) {
+	if ((!total_bw) ||
+	    (!cos0_bw) ||
+	    (!cos1_bw)) {
 		DP(NETIF_MSG_LINK, "Total BW can't be zero\n");
 		return;
 	}
@@ -1329,7 +1329,7 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
 	 * dbg0-010     dbg1-001     cos1-100     cos0-011     MCP-000
 	 * dbg0-010     dbg1-001     cos0-011     cos1-100     MCP-000
 	 */
-	val = (0 == strict_cos) ? 0x2318 : 0x22E0;
+	val = (!strict_cos) ? 0x2318 : 0x22E0;
 	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
 
 	return 0;
@@ -1439,7 +1439,7 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
 	if (!vars->link_up)
 		return;
 
-	if (MAC_TYPE_EMAC == vars->mac_type) {
+	if (vars->mac_type == MAC_TYPE_EMAC) {
 		DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n");
 		bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
 					pfc_frames_received);
@@ -2285,7 +2285,7 @@ static int bnx2x_update_pfc_brb(struct link_params *params,
 	/* default - pause configuration */
 	reg_th_config = &config_val.pauseable_th;
 	bnx2x_status = bnx2x_pfc_brb_get_config_params(params, &config_val);
-	if (0 != bnx2x_status)
+	if (bnx2x_status)
 		return bnx2x_status;
 
 	if (pfc_enabled) {
@@ -2619,7 +2619,7 @@ int bnx2x_update_pfc(struct link_params *params,
 
 	/* update BRB params */
 	bnx2x_status = bnx2x_update_pfc_brb(params, vars, pfc_params);
-	if (0 != bnx2x_status)
+	if (bnx2x_status)
 		return bnx2x_status;
 
 	if (!vars->link_up)
-- 
1.7.7.1

^ permalink raw reply related

* Re: [PATCH net-next v2 2/4] can: cc770: add legacy ISA bus driver for the CC770 and AN82527
From: Wolfgang Zarre @ 2011-11-28  8:56 UTC (permalink / raw)
  To: Oliver Hartkopp
  Cc: Wolfgang Grandegger, netdev, linux-can, socketcan-users, IreneV,
	Stanislav Yelenskiy
In-Reply-To: <4ED0FEC5.3070108@hartkopp.net>

Hello Oliver,

> Hello Wolfgang,
>
> many thanks for posting this driver. Indeed this is the last from the missing
> drivers in the SVN ...

@Wolfgang

The same her, thanks a lot.

>
> I added Wolfgang Zarre to the list of recipients who tested your CC770 driver
> recently:
>
> http://old.nabble.com/Compile-Fails-On-2.6.39-2-td32259346.html
>
> Maybe he can check this latest version and can send a "Tested-by:"
>
> @Wolfgang Zarre: The entire patch set from Wolfgang Grandegger is here:
>
> http://patchwork.ozlabs.org/patch/127653/
> http://patchwork.ozlabs.org/patch/127651/
> http://patchwork.ozlabs.org/patch/127654/
> http://patchwork.ozlabs.org/patch/127652/

In fact a month ago we discovered a problem with the previous isa driver but were not
able to reproduce it.

Last Friday during a test run we got the same problem and with some further tests I
was able to reproduce and started with some investigation.

So the patches came in quite handy and even not to waste time I was applying the
patches to an updated svn tree but had to do some manual corrections to get it
compiled.

So far the driver is functioning quite good and I was hoping that our problem would
be solved as well.

But unfortunately that is not the case and it would be great if somebody would have
an idea or similar experience and maybe a solution.

In use:
ISA card: B&R with CC770 (40007) Series Bosch CAN Controller - LQFP-44
Kernel: 2.6.39.4
Module: modprobe cc770_isa irq=0xa port=0x384 indirect=1
Commands: ip link set can0 up type can bitrate 500000;ip link set can0 txqueuelen 2000

dmesg:
[190911.144337] CAN device driver interface
[190911.153316] cc770 CAN netdevice driver
[190911.159708] cc770_isa: platform device 0: port=0x384, mem=0x0, irq=10
[190911.159740] cc770_isa cc770_isa.0: probing idx=0: port=0x384, mem=0x0, irq=10
[190911.159799] cc770_isa cc770_isa.0: (unregistered net_device): i82527 mode with additional functions
[190911.161338] cc770_isa cc770_isa.0: cc770_isa device registered (reg_base=0x00000384, irq=10)
[190911.161384] Legacy cc770_isa driver for max. 8 devices registered
[190912.173762] cc770_isa cc770_isa.0: can0: setting BTR0=0x00 BTR1=0x1c
[190912.173835] cc770_isa cc770_isa.0: can0: Message object 15 for RX data, RTR, SFF and EFF
[190912.173852] cc770_isa cc770_isa.0: can0: Message object 11 for TX data, RTR, SFF and EFF


Description of problem:
After a while sending quite some telegrams the driver of a sudden stops transmitting
and the queue is running full but still capable to receive telegrams.
This issue is not depending on the amount of transmitted telegrams and also no logfile
entries.

Further it is possible to recover with ip link set down and up again.


>
> Just a nitpick in the description:
>
>> Furthermore, the following mode parameter can be defined:
>
>>
>>    clk: External oscillator clock frequency (default=16000000 [16 MHz])
>>    cir: CPU interface register (default=0x40 [DSC])
>>    ocr, Bus configuration register (default=0x40 [CBY])
>
>
> ->  bcr: CPU ...
>
>>    cor, Clockout register (default=0x00)
>
>
> ->  cor: Clockout ...
>
> Regards,
> Oliver

Thanks in advance.

Regards
Wolfgang

^ permalink raw reply

* RE: [net-next v2 0/9] bnx2x: Link changes
From: Yaniv Rosner @ 2011-11-28  9:09 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <1322477393-22904-1-git-send-email-yanivr@broadcom.com>

 This is V2 of series of patches for bnx2x driver.

 The changes from initial commit:
1. Adding new patch9 - Change value comparison order from "val == X" to "X == val".
2. Patch2 - Fix coding convention as #1.
3. Patch4 - Fix indentation.
4. Patch5 - Fix indentation.
5. Patch6 - Fix indentation.
6. Patch7 - Fix indentation.

-----Original Message-----
From: Yaniv Rosner [mailto:yanivr@broadcom.com] 
Sent: Monday, November 28, 2011 12:50 PM
To: David Miller
Cc: netdev; Yaniv Rosner
Subject: [net-next v2 0/9] bnx2x: Link changes

Hi Dave,
The following patch series describe some link changes.
Please consider applying it to net-next.

Thanks,
Yaniv

^ permalink raw reply

* [PATCH] net: rfkill: convert net/rfkill/* to use module_platform_driver()
From: Axel Lin @ 2011-11-28  9:15 UTC (permalink / raw)
  To: linux-kernel
  Cc: John W. Linville, Johannes Berg, David S. Miller, Antonio Ospite,
	Rhyland Klein, linux-wireless, netdev

This patch converts the drivers in net/rfkill/* to use the
module_platform_driver() macro which makes the code smaller and a bit
simpler.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Antonio Ospite <ospite@studenti.unina.it>
Cc: Rhyland Klein <rklein@nvidia.com>
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
 net/rfkill/rfkill-gpio.c      |   13 +------------
 net/rfkill/rfkill-regulator.c |   12 +-----------
 2 files changed, 2 insertions(+), 23 deletions(-)

diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index 128677d..ca355e7 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -220,18 +220,7 @@ static struct platform_driver rfkill_gpio_driver = {
 	},
 };
 
-static int __init rfkill_gpio_init(void)
-{
-	return platform_driver_register(&rfkill_gpio_driver);
-}
-
-static void __exit rfkill_gpio_exit(void)
-{
-	platform_driver_unregister(&rfkill_gpio_driver);
-}
-
-module_init(rfkill_gpio_init);
-module_exit(rfkill_gpio_exit);
+module_platform_driver(rfkill_gpio_driver);
 
 MODULE_DESCRIPTION("gpio rfkill");
 MODULE_AUTHOR("NVIDIA");
diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c
index 3ca7277..2ebfe8d 100644
--- a/net/rfkill/rfkill-regulator.c
+++ b/net/rfkill/rfkill-regulator.c
@@ -144,17 +144,7 @@ static struct platform_driver rfkill_regulator_driver = {
 	},
 };
 
-static int __init rfkill_regulator_init(void)
-{
-	return platform_driver_register(&rfkill_regulator_driver);
-}
-module_init(rfkill_regulator_init);
-
-static void __exit rfkill_regulator_exit(void)
-{
-	platform_driver_unregister(&rfkill_regulator_driver);
-}
-module_exit(rfkill_regulator_exit);
+module_platform_driver(rfkill_regulator_driver);
 
 MODULE_AUTHOR("Guiming Zhuo <gmzhuo@gmail.com>");
 MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
-- 
1.7.5.4

^ permalink raw reply related

* Re: [PATCH net-next v2 2/4] can: cc770: add legacy ISA bus driver for the CC770 and AN82527
From: Wolfgang Grandegger @ 2011-11-28  9:17 UTC (permalink / raw)
  To: info
  Cc: Oliver Hartkopp, netdev, linux-can, socketcan-users, IreneV,
	Stanislav Yelenskiy
In-Reply-To: <4ED34CAD.7040000@essax.com>

On 11/28/2011 09:56 AM, Wolfgang Zarre wrote:
> Hello Oliver,
> 
>> Hello Wolfgang,
>>
>> many thanks for posting this driver. Indeed this is the last from the
>> missing
>> drivers in the SVN ...
> 
> @Wolfgang
> 
> The same her, thanks a lot.
> 
>>
>> I added Wolfgang Zarre to the list of recipients who tested your CC770
>> driver
>> recently:
>>
>> http://old.nabble.com/Compile-Fails-On-2.6.39-2-td32259346.html
>>
>> Maybe he can check this latest version and can send a "Tested-by:"
>>
>> @Wolfgang Zarre: The entire patch set from Wolfgang Grandegger is here:
>>
>> http://patchwork.ozlabs.org/patch/127653/
>> http://patchwork.ozlabs.org/patch/127651/
>> http://patchwork.ozlabs.org/patch/127654/
>> http://patchwork.ozlabs.org/patch/127652/
> 
> In fact a month ago we discovered a problem with the previous isa driver
> but were not
> able to reproduce it.
> 
> Last Friday during a test run we got the same problem and with some
> further tests I
> was able to reproduce and started with some investigation.
> 
> So the patches came in quite handy and even not to waste time I was
> applying the
> patches to an updated svn tree but had to do some manual corrections to
> get it
> compiled.
> 
> So far the driver is functioning quite good and I was hoping that our
> problem would
> be solved as well.

Well, I do not remember any fix... apart from

> But unfortunately that is not the case and it would be great if somebody
> would have
> an idea or similar experience and maybe a solution.
> 
> In use:
> ISA card: B&R with CC770 (40007) Series Bosch CAN Controller - LQFP-44
> Kernel: 2.6.39.4
> Module: modprobe cc770_isa irq=0xa port=0x384 indirect=1
> Commands: ip link set can0 up type can bitrate 500000;ip link set can0
> txqueuelen 2000

... using a reasonable default for bcr of 0x40. But you may need to
provide better values for cir, bcr and cor.

> dmesg:
> [190911.144337] CAN device driver interface
> [190911.153316] cc770 CAN netdevice driver
> [190911.159708] cc770_isa: platform device 0: port=0x384, mem=0x0, irq=10
> [190911.159740] cc770_isa cc770_isa.0: probing idx=0: port=0x384,
> mem=0x0, irq=10
> [190911.159799] cc770_isa cc770_isa.0: (unregistered net_device): i82527
> mode with additional functions
> [190911.161338] cc770_isa cc770_isa.0: cc770_isa device registered
> (reg_base=0x00000384, irq=10)
> [190911.161384] Legacy cc770_isa driver for max. 8 devices registered
> [190912.173762] cc770_isa cc770_isa.0: can0: setting BTR0=0x00 BTR1=0x1c
> [190912.173835] cc770_isa cc770_isa.0: can0: Message object 15 for RX
> data, RTR, SFF and EFF
> [190912.173852] cc770_isa cc770_isa.0: can0: Message object 11 for TX
> data, RTR, SFF and EFF
> 
> 
> Description of problem:
> After a while sending quite some telegrams the driver of a sudden stops
> transmitting
> and the queue is running full but still capable to receive telegrams.
> This issue is not depending on the amount of transmitted telegrams and
> also no logfile
> entries.

What do you get with "candump -t d any,0:0,#FFFFFFFF"? What does "ip -d
-s link show" show?

Wolfgang.


^ permalink raw reply

* Re[2]:  [v4 PATCH 1/2] NETFILTER module xt_hmark, new target for HASH based fwmark
From: Hans Schillstrom @ 2011-11-28  9:36 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: kaber, jengelh, netfilter-devel, netdev, hans.schillstrom

>
>On Fri, Nov 25, 2011 at 10:36:26AM +0100, Hans Schillstrom wrote:
>> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
>> index 3f0258d..9e4d4f9 100644
>> --- a/include/net/ipv6.h
>> +++ b/include/net/ipv6.h
>> @@ -39,6 +39,7 @@
>>  #define NEXTHDR_ICMP		58	/* ICMP for IPv6. */
>>  #define NEXTHDR_NONE		59	/* No next header */
>>  #define NEXTHDR_DEST		60	/* Destination options header. */
>> +#define NEXTHDR_SCTP		132	/* Stream Control Transport Protocol */
>>  #define NEXTHDR_MOBILITY	135	/* Mobility header. */
>>  
>>  #define NEXTHDR_MAX		255
>
>This has to go in a separated patch. Please, send it to netdev. I
>think davem can pick that for 3.2-rc

I will send this tiny one to Dave

[snip]

>> +static int get_inner_hdr(struct sk_buff *skb, int iphsz, int nhoff)
>> +{
>> +	const struct icmphdr *icmph;
>> +	struct icmphdr _ih;
>> +	struct iphdr *iph = NULL;
>> +
>> +	/* Not enough header? */
>> +	icmph = skb_header_pointer(skb, nhoff + iphsz, sizeof(_ih), &_ih);
>> +	if (icmph == NULL)
>> +		return nhoff;
>> +
>> +	if (icmph->type > NR_ICMP_TYPES)
>> +		return nhoff;
>> +
>> +	/* Error message? */
>> +	if (icmph->type != ICMP_DEST_UNREACH &&
>> +	    icmph->type != ICMP_SOURCE_QUENCH &&
>> +	    icmph->type != ICMP_TIME_EXCEEDED &&
>> +	    icmph->type != ICMP_PARAMETERPROB &&
>> +	    icmph->type != ICMP_REDIRECT)
>> +		return nhoff;
>> +	/* Checkin full IP header plus 8 bytes of protocol to
>> +	 * avoid additional coding at protocol handlers.
>> +	 */
>> +	if (!pskb_may_pull(skb, nhoff + iphsz + sizeof(_ih) + 8))
>> +		return nhoff;
>
>skb_header_pointer again here, if conntrack is enabled, we can benefit
>from handling fragments.
>
Yes, but I can't asume that conntrack is there.

[snip]

>> +/*
>> + * Calc hash value, special casre is taken on icmp and fragmented messages
>> + * i.e. fragmented messages don't use ports.
>> + */
>> +__u32 hmark_v6(struct sk_buff *skb, const struct xt_action_param *par)
>> +{
>> +	struct xt_hmark_info *info = (struct xt_hmark_info *)par->targinfo;
>> +	int nhoff, poff, hdrlen;
>> +	u32 addr1, addr2, hash;
>> +	struct ipv6hdr *ip6;
>> +	u8 nexthdr;
>> +	int frag = 0, ip6hdrlvl = 0;	/* Header level */
>> +	struct ipv6_opt_hdr _hdr, *hp;
>> +	union {
>> +		u32 v32;
>> +		u16 v16[2];
>> +	} ports;
>> +
>> +	ports.v32 = 0;
>> +	nhoff = skb_network_offset(skb);
>> +
>> +hdr_new:
>> +	/* Get header info */
>> +	ip6 = (struct ipv6hdr *) (skb->data + nhoff);
>> +	nexthdr = ip6->nexthdr;
>> +	hdrlen = sizeof(struct ipv6hdr);
>> +	hp = skb_header_pointer(skb, nhoff + hdrlen, sizeof(_hdr), &_hdr);
>
>you have to check return value of skb_header_pointer here.

This  is actually where next header will start if any, not the current one that is processed. 
It's not time for checking it now. The check is done before using it further down.

>
>> +	while (nexthdr) {
>> +		switch (nexthdr) {
>> +		case IPPROTO_ICMPV6:
>> +			/* ICMP Error then move ptr to inner header */
>> +			if (get_inner6_hdr(skb, &nhoff, hdrlen)) {
>> +				ip6hdrlvl++;
>> +				if (!pskb_may_pull(skb, sizeof(_hdr) + nhoff))
>> +					return XT_CONTINUE;
>> +				goto hdr_new;
>> +			}
>> +			nhoff += hdrlen;
>> +			goto hdr_rdy;
>> +
>> +		case NEXTHDR_FRAGMENT:
>> +			if (!ip6hdrlvl) /* Do not use ports if fragmented */
>> +				frag = 1;
>> +			break;
>> +
>> +		/* End of hdr traversing cont. with ports and hash calc. */
>> +		case NEXTHDR_IPV6:	/* Do not process tunnels */
>> +		case NEXTHDR_TCP:
>> +		case NEXTHDR_UDP:
>> +		case NEXTHDR_ESP:
>> +		case NEXTHDR_AUTH:
>> +		case NEXTHDR_SCTP:
>> +		case NEXTHDR_NONE:	/* Last hdr of something unknown */
>> +			nhoff += hdrlen;
>> +			goto hdr_rdy;
>> +		default:
>> +			return XT_CONTINUE;
>> +		}
>> +		if (!hp)
>> +			return XT_CONTINUE;
>> +		nhoff += hdrlen;	/* eat current header */
>> +		nexthdr =  hp->nexthdr;	/* Next header */
>> +		hdrlen = ipv6_optlen(hp);
>> +		hp = skb_header_pointer(skb, nhoff + hdrlen, sizeof(_hdr),
>> +					&_hdr);
>
>same here.
>
>> +		if (!pskb_may_pull(skb, nhoff))
>
>why this after skb_header_pointer?

hp is used for next turn, but you got a point here  I'll swap them 

>
>[... trimmed off ...]
>>       poff = proto_ports_offset(ip_proto);
>>       nhoff += ip->ihl * 4 + poff;
>>       if (frag || poff < 0 || !pskb_may_pull(skb, nhoff + 4))
>>               goto noports;
>>
>>       ports.v32 = * (__force u32 *) (skb->data + nhoff);
>>       if (ip_proto == IPPROTO_ESP || ip_proto == IPPROTO_AH) {
>>               ports.v32 = (ports.v32 & info->spimask) | nfo->spiset;
>>       } else {
>>               if (snatport)   /* Replace nat'ed port(s) */
>>                       ports.v16[1] = snatport;
>>               if (dnatport)
>>                       ports.v16[0] = dnatport;
>>               ports.v32 = (ports.v32 & info->pmask.v32) |
>>                               info->pset.v32;
>>               if (ports.v16[1] < ports.v16[0])
>>                       swap(ports.v16[0], ports.v16[1]);
>>       }
>>
>>noports:
>>       ip_proto &= info->prmask;
>>       /* get a consistent hash (same value on both flow directions)/
>>       if (addr2 < addr1)
>>               swap(addr1, addr2);
>>
>>       hash = jhash_3words(addr1, addr2, ports.v32, info->hashrnd) ^ p_proto;
>>       if (info->hmod)
>>               skb->mark = (hash % info->hmod) + info->hoffs;
>>       return XT_CONTINUE;
>> }
>
>Hm, I think the fragmentation handling is broken.
>
>Say that the first fragment contains the transport header
>header, then the mark is calculated based on the address and ports.
>Then, later on fragments will receive the mark based on the network
>header only. They may have different marks.

I think the documentation need improvments :-)
Fragments  never try to use ports.
"    if (frag)
         goto noports;"

>
>If you don't want to use conntrack in your setup and you want to handle
>fragments, then you have to configure HMARK to calculate the hashing
>based on the network addresses. If you want to fully support fragments,
>then enable conntrack and you can configure HMARK to calculate the
>hashing based on network address + transport bits.
>
>Fix this by removing the fragmentation handling, then assume that
>people can select between two hashing configuration for HMARK. One
>based for network address which is fragment-safe, one that uses the
>transport layer information, that requires conntrack. Otherwise, I
>don't see a sane way to handle this situation.

Correct me if I'm wrong here, 
If conntrack is enabled hmark don't see the packet until it is reassembled and 
in that case the fragmentation header is removed.

So, with conntrack HMARK will operate on full packets not fragments
without conntrack ports will not be used on any fragment.

>
>I think this has to be documented in the iptables manpage for HMARK.

The documentation needs update here, this is not crystal clear.

Thanks
Hans


^ permalink raw reply

* Re: [PATCH] net: Fix corruption in /proc/*/net/dev_mcast
From: Eric Dumazet @ 2011-11-28  9:55 UTC (permalink / raw)
  To: Anton Blanchard
  Cc: Sasha Levin, David Miller, Matt Mackall, Christoph Lameter,
	Pekka Enberg, linux-mm, linux-kernel, netdev, Mihai Maruseac
In-Reply-To: <20111128181446.2ab784d0@kryten>

Le lundi 28 novembre 2011 à 18:14 +1100, Anton Blanchard a écrit :
> Hi,
> 
> > I got the following output when running some tests (I'm not really sure
> > what exactly happened when this bug was triggered):
> > 
> > [13850.947279] =============================================================================
> > [13850.948024] BUG kmalloc-8: Redzone overwritten
> > [13850.948024] -----------------------------------------------------------------------------
> > [13850.948024] 
> > [13850.948024] INFO: 0xffff8800104f6d28-0xffff8800104f6d2b. First byte 0x0 instead of 0xcc
> > [13850.948024] INFO: Allocated in __seq_open_private+0x20/0x5e age=4436 cpu=0 pid=17295
> > [13850.948024] 	__slab_alloc.clone.46+0x3e7/0x456
> > [13850.948024] 	__kmalloc+0x8c/0x110
> > [13850.948024] 	__seq_open_private+0x20/0x5e
> > [13850.948024] 	seq_open_net+0x3b/0x5d
> > [13850.948024] 	dev_mc_seq_open+0x15/0x17
> > [13850.948024] 	proc_reg_open+0xad/0x127
> 
> I just hit this during my testing. Isn't there another bug lurking?
> 
> Anton
> --
> 
> 
> With slub debugging on I see red zone issues in /proc/*/net/dev_mcast:
> 
> =============================================================================
> BUG kmalloc-8: Redzone overwritten
> -----------------------------------------------------------------------------
> 
> INFO: 0xc0000000de9dec48-0xc0000000de9dec4b. First byte 0x0 instead of 0xcc
> INFO: Allocated in .__seq_open_private+0x30/0xa0 age=0 cpu=5 pid=3896
> 	.__kmalloc+0x1e0/0x2d0
> 	.__seq_open_private+0x30/0xa0
> 	.seq_open_net+0x60/0xe0
> 	.dev_mc_seq_open+0x4c/0x70
> 	.proc_reg_open+0xd8/0x260
> 	.__dentry_open.clone.11+0x2b8/0x400
> 	.do_last+0xf4/0x950
> 	.path_openat+0xf8/0x480
> 	.do_filp_open+0x48/0xc0
> 	.do_sys_open+0x140/0x250
> 	syscall_exit+0x0/0x40
> 
> dev_mc_seq_ops uses dev_seq_start/next/stop but only allocates
> sizeof(struct seq_net_private) of private data, whereas it expects
> sizeof(struct dev_iter_state):
> 
> struct dev_iter_state {
> 	struct seq_net_private p;
> 	unsigned int pos; /* bucket << BUCKET_SPACE + offset */
> };
> 
> Create dev_seq_open_ops and use it so we don't have to expose
> struct dev_iter_state.
> 
> Signed-off-by: Anton Blanchard <anton@samba.org>
> ---
> 
> Index: linux-net/include/linux/netdevice.h
> ===================================================================
> --- linux-net.orig/include/linux/netdevice.h	2011-11-28 17:55:51.469508056 +1100
> +++ linux-net/include/linux/netdevice.h	2011-11-28 17:55:52.985535812 +1100
> @@ -2536,6 +2536,8 @@ extern void		net_disable_timestamp(void)
>  extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);
>  extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
>  extern void dev_seq_stop(struct seq_file *seq, void *v);
> +extern int dev_seq_open_ops(struct inode *inode, struct file *file,
> +			    const struct seq_operations *ops);
>  #endif
>  
>  extern int netdev_class_create_file(struct class_attribute *class_attr);
> Index: linux-net/net/core/dev.c
> ===================================================================
> --- linux-net.orig/net/core/dev.c	2011-11-28 17:55:51.481508276 +1100
> +++ linux-net/net/core/dev.c	2011-11-28 17:55:52.989535885 +1100
> @@ -4282,6 +4282,12 @@ static int dev_seq_open(struct inode *in
>  			    sizeof(struct dev_iter_state));
>  }
>  
> +int dev_seq_open_ops(struct inode *inode, struct file *file,
> +		     const struct seq_operations *ops)
> +{
> +	return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state));
> +}
> +
>  static const struct file_operations dev_seq_fops = {
>  	.owner	 = THIS_MODULE,
>  	.open    = dev_seq_open,
> Index: linux-net/net/core/dev_addr_lists.c
> ===================================================================
> --- linux-net.orig/net/core/dev_addr_lists.c	2011-11-28 17:55:47.845441705 +1100
> +++ linux-net/net/core/dev_addr_lists.c	2011-11-28 17:55:52.989535885 +1100
> @@ -696,8 +696,7 @@ static const struct seq_operations dev_m
>  
>  static int dev_mc_seq_open(struct inode *inode, struct file *file)
>  {
> -	return seq_open_net(inode, file, &dev_mc_seq_ops,
> -			    sizeof(struct seq_net_private));
> +	return dev_seq_open_ops(inode, file, &dev_mc_seq_ops);
>  }
>  
>  static const struct file_operations dev_mc_seq_fops = {


Good catch, thanks !

Problem added by commit f04565ddf52e4 (dev: use name hash for
dev_seq_ops)


Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Mihai Maruseac <mihai.maruseac@gmail.com>



--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [BUG] 3.2-rc2: BUG kmalloc-8: Redzone overwritten
From: Christine Caulfield @ 2011-11-28  9:58 UTC (permalink / raw)
  To: David Miller
  Cc: swhiteho, eric.dumazet, levinsasha928, mpm, cl, penberg, linux-mm,
	linux-kernel, netdev
In-Reply-To: <20111126.155028.1986754382924402334.davem@davemloft.net>

On 26/11/11 20:50, David Miller wrote:
> From: Steven Whitehouse<swhiteho@redhat.com>
> Date: Mon, 21 Nov 2011 10:58:30 +0000
>
>> I have to say that I've been wondering lately whether it has got to the
>> point where it is no longer useful. Has anybody actually tested it
>> lately against "real" DEC implementations?
>
> I doubt it :-)
>

DECnet is in use against real DEC implementations - I have checked it 
quite recently against a VAX running OpenVMS. How many people are 
actually using it for real work is a different question though.

It's also true that it's not really supported by anyone as I orphaned it 
some time ago and nobody else seems to care enough to take it over. So 
if it's becoming a burden on people doing real kernel work then I don't 
think many tears will be wept for its removal.

Chrissie

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH] net/can: convert drivers/net/can/* to use module_platform_driver()
From: Marc Kleine-Budde @ 2011-11-28 10:17 UTC (permalink / raw)
  To: Axel Lin
  Cc: linux-kernel, Wolfgang Grandegger, David S. Miller,
	Bhupesh Sharma, Jiri Kosina, Grant Likely, Anatolij Gustschin,
	Paul Bolle, Kurt Van Dijck, Alexey Dobriyan, linux-can, netdev
In-Reply-To: <1322444551.2408.2.camel@phoenix>

[-- Attachment #1: Type: text/plain, Size: 9569 bytes --]

On 11/28/2011 02:42 AM, Axel Lin wrote:
> This patch converts the drivers in drivers/net/can/* to use the
> module_platform_driver() macro which makes the code smaller and a bit
> simpler.
> 
> Cc: Wolfgang Grandegger <wg@grandegger.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Bhupesh Sharma <bhupesh.sharma@st.com> 
> Cc: Jiri Kosina <jkosina@suse.cz>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Anatolij Gustschin <agust@denx.de> 
> Cc: Paul Bolle <pebolle@tiscali.nl>
> Cc: Kurt Van Dijck <kurt.van.dijck@eia.be>
> Cc: Alexey Dobriyan <adobriyan@gmail.com> 
> Signed-off-by: Axel Lin <axel.lin@gmail.com>

Acked-by: Marc Kleine-Budde <mkl@pengutronix.de>

> ---
>  drivers/net/can/at91_can.c                    |   13 +------------
>  drivers/net/can/bfin_can.c                    |   12 +-----------
>  drivers/net/can/c_can/c_can_platform.c        |   12 +-----------
>  drivers/net/can/flexcan.c                     |   15 +--------------
>  drivers/net/can/janz-ican3.c                  |   13 +------------
>  drivers/net/can/mscan/mpc5xxx_can.c           |   12 +-----------
>  drivers/net/can/sja1000/sja1000_of_platform.c |   12 +-----------
>  drivers/net/can/sja1000/sja1000_platform.c    |   13 +------------
>  drivers/net/can/softing/softing_main.c        |   16 ++--------------
>  drivers/net/can/ti_hecc.c                     |   15 +--------------
>  10 files changed, 11 insertions(+), 122 deletions(-)
> 
> diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
> index 044ea06..6ea905c 100644
> --- a/drivers/net/can/at91_can.c
> +++ b/drivers/net/can/at91_can.c
> @@ -1383,18 +1383,7 @@ static struct platform_driver at91_can_driver = {
>  	.id_table = at91_can_id_table,
>  };
>  
> -static int __init at91_can_module_init(void)
> -{
> -	return platform_driver_register(&at91_can_driver);
> -}
> -
> -static void __exit at91_can_module_exit(void)
> -{
> -	platform_driver_unregister(&at91_can_driver);
> -}
> -
> -module_init(at91_can_module_init);
> -module_exit(at91_can_module_exit);
> +module_platform_driver(at91_can_driver);
>  
>  MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>");
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
> index a1c5abc..349e0fa 100644
> --- a/drivers/net/can/bfin_can.c
> +++ b/drivers/net/can/bfin_can.c
> @@ -676,17 +676,7 @@ static struct platform_driver bfin_can_driver = {
>  	},
>  };
>  
> -static int __init bfin_can_init(void)
> -{
> -	return platform_driver_register(&bfin_can_driver);
> -}
> -module_init(bfin_can_init);
> -
> -static void __exit bfin_can_exit(void)
> -{
> -	platform_driver_unregister(&bfin_can_driver);
> -}
> -module_exit(bfin_can_exit);
> +module_platform_driver(bfin_can_driver);
>  
>  MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
>  MODULE_LICENSE("GPL");
> diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
> index 0b5c6f8..5e1a5ff 100644
> --- a/drivers/net/can/c_can/c_can_platform.c
> +++ b/drivers/net/can/c_can/c_can_platform.c
> @@ -197,17 +197,7 @@ static struct platform_driver c_can_plat_driver = {
>  	.remove = __devexit_p(c_can_plat_remove),
>  };
>  
> -static int __init c_can_plat_init(void)
> -{
> -	return platform_driver_register(&c_can_plat_driver);
> -}
> -module_init(c_can_plat_init);
> -
> -static void __exit c_can_plat_exit(void)
> -{
> -	platform_driver_unregister(&c_can_plat_driver);
> -}
> -module_exit(c_can_plat_exit);
> +module_platform_driver(c_can_plat_driver);
>  
>  MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>");
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
> index e023379..165a4c7 100644
> --- a/drivers/net/can/flexcan.c
> +++ b/drivers/net/can/flexcan.c
> @@ -1060,20 +1060,7 @@ static struct platform_driver flexcan_driver = {
>  	.remove = __devexit_p(flexcan_remove),
>  };
>  
> -static int __init flexcan_init(void)
> -{
> -	pr_info("%s netdevice driver\n", DRV_NAME);
> -	return platform_driver_register(&flexcan_driver);
> -}
> -
> -static void __exit flexcan_exit(void)
> -{
> -	platform_driver_unregister(&flexcan_driver);
> -	pr_info("%s: driver removed\n", DRV_NAME);
> -}
> -
> -module_init(flexcan_init);
> -module_exit(flexcan_exit);
> +module_platform_driver(flexcan_driver);
>  
>  MODULE_AUTHOR("Sascha Hauer <kernel@pengutronix.de>, "
>  	      "Marc Kleine-Budde <kernel@pengutronix.de>");
> diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c
> index 32778d5..08c893c 100644
> --- a/drivers/net/can/janz-ican3.c
> +++ b/drivers/net/can/janz-ican3.c
> @@ -1803,20 +1803,9 @@ static struct platform_driver ican3_driver = {
>  	.remove		= __devexit_p(ican3_remove),
>  };
>  
> -static int __init ican3_init(void)
> -{
> -	return platform_driver_register(&ican3_driver);
> -}
> -
> -static void __exit ican3_exit(void)
> -{
> -	platform_driver_unregister(&ican3_driver);
> -}
> +module_platform_driver(ican3_driver);
>  
>  MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
>  MODULE_DESCRIPTION("Janz MODULbus VMOD-ICAN3 Driver");
>  MODULE_LICENSE("GPL");
>  MODULE_ALIAS("platform:janz-ican3");
> -
> -module_init(ican3_init);
> -module_exit(ican3_exit);
> diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
> index 5fedc33..5caa572 100644
> --- a/drivers/net/can/mscan/mpc5xxx_can.c
> +++ b/drivers/net/can/mscan/mpc5xxx_can.c
> @@ -411,17 +411,7 @@ static struct platform_driver mpc5xxx_can_driver = {
>  #endif
>  };
>  
> -static int __init mpc5xxx_can_init(void)
> -{
> -	return platform_driver_register(&mpc5xxx_can_driver);
> -}
> -module_init(mpc5xxx_can_init);
> -
> -static void __exit mpc5xxx_can_exit(void)
> -{
> -	platform_driver_unregister(&mpc5xxx_can_driver);
> -};
> -module_exit(mpc5xxx_can_exit);
> +module_platform_driver(mpc5xxx_can_driver);
>  
>  MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
>  MODULE_DESCRIPTION("Freescale MPC5xxx CAN driver");
> diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
> index c3dd9d0..f2683eb 100644
> --- a/drivers/net/can/sja1000/sja1000_of_platform.c
> +++ b/drivers/net/can/sja1000/sja1000_of_platform.c
> @@ -220,14 +220,4 @@ static struct platform_driver sja1000_ofp_driver = {
>  	.remove = __devexit_p(sja1000_ofp_remove),
>  };
>  
> -static int __init sja1000_ofp_init(void)
> -{
> -	return platform_driver_register(&sja1000_ofp_driver);
> -}
> -module_init(sja1000_ofp_init);
> -
> -static void __exit sja1000_ofp_exit(void)
> -{
> -	return platform_driver_unregister(&sja1000_ofp_driver);
> -};
> -module_exit(sja1000_ofp_exit);
> +module_platform_driver(sja1000_ofp_driver);
> diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
> index d9fadc4..4f50145 100644
> --- a/drivers/net/can/sja1000/sja1000_platform.c
> +++ b/drivers/net/can/sja1000/sja1000_platform.c
> @@ -185,15 +185,4 @@ static struct platform_driver sp_driver = {
>  	},
>  };
>  
> -static int __init sp_init(void)
> -{
> -	return platform_driver_register(&sp_driver);
> -}
> -
> -static void __exit sp_exit(void)
> -{
> -	platform_driver_unregister(&sp_driver);
> -}
> -
> -module_init(sp_init);
> -module_exit(sp_exit);
> +module_platform_driver(sp_driver);
> diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
> index 09a8b86..a7c77c7 100644
> --- a/drivers/net/can/softing/softing_main.c
> +++ b/drivers/net/can/softing/softing_main.c
> @@ -874,21 +874,9 @@ static struct platform_driver softing_driver = {
>  	.remove = __devexit_p(softing_pdev_remove),
>  };
>  
> -MODULE_ALIAS("platform:softing");
> -
> -static int __init softing_start(void)
> -{
> -	return platform_driver_register(&softing_driver);
> -}
> -
> -static void __exit softing_stop(void)
> -{
> -	platform_driver_unregister(&softing_driver);
> -}
> -
> -module_init(softing_start);
> -module_exit(softing_stop);
> +module_platform_driver(softing_driver);
>  
> +MODULE_ALIAS("platform:softing");
>  MODULE_DESCRIPTION("Softing DPRAM CAN driver");
>  MODULE_AUTHOR("Kurt Van Dijck <kurt.van.dijck@eia.be>");
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
> index 2adc294..df809e3 100644
> --- a/drivers/net/can/ti_hecc.c
> +++ b/drivers/net/can/ti_hecc.c
> @@ -1037,20 +1037,7 @@ static struct platform_driver ti_hecc_driver = {
>  	.resume = ti_hecc_resume,
>  };
>  
> -static int __init ti_hecc_init_driver(void)
> -{
> -	printk(KERN_INFO DRV_DESC "\n");
> -	return platform_driver_register(&ti_hecc_driver);
> -}
> -
> -static void __exit ti_hecc_exit_driver(void)
> -{
> -	printk(KERN_INFO DRV_DESC " unloaded\n");
> -	platform_driver_unregister(&ti_hecc_driver);
> -}
> -
> -module_exit(ti_hecc_exit_driver);
> -module_init(ti_hecc_init_driver);
> +module_platform_driver(ti_hecc_driver);
>  
>  MODULE_AUTHOR("Anant Gole <anantgole@ti.com>");
>  MODULE_LICENSE("GPL v2");


-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply

* [PATCH net-next] tcp: tcp_sendmsg() wrong access to sk_route_caps
From: Eric Dumazet @ 2011-11-28 10:27 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Michał Mirosław

Now sk_route_caps is u64, its dangerous to use an integer to store
result of an AND operator. It wont work if NETIF_F_SG is moved on the
upper part of u64.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 net/ipv4/tcp.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 50c3596..ecbc89a 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -891,7 +891,7 @@ EXPORT_SYMBOL(tcp_sendpage);
 #define TCP_PAGE(sk)	(sk->sk_sndmsg_page)
 #define TCP_OFF(sk)	(sk->sk_sndmsg_off)
 
-static inline int select_size(const struct sock *sk, int sg)
+static inline int select_size(const struct sock *sk, bool sg)
 {
 	const struct tcp_sock *tp = tcp_sk(sk);
 	int tmp = tp->mss_cache;
@@ -917,9 +917,9 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	struct iovec *iov;
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *skb;
-	int iovlen, flags;
+	int iovlen, flags, err, copied;
 	int mss_now, size_goal;
-	int sg, err, copied;
+	bool sg;
 	long timeo;
 
 	lock_sock(sk);
@@ -946,7 +946,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
 		goto out_err;
 
-	sg = sk->sk_route_caps & NETIF_F_SG;
+	sg = !!(sk->sk_route_caps & NETIF_F_SG);
 
 	while (--iovlen >= 0) {
 		size_t seglen = iov->iov_len;

^ permalink raw reply related

* Re: [PATCH] net: Fix corruption in /proc/*/net/dev_mcast
From: Daniel Baluta @ 2011-11-28 10:40 UTC (permalink / raw)
  To: Eric Dumazet, Anton Blanchard
  Cc: Sasha Levin, David Miller, Matt Mackall, Christoph Lameter,
	Pekka Enberg, linux-mm, linux-kernel, netdev, Mihai Maruseac
In-Reply-To: <1322474116.2292.5.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

>> dev_mc_seq_ops uses dev_seq_start/next/stop but only allocates
>> sizeof(struct seq_net_private) of private data, whereas it expects
>> sizeof(struct dev_iter_state):
>>
>> struct dev_iter_state {
>>       struct seq_net_private p;
>>       unsigned int pos; /* bucket << BUCKET_SPACE + offset */
>> };
>>
>> Create dev_seq_open_ops and use it so we don't have to expose
>> struct dev_iter_state.

Good catch, indeed! We've now checked and this is the only place
where the problem happens.


>> +int dev_seq_open_ops(struct inode *inode, struct file *file,
>> +                  const struct seq_operations *ops)
>> +{
>> +     return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state));
>> +}

Perhaps you could use this function also in dev_seq_open (dev.c:4280).

>>  static int dev_mc_seq_open(struct inode *inode, struct file *file)
>>  {
>> -     return seq_open_net(inode, file, &dev_mc_seq_ops,
>> -                         sizeof(struct seq_net_private));
>> +     return dev_seq_open_ops(inode, file, &dev_mc_seq_ops);
>>  }
>>
>>  static const struct file_operations dev_mc_seq_fops = {


thanks,
Daniel.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH net-next] tcp: tcp_sendmsg() wrong access to sk_route_caps
From: Joe Perches @ 2011-11-28 10:46 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, Michał Mirosław
In-Reply-To: <1322476067.2292.12.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>

On Mon, 2011-11-28 at 11:27 +0100, Eric Dumazet wrote:
> Now sk_route_caps is u64, its dangerous to use an integer to store
> result of an AND operator. It wont work if NETIF_F_SG is moved on the
> upper part of u64.

trivial comment below.

> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
[]
> @@ -917,9 +917,9 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
>  	struct iovec *iov;
>  	struct tcp_sock *tp = tcp_sk(sk);
>  	struct sk_buff *skb;
> -	int iovlen, flags;
> +	int iovlen, flags, err, copied;
>  	int mss_now, size_goal;
> -	int sg, err, copied;
> +	bool sg;
>  	long timeo;
>  
>  	lock_sock(sk);
> @@ -946,7 +946,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
>  	if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
>  		goto out_err;
>  
> -	sg = sk->sk_route_caps & NETIF_F_SG;
> +	sg = !!(sk->sk_route_caps & NETIF_F_SG);

As sg is now bool, using !! is unnecessary.

A commit was done recently to remove one.
3ad9b358e03fd9dbf6705721490c811b666b0fe2

^ permalink raw reply

* Re: [PATCH v6 10/10] Disable task moving when using kernel memory accounting
From: Glauber Costa @ 2011-11-28 11:00 UTC (permalink / raw)
  To: KAMEZAWA Hiroyuki
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, lizf-BthXqXjhjHXQFUHtdCDX3A,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	paul-inf54ven1CmVyaH7bEyXVA, gthelen-hpIqsD4AKlfQT0dZR+AlfA,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	kirill-oKw7cIdHH8eLwutG50LtGA, avagin-bzQdu9zFT3WakBO8gow8eQ,
	devel-GEFAQzZX7r8dnm+yROfE0A, eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
	cgroups-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20111128133203.2d52ee28.kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>

On 11/28/2011 02:32 AM, KAMEZAWA Hiroyuki wrote:
> On Fri, 25 Nov 2011 15:38:16 -0200
> Glauber Costa<glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>  wrote:
>
>> Since this code is still experimental, we are leaving the exact
>> details of how to move tasks between cgroups when kernel memory
>> accounting is used as future work.
>>
>> For now, we simply disallow movement if there are any pending
>> accounted memory.
>>
>> Signed-off-by: Glauber Costa<glommer-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
>> CC: Hiroyouki Kamezawa<kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
>> ---
>>   mm/memcontrol.c |   23 ++++++++++++++++++++++-
>>   1 files changed, 22 insertions(+), 1 deletions(-)
>>
>> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
>> index 2df5d3c..ab7e57b 100644
>> --- a/mm/memcontrol.c
>> +++ b/mm/memcontrol.c
>> @@ -5451,10 +5451,19 @@ static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
>>   {
>>   	int ret = 0;
>>   	struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup);
>> +	struct mem_cgroup *from = mem_cgroup_from_task(p);
>> +
>> +#if defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM)&&  defined(CONFIG_INET)
>> +	if (from != mem&&  !mem_cgroup_is_root(from)&&
>> +	    res_counter_read_u64(&from->tcp_mem.tcp_memory_allocated, RES_USAGE)) {
>> +		printk(KERN_WARNING "Can't move tasks between cgroups: "
>> +			"Kernel memory held. task: %s\n", p->comm);
>> +		return 1;
>> +	}
>> +#endif
>
> Hmm, the kernel memory is not guaranteed as being held by the 'task' ?
>
> How about
> "Now, moving task between cgroup is disallowed while the source cgroup
>   containes kmem reference." ?
>
> Hmm.. we need to fix this task-move/rmdir issue before production use.
>
>
> Thanks,
> -Kame
>
Hi Kame,

Let me tell you the direction I am going wrt task movement: The only 
reasons I haven't included so far, is that I believe it needs more 
testing, and as you know, I am right now more interested in getting past 
the initial barriers for inclusion. I am committed to fix anything that 
needs to be fixed - stylish or non-stylish before we remove the 
experimental flag.

So what I intend to do, is to basically
* lock the task,
* scan through its file descriptors list,
* identify which of them are sockets,
* cast them to struct sock *,
* see if it has a cgrp associated
* see if cgrp == from

At this point we can decrement sockets allocated by 1 in from, and 
memory_allocated by sk_forward_alloc (increasing by equal quantities in 
the destination cgroup)

I belive it will work.


--
To unsubscribe from this list: send the line "unsubscribe cgroups" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v6 01/10] Basic kernel memory functionality for the Memory Controller
From: Glauber Costa @ 2011-11-28 11:03 UTC (permalink / raw)
  To: KAMEZAWA Hiroyuki
  Cc: linux-kernel, lizf, ebiederm, davem, paul, gthelen, netdev,
	linux-mm, kirill, avagin, devel, eric.dumazet, cgroups
In-Reply-To: <20111128112441.44a6e166.kamezawa.hiroyu@jp.fujitsu.com>

On 11/28/2011 12:24 AM, KAMEZAWA Hiroyuki wrote:
> On Fri, 25 Nov 2011 15:38:07 -0200
> Glauber Costa<glommer@parallels.com>  wrote:
>
>> This patch lays down the foundation for the kernel memory component
>> of the Memory Controller.
>>
>> As of today, I am only laying down the following files:
>>
>>   * memory.independent_kmem_limit
>>   * memory.kmem.limit_in_bytes (currently ignored)
>>   * memory.kmem.usage_in_bytes (always zero)
>>
>> Signed-off-by: Glauber Costa<glommer@parallels.com>
>> Reviewed-by: Kirill A. Shutemov<kirill@shutemov.name>
>> CC: Paul Menage<paul@paulmenage.org>
>> CC: Greg Thelen<gthelen@google.com>
>> ---
>>   Documentation/cgroups/memory.txt |   36 ++++++++++++-
>>   init/Kconfig                     |   14 +++++
>>   mm/memcontrol.c                  |  107 ++++++++++++++++++++++++++++++++++++--
>>   3 files changed, 150 insertions(+), 7 deletions(-)
>>
>> diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
>> index 06eb6d9..bf00cd2 100644
>> --- a/Documentation/cgroups/memory.txt
>> +++ b/Documentation/cgroups/memory.txt
>> @@ -44,8 +44,9 @@ Features:
>>    - oom-killer disable knob and oom-notifier
>>    - Root cgroup has no limit controls.
>>
>> - Kernel memory and Hugepages are not under control yet. We just manage
>> - pages on LRU. To add more controls, we have to take care of performance.
>> + Hugepages is not under control yet. We just manage pages on LRU. To add more
>> + controls, we have to take care of performance. Kernel memory support is work
>> + in progress, and the current version provides basically functionality.
>>
>>   Brief summary of control files.
>>
>> @@ -56,8 +57,11 @@ Brief summary of control files.
>>   				 (See 5.5 for details)
>>    memory.memsw.usage_in_bytes	 # show current res_counter usage for memory+Swap
>>   				 (See 5.5 for details)
>> + memory.kmem.usage_in_bytes	 # show current res_counter usage for kmem only.
>> +				 (See 2.7 for details)
>>    memory.limit_in_bytes		 # set/show limit of memory usage
>>    memory.memsw.limit_in_bytes	 # set/show limit of memory+Swap usage
>> + memory.kmem.limit_in_bytes	 # if allowed, set/show limit of kernel memory
>>    memory.failcnt			 # show the number of memory usage hits limits
>>    memory.memsw.failcnt		 # show the number of memory+Swap hits limits
>>    memory.max_usage_in_bytes	 # show max memory usage recorded
>> @@ -72,6 +76,9 @@ Brief summary of control files.
>>    memory.oom_control		 # set/show oom controls.
>>    memory.numa_stat		 # show the number of memory usage per numa node
>>
>> + memory.independent_kmem_limit	 # select whether or not kernel memory limits are
>> +				   independent of user limits
>> +
>>   1. History
>>
>>   The memory controller has a long history. A request for comments for the memory
>> @@ -255,6 +262,31 @@ When oom event notifier is registered, event will be delivered.
>>     per-zone-per-cgroup LRU (cgroup's private LRU) is just guarded by
>>     zone->lru_lock, it has no lock of its own.
>>
>> +2.7 Kernel Memory Extension (CONFIG_CGROUP_MEM_RES_CTLR_KMEM)
>> +
>> + With the Kernel memory extension, the Memory Controller is able to limit
>> +the amount of kernel memory used by the system. Kernel memory is fundamentally
>> +different than user memory, since it can't be swapped out, which makes it
>> +possible to DoS the system by consuming too much of this precious resource.
>> +Kernel memory limits are not imposed for the root cgroup.
>> +
>> +Memory limits as specified by the standard Memory Controller may or may not
>> +take kernel memory into consideration. This is achieved through the file
>> +memory.independent_kmem_limit. A Value different than 0 will allow for kernel
>> +memory to be controlled separately.
>> +
>> +When kernel memory limits are not independent, the limit values set in
>> +memory.kmem files are ignored.
>> +
>> +Currently no soft limit is implemented for kernel memory. It is future work
>> +to trigger slab reclaim when those limits are reached.
>> +
>> +CAUTION: As of this writing, the kmem extention may prevent tasks from moving
>> +among cgroups. If a task has kmem accounting in a cgroup, the task cannot be
>> +moved until the kmem resource is released. Also, until the resource is fully
>> +released, the cgroup cannot be destroyed. So, please consider your use cases
>> +and set kmem extention config option carefully.
>> +
>
> This seems that memcg 'has' kernel memory limiting feature for all kinds of kmem..
> Could you add a list of "currently controled kmems" section ?
> And update the list in later patch ?
>
> Thanks,
> -Kame
>
>
Hi Kame,

Thanks for your review.
Since none of your comments are blockers, I'd prefer to send follow up 
patches if you don't mind - assuming Dave won't have any restrictions 
himself that would prevent him from picking this series. If I have to 
resend it anyway, I'll be more than happy to address them all in my next 
submission


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* sky2: hw csum failure
From: Vincent Blut @ 2011-11-28 12:10 UTC (permalink / raw)
  To: netdev; +Cc: shemminger, Debian Bug Tracking System

Hi,

[reference: http://bugs.debian.org/609994]

I have a Marvell ethernet controller which presents some failures when
'rx checksumming' is enabled,
here is the model:

$ lspci -vvs 03:00.0
03:00.0 Ethernet controller: Marvell Technology Group Ltd. 88E8053 PCI-E
Gigabit Ethernet Controller (rev 15)
        Subsystem: Micro-Star International Co., Ltd. Marvell 88E8053
Gigabit Ethernet Controller (MSI)
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
ParErr- Stepping- SERR- FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
<TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 32 bytes
        Interrupt: pin A routed to IRQ 44
        Region 0: Memory at fdbfc000 (64-bit, non-prefetchable) [size=16K]
        Region 2: I/O ports at 7c00 [size=256]
        [virtual] Expansion ROM at fda00000 [disabled] [size=128K]
        Capabilities: <access denied>
        Kernel driver in use: sky2

At first I thought it was due to the MTU size, so I tested different
values but unfortunately without positive effect.
Overall this issue appears randomly when the incoming traffic is high. I
tested 2.6.32, 3.1.1, and 3.2-rc3, sadly
all are affected. Finally, the only way to avoid those failures is to
disabled 'rx checksumming' (ethtool -K ethX rx off).

Here is the stack trace:

[   14.615648] sky2 0000:03:00.0: eth1: enabling interface
[   14.616452] ADDRCONF(NETDEV_UP): eth1: link is not ready
[   17.094194] sky2 0000:03:00.0: eth1: Link is up at 1000 Mbps, full
duplex, flow control both
[   17.094887] ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
[   28.080018] eth1: no IPv6 routers present
[  563.816032] sky2 0000:03:00.0: eth1: hung mac 124:22 fifo 195 (150:145)
[  563.816036] sky2 0000:03:00.0: eth1: receiver hang detected
[  567.005422] sky2 0000:03:00.0: eth1: Link is up at 1000 Mbps, full
duplex, flow control both
[ 1040.816314] sky2 0000:03:00.0: eth1: rx error, status 0x7ffc0001
length 1004
[ 2097.401616] sky2 0000:03:00.0: eth1: rx error, status 0x39a339a3 length 0
[ 2097.536950] <unknown>: hw csum failure.
[ 2097.536956] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2097.536959] Call Trace:
[ 2097.536961]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.536972]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.536976]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.536980]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.536984]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.536987]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.536991]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.536995]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.536999]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.537003]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.537007]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.537011]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.537014]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.537031]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.537035]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.537040]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.537044]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.537048]  [<ffffffff8104e01f>] ? __do_softirq+0x13d/0x1a0
[ 2097.537051]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.537056]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.537059]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.537063]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.537066]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.537068]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2097.537075]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2097.537078]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2097.537082]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2097.537086]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2097.537841] <unknown>: hw csum failure.
[ 2097.537844] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2097.537845] Call Trace:
[ 2097.537847]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.537854]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.537857]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.537861]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.537864]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.537868]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.537872]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.537875]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.537879]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.537883]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.537887]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.537890]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.537894]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.537900]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.537905]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.537909]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.537912]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.537916]  [<ffffffff8104e01f>] ? __do_softirq+0x13d/0x1a0
[ 2097.537919]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.537923]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.537926]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.537930]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.537933]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.537935]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2097.537941]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2097.537944]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2097.537947]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2097.537951]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2097.539549] <unknown>: hw csum failure.
[ 2097.539552] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2097.539553] Call Trace:
[ 2097.539555]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.539561]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.539565]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.539568]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.539572]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.539576]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.539579]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.539583]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.539587]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.539591]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.539594]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.539598]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.539604]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.539608]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.539612]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.539616]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.539619]  [<ffffffff8104e01f>] ? __do_softirq+0x13d/0x1a0
[ 2097.539623]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.539626]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.539630]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.539633]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.539637]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.539639]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2097.539644]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2097.539648]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2097.539651]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2097.539655]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2097.540329] <unknown>: hw csum failure.
[ 2097.540332] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2097.540333] Call Trace:
[ 2097.540335]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.540341]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.540345]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.540349]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.540352]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.540356]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.540360]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.540364]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.540367]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.540371]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.540375]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.540379]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.540385]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.540389]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.540393]  [<ffffffff8106e080>] ? clockevents_program_event+0x99/0xb8
[ 2097.540398]  [<ffffffff810656fb>] ? __hrtimer_start_range_ns+0x2d3/0x2e6
[ 2097.540402]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.540405]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.540409]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.540413]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.540416]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.540420]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.540423]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.540425]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2097.540431]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2097.540434]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2097.540437]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2097.540441]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2097.542248] <unknown>: hw csum failure.
[ 2097.542251] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2097.542252] Call Trace:
[ 2097.542254]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.542260]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.542264]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.542267]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.542271]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.542275]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.542279]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.542283]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.542286]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.542290]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.542294]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.542298]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.542304]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.542308]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.542312]  [<ffffffff8106e080>] ? clockevents_program_event+0x99/0xb8
[ 2097.542316]  [<ffffffff810656fb>] ? __hrtimer_start_range_ns+0x2d3/0x2e6
[ 2097.542320]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.542323]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.542326]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.542330]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.542334]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.542337]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.542341]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.542343]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2097.542348]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2097.542352]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2097.542355]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2097.542359]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2097.543036] <unknown>: hw csum failure.
[ 2097.543038] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2097.543040] Call Trace:
[ 2097.543041]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.543048]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.543052]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.543055]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.543059]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.543063]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.543066]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.543070]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.543074]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.543078]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.543082]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.543085]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.543091]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.543096]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.543099]  [<ffffffff8106e080>] ? clockevents_program_event+0x99/0xb8
[ 2097.543103]  [<ffffffff810656fb>] ? __hrtimer_start_range_ns+0x2d3/0x2e6
[ 2097.543107]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.543111]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.543114]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.543118]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.543122]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.543125]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.543128]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.543130]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2097.543136]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2097.543139]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2097.543143]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2097.543146]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2097.795913] <unknown>: hw csum failure.
[ 2097.795919] Pid: 2311, comm: xulrunner-stub Not tainted 3.2.0-rc3 #1
[ 2097.795922] Call Trace:
[ 2097.795924]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.795935]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.795940]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.795943]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.795947]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.795951]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.795955]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.795959]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.795962]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.795967]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.795970]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.795974]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.795990]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.795995]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.796000]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.796032]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.796036]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.796041]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.796044]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.796048]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.796051]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.796053]  <EOI>  [<ffffffff813548d2>] ? system_call_fastpath+0x16/0x1b
[ 2097.803096] <unknown>: hw csum failure.
[ 2097.803102] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2097.803104] Call Trace:
[ 2097.803106]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.803117]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.803121]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.803125]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.803129]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.803132]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.803136]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.803140]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.803144]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.803148]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.803152]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.803156]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.803172]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.803176]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.803181]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.803185]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.803189]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.803193]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.803197]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.803200]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.803204]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.803206]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2097.803212]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2097.803216]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2097.803220]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2097.803223]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2097.865904] <unknown>: hw csum failure.
[ 2097.865910] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2097.865912] Call Trace:
[ 2097.865914]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2097.865925]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2097.865930]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2097.865933]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2097.865937]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.865941]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2097.865945]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2097.865948]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.865952]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2097.865956]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2097.865960]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2097.865964]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2097.865967]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2097.865984]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2097.865988]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2097.865993]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2097.865997]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2097.866001]  [<ffffffff8104e01f>] ? __do_softirq+0x13d/0x1a0
[ 2097.866004]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2097.866009]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2097.866012]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2097.866016]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2097.866019]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2097.866021]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2097.866028]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2097.866031]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2097.866035]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2097.866039]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2105.784575] net_ratelimit: 14 callbacks suppressed
[ 2105.784579] <unknown>: hw csum failure.
[ 2105.784582] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2105.784585] Call Trace:
[ 2105.784586]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2105.784598]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2105.784602]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2105.784606]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2105.784611]  [<ffffffff8110f916>] ? send_sigio_to_task+0xe0/0xed
[ 2105.784615]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2105.784620]  [<ffffffff811ba489>] ? delay_tsc+0x2d/0x74
[ 2105.784624]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2105.784628]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2105.784631]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2105.784636]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2105.784639]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2105.784643]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2105.784660]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2105.784664]  [<ffffffff8126bed0>] ? input_event+0x5c/0x80
[ 2105.784670]  [<ffffffffa022de6b>] ? psmouse_interrupt+0x2a3/0x2c0
[psmouse]
[ 2105.784674]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2105.784679]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2105.784683]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2105.784687]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2105.784692]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2105.784695]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2105.784699]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2105.784702]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2105.784704]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2105.784711]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2105.784714]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2105.784718]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2105.784722]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2105.809944] <unknown>: hw csum failure.
[ 2105.809950] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2105.809953] Call Trace:
[ 2105.809955]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2105.809966]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2105.809970]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2105.809973]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2105.809978]  [<ffffffff8110f916>] ? send_sigio_to_task+0xe0/0xed
[ 2105.809982]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2105.809987]  [<ffffffff811ba489>] ? delay_tsc+0x2d/0x74
[ 2105.809991]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2105.809995]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2105.809998]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2105.810003]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2105.810006]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2105.810010]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2105.810026]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2105.810031]  [<ffffffff8126bed0>] ? input_event+0x5c/0x80
[ 2105.810035]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2105.810040]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2105.810043]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2105.810047]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2105.810056]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2105.810060]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2105.810063]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2105.810067]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2105.810069]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2105.810075]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2105.810079]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2105.810083]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2105.810087]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2114.099063] <unknown>: hw csum failure.
[ 2114.099069] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2114.099072] Call Trace:
[ 2114.099074]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2114.099085]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2114.099089]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2114.099094]  [<ffffffff810142aa>] ? native_sched_clock+0x28/0x5a
[ 2114.099097]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2114.099102]  [<ffffffff8110f916>] ? send_sigio_to_task+0xe0/0xed
[ 2114.099106]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2114.099110]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2114.099114]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2114.099117]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2114.099122]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2114.099125]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2114.099129]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2114.099145]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2114.099149]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2114.099154]  [<ffffffff81065401>] ? enqueue_hrtimer+0x43/0x6a
[ 2114.099157]  [<ffffffff810656fb>] ? __hrtimer_start_range_ns+0x2d3/0x2e6
[ 2114.099162]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2114.099166]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2114.099170]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2114.099174]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2114.099178]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2114.099181]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2114.099184]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2114.099186]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2114.099193]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2114.099196]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2114.099200]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2114.099204]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2114.297922] <unknown>: hw csum failure.
[ 2114.297928] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2114.297930] Call Trace:
[ 2114.297932]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2114.297943]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2114.297948]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2114.297951]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2114.297956]  [<ffffffff8110f916>] ? send_sigio_to_task+0xe0/0xed
[ 2114.297960]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2114.297964]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2114.297968]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2114.297972]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2114.297976]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2114.297980]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2114.297983]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2114.298000]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2114.298004]  [<ffffffff8126bed0>] ? input_event+0x5c/0x80
[ 2114.298008]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2114.298013]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2114.298017]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2114.298021]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2114.298025]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2114.298029]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2114.298032]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2114.298036]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2114.298038]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2114.298044]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2114.298048]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2114.298052]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2114.298055]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2124.098727] <unknown>: hw csum failure.
[ 2124.098733] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2124.098735] Call Trace:
[ 2124.098738]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2124.098749]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2124.098753]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2124.098757]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2124.098762]  [<ffffffff81037f3d>] ? check_preempt_curr+0x25/0x62
[ 2124.098767]  [<ffffffff8104314c>] ? ttwu_do_wakeup+0x51/0xc8
[ 2124.098771]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2124.098775]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2124.098779]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2124.098782]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2124.098787]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2124.098790]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2124.098794]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2124.098811]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2124.098815]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2124.098820]  [<ffffffff81065401>] ? enqueue_hrtimer+0x43/0x6a
[ 2124.098823]  [<ffffffff810656fb>] ? __hrtimer_start_range_ns+0x2d3/0x2e6
[ 2124.098828]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2124.098832]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2124.098836]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2124.098840]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2124.098844]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2124.098847]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2124.098851]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2124.098853]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2124.098859]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2124.098863]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2124.098867]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2124.098870]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2124.297980] <unknown>: hw csum failure.
[ 2124.297987] Pid: 0, comm: swapper Not tainted 3.2.0-rc3 #1
[ 2124.297989] Call Trace:
[ 2124.297991]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2124.298002]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2124.298006]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2124.298010]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2124.298015]  [<ffffffff81037f3d>] ? check_preempt_curr+0x25/0x62
[ 2124.298020]  [<ffffffff8104314c>] ? ttwu_do_wakeup+0x51/0xc8
[ 2124.298023]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2124.298027]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2124.298031]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2124.298035]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2124.298039]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2124.298043]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2124.298047]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2124.298063]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2124.298067]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2124.298072]  [<ffffffff81065401>] ? enqueue_hrtimer+0x43/0x6a
[ 2124.298075]  [<ffffffff810656fb>] ? __hrtimer_start_range_ns+0x2d3/0x2e6
[ 2124.298080]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2124.298084]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2124.298088]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2124.298092]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2124.298096]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2124.298099]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2124.298103]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2124.298105]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2124.298111]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2124.298115]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2124.298119]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2124.298122]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2132.893546] general protection fault: 0000 [#1] SMP
[ 2132.893592] CPU 0
[ 2132.893607] Modules linked in: fuse firewire_sbp2 loop radeon
snd_ca0106 snd_seq_midi snd_seq_midi_event snd_rawmidi rtl8192cu ttm
arc4 snd_ac97_codec rt2500pci rt2x00pci rt2x00lib ac97_bus snd_pcm
rtl8192c_common drm_kms_helper drm rtlwifi mac80211 snd_seq snd_timer
snd_seq_device cfg80211 tpm_tis tpm tpm_bios snd psmouse i2c_algo_bit
power_supply k8temp edac_core evdev eeprom_93cx6 edac_mce_amd pcspkr
serio_raw rfkill soundcore snd_page_alloc i2c_nforce2 processor button
i2c_core ext4 mbcache jbd2 crc16 usbhid sg sr_mod sd_mod hid crc_t10dif
cdrom ohci_hcd sata_sil pata_amd ata_generic sata_nv libata ehci_hcd
usbcore firewire_ohci scsi_mod firewire_core crc_itu_t forcedeth sky2
thermal fan thermal_sys usb_common [last unloaded: scsi_wait_scan]
[ 2132.894174]
[ 2132.894187] Pid: 2641, comm: bash Not tainted 3.2.0-rc3 #1 MICRO-STAR
INTERNATIONAL CO., LTD MS-7125/MS-7125
[ 2132.894258] RIP: 0010:[<ffffffff81117c5b>]  [<ffffffff81117c5b>]
dup_fd+0x1cf/0x285
[ 2132.894317] RSP: 0018:ffff8800b0245df0  EFLAGS: 00010206
[ 2132.894354] RAX: 0000000000000040 RBX: ffff8800ba68e8c0 RCX:
ffffffffffffff7f
[ 2132.894403] RDX: 21a08abfd7091100 RSI: 0000000000000008 RDI:
00000000000000f8
[ 2132.894451] RBP: ffff880036696580 R08: ffff8800366967c0 R09:
ffff8800b02d1000
[ 2132.894500] R10: ffff8800368ad000 R11: 0000000000000000 R12:
0000000000000100
[ 2132.894548] R13: ffff8800377f16c0 R14: 0000000000000001 R15:
0000000000000080
[ 2132.894597] FS:  00007f199e9d6700(0000) GS:ffff8800bfc00000(0000)
knlGS:0000000000000000
[ 2132.894652] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 2132.894692] CR2: 0000000000468000 CR3: 0000000037ef0000 CR4:
00000000000006f0
[ 2132.894740] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
0000000000000000
[ 2132.894789] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
0000000000000400
[ 2132.894838] Process bash (pid: 2641, threadinfo ffff8800b0244000,
task ffff88003736c3c0)
[ 2132.894892] Stack:
[ 2132.894907]  ffff880037c46720 ffff8800377f1740 ffff8800377f1740
ffff8800377f16c8
[ 2132.894964]  ffff880037c46720 0000000001200011 ffff880037c46720
0000000000000000
[ 2132.895020]  0000000000000000 ffff880037c46930 00007f199e9d69d0
ffffffff81047326
[ 2132.895077] Call Trace:
[ 2132.895098]  [<ffffffff81047326>] ? copy_process+0x59f/0x10ca
[ 2132.895139]  [<ffffffff81048021>] ? do_fork+0xda/0x219
[ 2132.895177]  [<ffffffff8110183d>] ? fd_install+0x27/0x4e
[ 2132.895216]  [<ffffffff81354bf3>] ? stub_clone+0x13/0x20
[ 2132.895254]  [<ffffffff813548d2>] ? system_call_fastpath+0x16/0x1b
[ 2132.895296] Code: 89 d7 48 98 48 89 c1 f3 a4 48 89 c1 31 c0 48 8b 55
10 49 8b 70 10 48 89 d7 f3 a4 44 89 e7 31 f6 eb 3d 49 8b 14 02 48 85 d2
74 07 <3e> 48 ff 42 30 eb 21 48 63 ce 4c 8b 45 18 4d 89 f7 49 89 cb 83
[ 2132.895527] RIP  [<ffffffff81117c5b>] dup_fd+0x1cf/0x285
[ 2132.895567]  RSP <ffff8800b0245df0>
[ 2132.915113] ---[ end trace 3541bcacd8b98988 ]---
[ 2134.302779] <unknown>: hw csum failure.
[ 2134.302785] Pid: 0, comm: swapper Tainted: G      D      3.2.0-rc3 #1
[ 2134.302788] Call Trace:
[ 2134.302790]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2134.302801]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2134.302805]  [<ffffffff812cb3da>] ? tcp_checksum_complete_user+0x40/0x4e
[ 2134.302809]  [<ffffffff812cdcbf>] ? tcp_rcv_established+0x56f/0x683
[ 2134.302814]  [<ffffffff81044050>] ? enqueue_task_fair+0x129/0x262
[ 2134.302818]  [<ffffffff812d50bc>] ? tcp_v4_do_rcv+0x1bd/0x3eb
[ 2134.302823]  [<ffffffff811ba489>] ? delay_tsc+0x2d/0x74
[ 2134.302827]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2134.302831]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2134.302834]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2134.302839]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2134.302843]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2134.302846]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2134.302863]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2134.302867]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2134.302871]  [<ffffffff81065401>] ? enqueue_hrtimer+0x43/0x6a
[ 2134.302875]  [<ffffffff810656fb>] ? __hrtimer_start_range_ns+0x2d3/0x2e6
[ 2134.302880]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2134.302883]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2134.302887]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2134.302892]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2134.302895]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2134.302899]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2134.302902]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2134.302904]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2134.302911]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2134.302914]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2134.302918]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2134.302922]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f
[ 2181.645236] <unknown>: hw csum failure.
[ 2181.645243] Pid: 0, comm: swapper Tainted: G      D      3.2.0-rc3 #1
[ 2181.645245] Call Trace:
[ 2181.645247]  <IRQ>  [<ffffffff8128f5d9>] ? netdev_rx_csum_fault+0x29/0x31
[ 2181.645259]  [<ffffffff8128ae7e>] ?
__skb_checksum_complete_head+0x44/0x56
[ 2181.645263]  [<ffffffff812d50f6>] ? tcp_v4_do_rcv+0x1f7/0x3eb
[ 2181.645267]  [<ffffffff812d6708>] ? tcp_v4_rcv+0x449/0x6f5
[ 2181.645272]  [<ffffffff810376d8>] ? __wake_up_common+0x41/0x78
[ 2181.645276]  [<ffffffff812b9d1a>] ? ip_local_deliver_finish+0x13d/0x1aa
[ 2181.645280]  [<ffffffff8128ee04>] ? __netif_receive_skb+0x44c/0x490
[ 2181.645284]  [<ffffffff81293800>] ? netif_receive_skb+0x67/0x6d
[ 2181.645288]  [<ffffffff81293d03>] ? napi_gro_receive+0x1f/0x2c
[ 2181.645292]  [<ffffffff812938d5>] ? napi_skb_finish+0x1c/0x31
[ 2181.645309]  [<ffffffffa0029ab6>] ? sky2_poll+0x76c/0xa0a [sky2]
[ 2181.645313]  [<ffffffff81293e2e>] ? net_rx_action+0xa8/0x207
[ 2181.645317]  [<ffffffff81065401>] ? enqueue_hrtimer+0x43/0x6a
[ 2181.645321]  [<ffffffff810656fb>] ? __hrtimer_start_range_ns+0x2d3/0x2e6
[ 2181.645326]  [<ffffffff8104dfa6>] ? __do_softirq+0xc4/0x1a0
[ 2181.645330]  [<ffffffff8109666d>] ? handle_irq_event_percpu+0x166/0x184
[ 2181.645333]  [<ffffffff81356b2c>] ? call_softirq+0x1c/0x30
[ 2181.645338]  [<ffffffff8100f9f7>] ? do_softirq+0x3f/0x79
[ 2181.645342]  [<ffffffff8104dd76>] ? irq_exit+0x44/0xb5
[ 2181.645345]  [<ffffffff8100f342>] ? do_IRQ+0x94/0xaa
[ 2181.645349]  [<ffffffff8134f62e>] ? common_interrupt+0x6e/0x6e
[ 2181.645351]  <EOI>  [<ffffffff8102b850>] ? native_safe_halt+0x2/0x3
[ 2181.645357]  [<ffffffff81015039>] ? default_idle+0x4b/0x84
[ 2181.645361]  [<ffffffff8100ddcb>] ? cpu_idle+0xb9/0xef
[ 2181.645365]  [<ffffffff816a9c3b>] ? start_kernel+0x3cc/0x3d7
[ 2181.645368]  [<ffffffff816a93c8>] ? x86_64_start_kernel+0x102/0x10f

Thanks,
Vincent

^ permalink raw reply

* Re: [Socketcan-users] [PATCH net-next v2 1/4] can: cc770: add driver core for the Bosch CC770 and Intel AN82527
From: Marc Kleine-Budde @ 2011-11-28 11:28 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: netdev, socketcan-users, linux-can
In-Reply-To: <1322214204-1121-2-git-send-email-wg@grandegger.com>

[-- Attachment #1: Type: text/plain, Size: 43026 bytes --]

On 11/25/2011 10:43 AM, Wolfgang Grandegger wrote:
> Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
> ---
>  drivers/net/can/Kconfig            |    2 +
>  drivers/net/can/Makefile           |    1 +
>  drivers/net/can/cc770/Kconfig      |    3 +
>  drivers/net/can/cc770/Makefile     |    7 +
>  drivers/net/can/cc770/cc770.c      |  895 ++++++++++++++++++++++++++++++++++++
>  drivers/net/can/cc770/cc770.h      |  234 ++++++++++
>  include/linux/can/platform/cc770.h |   33 ++
>  7 files changed, 1175 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/can/cc770/Kconfig
>  create mode 100644 drivers/net/can/cc770/Makefile
>  create mode 100644 drivers/net/can/cc770/cc770.c
>  create mode 100644 drivers/net/can/cc770/cc770.h
>  create mode 100644 include/linux/can/platform/cc770.h

I don't know the hardware, but the code looks good to me, some comments:
- The driver doesn't use NAPI, can this be added
- The rx-handlers have a while(1) loop
  For NAPI you have to add accounting, for the non NAPI case it would
  be good, too.
- I think you can move a large number of lines from the .h file into
  the driver. Code that's not used in the different binding drivers.

More comments inline (mostly nitpicking)

Marc
> 
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index f6c98fb..ab45758 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -116,6 +116,8 @@ source "drivers/net/can/sja1000/Kconfig"
>  
>  source "drivers/net/can/c_can/Kconfig"
>  
> +source "drivers/net/can/cc770/Kconfig"
> +
>  source "drivers/net/can/usb/Kconfig"
>  
>  source "drivers/net/can/softing/Kconfig"
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 24ebfe8..938be37 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -14,6 +14,7 @@ obj-y				+= softing/
>  obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
>  obj-$(CONFIG_CAN_MSCAN)		+= mscan/
>  obj-$(CONFIG_CAN_C_CAN)		+= c_can/
> +obj-$(CONFIG_CAN_CC770)		+= cc770/
>  obj-$(CONFIG_CAN_AT91)		+= at91_can.o
>  obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
>  obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
> diff --git a/drivers/net/can/cc770/Kconfig b/drivers/net/can/cc770/Kconfig
> new file mode 100644
> index 0000000..225131b
> --- /dev/null
> +++ b/drivers/net/can/cc770/Kconfig
> @@ -0,0 +1,3 @@
> +menuconfig CAN_CC770
> +	tristate "Bosch CC770 and Intel AN82527 devices"
> +	depends on CAN_DEV && HAS_IOMEM
> diff --git a/drivers/net/can/cc770/Makefile b/drivers/net/can/cc770/Makefile
> new file mode 100644
> index 0000000..34e8180
> --- /dev/null
> +++ b/drivers/net/can/cc770/Makefile
> @@ -0,0 +1,7 @@
> +#
> +#  Makefile for the Bosch CC770 CAN controller drivers.
> +#
> +
> +obj-$(CONFIG_CAN_CC770) += cc770.o
> +
> +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
> diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
> new file mode 100644
> index 0000000..47a6965
> --- /dev/null
> +++ b/drivers/net/can/cc770/cc770.c
> @@ -0,0 +1,895 @@
> +/*
> + * cc770.c - Bosch CC770 and Intel AN82527 network device driver
> + *
> + * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
> + *
> + * Derived from the old Socket-CAN i82527 driver:
> + *
> + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of Volkswagen nor the names of its contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
> + *
> + * Alternatively, provided that this notice is retained in full, this
> + * software may be distributed under the terms of the GNU General
> + * Public License ("GPL") version 2, in which case the provisions of the
> + * GPL apply INSTEAD OF those given above.
> + *
> + * The provided data structures and external interfaces from this code
> + * are not restricted to be used by modules with a GPL compatible license.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + *
> + * Send feedback to <socketcan-users@lists.berlios.de>

please remove :)

> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/types.h>
> +#include <linux/fcntl.h>
> +#include <linux/interrupt.h>
> +#include <linux/ptrace.h>
> +#include <linux/string.h>
> +#include <linux/errno.h>
> +#include <linux/netdevice.h>
> +#include <linux/if_arp.h>
> +#include <linux/if_ether.h>
> +#include <linux/skbuff.h>
> +#include <linux/delay.h>
> +
> +#include <linux/can.h>
> +#include <linux/can/dev.h>
> +#include <linux/can/error.h>
> +#include <linux/can/dev.h>
> +#include <linux/can/platform/cc770.h>
> +
> +#include "cc770.h"

Can you move all the definitions that are not needed in the other
drivers (e.g. ISA, etc.) into this .c file?

> +
> +#define DRV_NAME  "cc770"
> +
> +MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver");
> +
> +/*
> + * The CC770 is a CAN controller from Bosch, which is 100% compatible
> + * with the AN82527 from Intel, but with "bugs" being fixed and some
> + * additional functionality, mainly:
> + *
> + * 1. RX and TX error counters are readable.
> + * 2. Support of silent (listen-only) mode.
> + * 3. Message object 15 can receive all types of frames, also RTR and EFF.
> + *
> + * Details are available from Bosch's "CC770_Product_Info_2007-01.pdf",
> + * which explains in detail the compatibility between the CC770 and the
> + * 82527. This driver use the additional functionality 3. on real CC770
> + * devices. Unfortunately, the CC770 does still not store the message
> + * identifier of received remote transmission request frames and
> + * therefore it's set to 0.
> + *
> + * The message objects 1..14 can be used for TX and RX while the message
> + * objects 15 is optimized for RX. It has a shadow register for reliable
> + * data receiption under heavy bus load. Therefore it makes sense to use
> + * this message object for the needed use case. The frame type (EFF/SFF)
> + * for the message object 15 can be defined via kernel module parameter
> + * "msgobj15_eff". If not equal 0, it will receive 29-bit EFF frames,
> + * otherwise 11 bit SFF messages.
> + */
> +static int msgobj15_eff;
> +module_param(msgobj15_eff, int, S_IRUGO);
> +MODULE_PARM_DESC(msgobj15_eff, "Extended 29-bit frames for message object 15 "
> +		 "(default: 11-bit standard frames)");
> +
> +static int i82527_compat;
> +module_param(i82527_compat, int, S_IRUGO);
> +MODULE_PARM_DESC(i82527_compat, "Strict Intel 82527 comptibility mode "
> +		 "without using additional functions");
> +
> +/*
> + * This driver uses the last 5 message objects 11..15. The definitions
> + * and structure below allows to configure and assign them to the real
> + * message object.
> + */
> +static unsigned char cc770_obj_flags[CC770_OBJ_MAX] = {
> +	[CC770_OBJ_RX0] = CC770_OBJ_FLAG_RX,
> +	[CC770_OBJ_RX1] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_EFF,
> +	[CC770_OBJ_RX_RTR0] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_RTR,
> +	[CC770_OBJ_RX_RTR1] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_RTR |
> +			      CC770_OBJ_FLAG_EFF,
> +	[CC770_OBJ_TX] = 0,
> +};

Is is worth the trouble making this a per device instance option? In a
OF-Tree world should this become an "attribute" (or what's the correct
of-tree word for it?)

> +
> +static struct can_bittiming_const cc770_bittiming_const = {
> +	.name = DRV_NAME,
> +	.tseg1_min = 1,
> +	.tseg1_max = 16,
> +	.tseg2_min = 1,
> +	.tseg2_max = 8,
> +	.sjw_max = 4,
> +	.brp_min = 1,
> +	.brp_max = 64,
> +	.brp_inc = 1,
> +};
> +
> +static inline int intid2obj(unsigned int intid)
> +{
> +	if (intid == 2)
> +		return 0;
> +	else
> +		return MSGOBJ_LAST + 2 - intid;
> +}
> +
> +static void enable_all_objs(const struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	u8 msgcfg;
> +	unsigned char obj_flags;
> +	unsigned int o, mo;
> +
> +	for (o = 0; o <  CC770_OBJ_MAX; o++) {
                         ^^^^^^^^^^^^^

what about ARRAY_SIZE(priv->obj_flags)

nitpick:
o is probalby short for object, but usually we use "i" for a for loop

> +		obj_flags = priv->obj_flags[o];
> +		mo = obj2msgobj(o);
> +
> +		if (obj_flags & CC770_OBJ_FLAG_RX) {
> +			/*
> +			 * We don't need extra objects for RTR and EFF if
> +			 * the additional CC770 functions are enabled.
> +			 */
> +			if (priv->control_normal_mode & CTRL_EAF) {
> +				if (o > 0)
> +					continue;
> +				netdev_dbg(dev, "Message object %d for "
> +					   "RX data, RTR, SFF and EFF\n", mo);
> +			} else {
> +				netdev_dbg(dev,
> +					   "Message object %d for RX %s %s\n",
> +					   mo, obj_flags & CC770_OBJ_FLAG_RTR ?
> +					   "RTR" : "data",
> +					   obj_flags & CC770_OBJ_FLAG_EFF ?
> +					   "EFF" : "SFF");
> +			}
> +
> +			if (obj_flags & CC770_OBJ_FLAG_EFF)
> +				msgcfg = MSGCFG_XTD;
> +			else
> +				msgcfg = 0;
> +			if (obj_flags & CC770_OBJ_FLAG_RTR)
> +				msgcfg |= MSGCFG_DIR;
> +
> +			cc770_write_reg(priv, msgobj[mo].config, msgcfg);
> +			cc770_write_reg(priv, msgobj[mo].ctrl0,
> +					MSGVAL_SET | TXIE_RES |
> +					RXIE_SET | INTPND_RES);
> +
> +			if (obj_flags & CC770_OBJ_FLAG_RTR)
> +				cc770_write_reg(priv, msgobj[mo].ctrl1,
> +						NEWDAT_RES | CPUUPD_SET |
> +						TXRQST_RES | RMTPND_RES);
> +			else
> +				cc770_write_reg(priv, msgobj[mo].ctrl1,
> +						NEWDAT_RES | MSGLST_RES |
> +						TXRQST_RES | RMTPND_RES);
> +		} else {
> +			netdev_dbg(dev, "Message object %d for "
> +				   "TX data, RTR, SFF and EFF\n", mo);
> +
> +			cc770_write_reg(priv, msgobj[mo].ctrl1,
> +					RMTPND_RES | TXRQST_RES |
> +					CPUUPD_RES | NEWDAT_RES);
> +			cc770_write_reg(priv, msgobj[mo].ctrl0,
> +					MSGVAL_RES | TXIE_RES |
> +					RXIE_RES | INTPND_RES);
> +		}
> +	}
> +}
> +
> +static void disable_all_objs(const struct cc770_priv *priv)
> +{
> +	int i, mo;

here you use "i"

> +
> +	for (i = 0; i <  CC770_OBJ_MAX; i++) {

ARRAY_SIZE?

> +		mo = obj2msgobj(i);
> +
> +		if (priv->obj_flags[i] & CC770_OBJ_FLAG_RX) {
> +			if (i > 0 && priv->control_normal_mode & CTRL_EAF)
> +				continue;
> +
> +			cc770_write_reg(priv, msgobj[mo].ctrl1,
> +					NEWDAT_RES | MSGLST_RES |
> +					TXRQST_RES | RMTPND_RES);
> +			cc770_write_reg(priv, msgobj[mo].ctrl0,
> +					MSGVAL_RES | TXIE_RES |
> +					RXIE_RES | INTPND_RES);
> +		} else {
> +			/* Clear message object for send */
> +			cc770_write_reg(priv, msgobj[mo].ctrl1,
> +					RMTPND_RES | TXRQST_RES |
> +					CPUUPD_RES | NEWDAT_RES);
> +			cc770_write_reg(priv, msgobj[mo].ctrl0,
> +					MSGVAL_RES | TXIE_RES |
> +					RXIE_RES | INTPND_RES);
> +		}
> +	}
> +}
> +
> +static void set_reset_mode(struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +
> +	/* Enable configuration and puts chip in bus-off, disable interrupts */
> +	cc770_write_reg(priv, control, CTRL_CCE | CTRL_INI);
> +
> +	priv->can.state = CAN_STATE_STOPPED;
> +
> +	/* Clear interrupts */
> +	cc770_read_reg(priv, interrupt);
> +
> +	/* Clear status register */
> +	cc770_write_reg(priv, status, 0);
> +
> +	/* Disable all used message objects */
> +	disable_all_objs(priv);
> +}
> +
> +static void set_normal_mode(struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +
> +	/* Clear interrupts */
> +	cc770_read_reg(priv, interrupt);
> +
> +	/* Clear status register and pre-set last error code */
> +	cc770_write_reg(priv, status, STAT_LEC_MASK);
> +
> +	/* Enable all used message objects*/
> +	enable_all_objs(dev);
> +
> +	/*
> +	 * Clear bus-off, interrupts only for errors,
> +	 * not for status change
> +	 */
> +	cc770_write_reg(priv, control, priv->control_normal_mode);
> +
> +	priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +}
> +
> +static void chipset_init(struct cc770_priv *priv)
> +{
> +	int mo, id, data;
> +
> +	/* Enable configuration and put chip in bus-off, disable interrupts */
> +	cc770_write_reg(priv, control, (CTRL_CCE | CTRL_INI));
> +
> +	/* Set CLKOUT divider and slew rates */
> +	cc770_write_reg(priv, clkout, priv->clkout);
> +
> +	/* Configure CPU interface / CLKOUT enable */
> +	cc770_write_reg(priv, cpu_interface, priv->cpu_interface);
> +
> +	/* Set bus configuration  */
> +	cc770_write_reg(priv, bus_config, priv->bus_config);
> +
> +	/* Clear interrupts */
> +	cc770_read_reg(priv, interrupt);
> +
> +	/* Clear status register */
> +	cc770_write_reg(priv, status, 0);
> +
> +	/* Clear and invalidate message objects */
> +	for (mo = MSGOBJ_FIRST; mo <= MSGOBJ_LAST; mo++) {
> +		cc770_write_reg(priv, msgobj[mo].ctrl0,
> +				INTPND_UNC | RXIE_RES |
> +				TXIE_RES | MSGVAL_RES);
> +		cc770_write_reg(priv, msgobj[mo].ctrl0,
> +				INTPND_RES | RXIE_RES |
> +				TXIE_RES | MSGVAL_RES);
> +		cc770_write_reg(priv, msgobj[mo].ctrl1,
> +				NEWDAT_RES | MSGLST_RES |
> +				TXRQST_RES | RMTPND_RES);
> +		for (data = 0; data < 8; data++)
> +			cc770_write_reg(priv, msgobj[mo].data[data], 0);
> +		for (id = 0; id < 4; id++)
> +			cc770_write_reg(priv, msgobj[mo].id[id], 0);
> +		cc770_write_reg(priv, msgobj[mo].config, 0);
> +	}
> +
> +	/* Set all global ID masks to "don't care" */
> +	cc770_write_reg(priv, global_mask_std[0], 0);
> +	cc770_write_reg(priv, global_mask_std[1], 0);
> +	cc770_write_reg(priv, global_mask_ext[0], 0);
> +	cc770_write_reg(priv, global_mask_ext[1], 0);
> +	cc770_write_reg(priv, global_mask_ext[2], 0);
> +	cc770_write_reg(priv, global_mask_ext[3], 0);
> +
> +}
> +
> +static int cc770_probe_chip(struct net_device *dev)

nitpick: This chip returns 1 on success and 0 on failure, IMHO unusual
return value. Why not make it return -ENODEV in case of failure?

> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +
> +	/* Enable configuration, put chip in bus-off, disable ints */
> +	cc770_write_reg(priv, control, CTRL_CCE | CTRL_EAF | CTRL_INI);
> +	/* Configure cpu interface / CLKOUT disable */
> +	cc770_write_reg(priv, cpu_interface, priv->cpu_interface);
> +
> +	/*
> +	 * Check if hardware reset is still inactive or maybe there
> +	 * is no chip in this address space
> +	 */
> +	if (cc770_read_reg(priv, cpu_interface) & CPUIF_RST) {
> +		netdev_info(dev, "probing @0x%p failed (reset)\n",
> +			    priv->reg_base);
> +		return 0;
> +	}
> +
> +	/* Write and read back test pattern */

Are these Hex numbers arbitrary values?

> +	cc770_write_reg(priv, msgobj[1].data[1], 0x25);
> +	cc770_write_reg(priv, msgobj[2].data[3], 0x52);
> +	cc770_write_reg(priv, msgobj[10].data[6], 0xc3);
> +	if ((cc770_read_reg(priv, msgobj[1].data[1]) != 0x25) ||
> +	    (cc770_read_reg(priv, msgobj[2].data[3]) != 0x52) ||
> +	    (cc770_read_reg(priv, msgobj[10].data[6]) != 0xc3)) {
> +		netdev_info(dev, "probing @0x%p failed (pattern)\n",
> +			    priv->reg_base);
> +		return 0;
> +	}
> +
> +	/* Check if this chip is a CC770 supporting additional functions */
> +	if (cc770_read_reg(priv, control) & CTRL_EAF)
> +		priv->control_normal_mode |= CTRL_EAF;
> +
> +	return 1;
> +}
> +
> +static void cc770_start(struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +
> +	/* leave reset mode */
> +	if (priv->can.state != CAN_STATE_STOPPED)
> +		set_reset_mode(dev);
> +
> +	/* leave reset mode */
> +	set_normal_mode(dev);
> +}
> +
> +static int cc770_set_mode(struct net_device *dev, enum can_mode mode)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +
> +	if (!priv->open_time)
> +		return -EINVAL;
> +
> +	switch (mode) {
> +	case CAN_MODE_START:
> +		cc770_start(dev);
> +		if (netif_queue_stopped(dev))
> +			netif_wake_queue(dev);

The "if (netif_queue_stopped(dev))" is not needed.

> +		break;
> +
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
> +}
> +
> +static int cc770_set_bittiming(struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	struct can_bittiming *bt = &priv->can.bittiming;
> +	u8 btr0, btr1;
> +
> +	btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
> +	btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
> +		(((bt->phase_seg2 - 1) & 0x7) << 4);
> +	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
> +		btr1 |= 0x80;
> +
> +	netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
> +
> +	cc770_write_reg(priv, bit_timing_0, btr0);
> +	cc770_write_reg(priv, bit_timing_1, btr1);
> +
> +	return 0;
> +}
> +
> +static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	struct net_device_stats *stats = &dev->stats;
> +	struct can_frame *cf = (struct can_frame *)skb->data;
> +	unsigned int mo = obj2msgobj(CC770_OBJ_TX);
> +	u8 dlc, rtr;
> +	u32 id;
> +	int i;
> +
> +	if (can_dropped_invalid_skb(dev, skb))
> +		return NETDEV_TX_OK;
> +
> +	if ((cc770_read_reg(priv,
> +			    msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) {
> +		netdev_err(dev, "TX register is still occupied!\n");
> +		return NETDEV_TX_BUSY;
> +	}
> +
> +	netif_stop_queue(dev);
> +
> +	dlc = cf->can_dlc;
> +	id = cf->can_id;
> +	if (cf->can_id & CAN_RTR_FLAG)
> +		rtr = 0;
> +	else
> +		rtr = MSGCFG_DIR;
> +	cc770_write_reg(priv, msgobj[mo].ctrl1,
> +			RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES);
> +	cc770_write_reg(priv, msgobj[mo].ctrl0,
> +			MSGVAL_SET | TXIE_SET | RXIE_RES | INTPND_RES);
> +	if (id & CAN_EFF_FLAG) {
> +		id &= CAN_EFF_MASK;
> +		cc770_write_reg(priv, msgobj[mo].config,
> +				(dlc << 4) + rtr + MSGCFG_XTD);

+ is the same as | here, but IMHO bitwise or is more common coding styele.

> +		cc770_write_reg(priv, msgobj[mo].id[3],
> +				(id << 3) & 0xFFU);
> +		cc770_write_reg(priv, msgobj[mo].id[2],
> +				(id >> 5) & 0xFFU);
> +		cc770_write_reg(priv, msgobj[mo].id[1],
> +				(id >> 13) & 0xFFU);
> +		cc770_write_reg(priv, msgobj[mo].id[0],
> +				(id >> 21) & 0xFFU);

msgobj[].id[] is an u8, so & 0xff is not needed.

> +	} else {
> +		id &= CAN_SFF_MASK;
> +		cc770_write_reg(priv, msgobj[mo].config,
> +				(dlc << 4) + rtr);
> +		cc770_write_reg(priv, msgobj[mo].id[0],
> +				(id >> 3) & 0xFFU);
> +		cc770_write_reg(priv, msgobj[mo].id[1],
> +				(id << 5) & 0xFFU);
dito
> +	}
> +
> +	dlc &= 0x0f;		/* restore length only */

is this needed? The dlc should be valid.

> +	for (i = 0; i < dlc; i++)
> +		cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]);
> +
> +	cc770_write_reg(priv, msgobj[mo].ctrl1,
> +			RMTPND_RES | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
> +
> +	stats->tx_bytes += dlc;
> +
> +	can_put_echo_skb(skb, dev, 0);
> +
> +	/*
> +	 * HM: We had some cases of repeated IRQs so make sure the

Who is HM?

> +	 * INT is acknowledged I know it's already further up, but
> +	 * doing again fixed the issue
> +	 */
> +	cc770_write_reg(priv, msgobj[mo].ctrl0,
> +			MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES);
> +
> +	return NETDEV_TX_OK;
> +}
> +
> +static void cc770_rx(struct net_device *dev, unsigned int mo, u8 ctrl1)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	struct net_device_stats *stats = &dev->stats;
> +	struct can_frame *cf;
> +	struct sk_buff *skb;
> +	u8 config;
> +	u32 id;
> +	int i;
> +
> +	skb = alloc_can_skb(dev, &cf);
> +	if (skb == NULL)
!skb
> +		return;
> +
> +	config = cc770_read_reg(priv, msgobj[mo].config);
> +
> +	if (ctrl1 & RMTPND_SET) {
> +		/*
> +		 * Unfortunately, the chip does not store the real message
> +		 * identifier of the received remote transmission request
> +		 * frame. Therefore we set it to 0.

What a bug!

> +		 */
> +		cf->can_id = CAN_RTR_FLAG;
> +		if (config & MSGCFG_XTD)
> +			cf->can_id |= CAN_EFF_FLAG;
> +		cf->can_dlc = 0;
> +	} else {
> +		if (config & MSGCFG_XTD) {
> +			id = cc770_read_reg(priv, msgobj[mo].id[3]);
> +			id |= cc770_read_reg(priv, msgobj[mo].id[2]) << 8;
> +			id |= cc770_read_reg(priv, msgobj[mo].id[1]) << 16;
> +			id |= cc770_read_reg(priv, msgobj[mo].id[0]) << 24;
> +			id >>= 3;
> +			id |= CAN_EFF_FLAG;
> +		} else {
> +			id = cc770_read_reg(priv, msgobj[mo].id[1]);
> +			id |= cc770_read_reg(priv, msgobj[mo].id[0]) << 8;
> +			id >>= 5;
> +		}
> +
> +		cf->can_id = id;
> +		cf->can_dlc = get_can_dlc((config & 0xf0) >> 4);
> +		for (i = 0; i < cf->can_dlc; i++)
> +			cf->data[i] = cc770_read_reg(priv, msgobj[mo].data[i]);
> +	}
> +	netif_rx(skb);
> +
> +	stats->rx_packets++;
> +	stats->rx_bytes += cf->can_dlc;
> +}
> +
> +static int cc770_err(struct net_device *dev, u8 status)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	struct net_device_stats *stats = &dev->stats;
> +	struct can_frame *cf;
> +	struct sk_buff *skb;
> +	u8 lec;
> +
> +	netdev_dbg(dev, "status interrupt (%#x)\n", status);
> +
> +	skb = alloc_can_err_skb(dev, &cf);
> +	if (skb == NULL)
!skb
> +		return -ENOMEM;
> +
> +	if (status & STAT_BOFF) {
> +		/* Disable interrupts */
> +		cc770_write_reg(priv, control, CTRL_INI);
> +		cf->can_id |= CAN_ERR_BUSOFF;
> +		priv->can.state = CAN_STATE_BUS_OFF;
> +		can_bus_off(dev);
> +	} else if (status & STAT_WARN) {
> +		cf->can_id |= CAN_ERR_CRTL;
> +		cf->data[1] = CAN_ERR_CRTL_RX_WARNING | CAN_ERR_CRTL_TX_WARNING;
> +		priv->can.state = CAN_STATE_ERROR_WARNING;
> +		priv->can.can_stats.error_warning++;
> +	}
> +
> +	lec = status & STAT_LEC_MASK;
> +	if (lec < 7 && lec > 0) {
> +		if (lec == STAT_LEC_ACK) {
> +			cf->can_id |= CAN_ERR_ACK;
> +		} else {
> +			cf->can_id |= CAN_ERR_PROT;
> +			switch (lec) {
> +			case STAT_LEC_STUFF:
> +				cf->data[2] |= CAN_ERR_PROT_STUFF;
> +				break;
> +			case STAT_LEC_FORM:
> +				cf->data[2] |= CAN_ERR_PROT_FORM;
> +				break;
> +			case STAT_LEC_BIT1:
> +				cf->data[2] |= CAN_ERR_PROT_BIT1;
> +				break;
> +			case STAT_LEC_BIT0:
> +				cf->data[2] |= CAN_ERR_PROT_BIT0;
> +				break;
> +			case STAT_LEC_CRC:
> +				cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
> +				break;
> +			}
> +		}
> +	}
> +
> +	netif_rx(skb);
> +
> +	stats->rx_packets++;
> +	stats->rx_bytes += cf->can_dlc;
> +
> +	return 0;
> +}
> +
> +static int cc770_status_interrupt(struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	u8 status;
> +
> +	status = cc770_read_reg(priv, status);
> +	/* Reset the status register including RXOK and TXOK */
> +	cc770_write_reg(priv, status, STAT_LEC_MASK);
> +
> +	if (status & (STAT_WARN | STAT_BOFF) ||
> +	    (status & STAT_LEC_MASK) != STAT_LEC_MASK) {
> +		cc770_err(dev, status);
> +		return status & STAT_BOFF;
> +	}
> +
> +	return 0;
> +}
> +
> +static void cc770_rx_interrupt(struct net_device *dev, unsigned int o)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	struct net_device_stats *stats = &dev->stats;
> +	unsigned int mo = obj2msgobj(o);
> +	u8 ctrl1;
> +
> +	while (1) {

What about limiting this?

> +		ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
> +
> +		if (!(ctrl1 & NEWDAT_SET))  {
> +			/* Check for RTR if additional functions are enabled */
> +			if (priv->control_normal_mode & CTRL_EAF) {
> +				if (!(cc770_read_reg(priv, msgobj[mo].ctrl0) &
> +				      INTPND_SET))
> +					break;
> +			} else {
> +				break;
> +			}
> +		}
> +
> +		if (ctrl1 & MSGLST_SET) {
> +			stats->rx_over_errors++;
> +			stats->rx_errors++;
> +		}
> +		if (mo < MSGOBJ_LAST)
> +			cc770_write_reg(priv, msgobj[mo].ctrl1,
> +					NEWDAT_RES | MSGLST_RES |
> +					TXRQST_UNC | RMTPND_UNC);
> +		cc770_rx(dev, mo, ctrl1);
> +
> +		cc770_write_reg(priv, msgobj[mo].ctrl0,
> +				MSGVAL_SET | TXIE_RES |
> +				RXIE_SET | INTPND_RES);
> +		cc770_write_reg(priv, msgobj[mo].ctrl1,
> +				NEWDAT_RES | MSGLST_RES |
> +				TXRQST_RES | RMTPND_RES);
> +	}
> +}
> +
> +static void cc770_rtr_interrupt(struct net_device *dev, unsigned int o)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	unsigned int mo = obj2msgobj(o);
> +	u8 ctrl0, ctrl1;
> +
> +	while (1) {

dito...?

> +		ctrl0 = cc770_read_reg(priv, msgobj[mo].ctrl0);
> +		if (!(ctrl0 & INTPND_SET))
> +			break;
> +
> +		ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
> +		cc770_rx(dev, mo, ctrl1);
> +
> +		cc770_write_reg(priv, msgobj[mo].ctrl0,
> +				MSGVAL_SET | TXIE_RES |
> +				RXIE_SET | INTPND_RES);
> +		cc770_write_reg(priv, msgobj[mo].ctrl1,
> +				NEWDAT_RES | CPUUPD_SET |
> +				TXRQST_RES | RMTPND_RES);
> +	}
> +}
> +
> +static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	struct net_device_stats *stats = &dev->stats;
> +	unsigned int mo = obj2msgobj(o);
> +
> +	/* Nothing more to send, switch off interrupts */
> +	cc770_write_reg(priv, msgobj[mo].ctrl0,
> +			MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
> +	/*
> +	 * We had some cases of repeated IRQ so make sure the
> +	 * INT is acknowledged
> +	 */
> +	cc770_write_reg(priv, msgobj[mo].ctrl0,
> +			MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES);
> +
> +	stats->tx_packets++;
> +	can_get_echo_skb(dev, 0);
> +	netif_wake_queue(dev);
> +}
> +
> +irqreturn_t cc770_interrupt(int irq, void *dev_id)
> +{
> +	struct net_device *dev = (struct net_device *)dev_id;
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	u8 intid;
> +	int o, n = 0;
> +
> +	/* Shared interrupts and IRQ off? */
> +	if (priv->can.state == CAN_STATE_STOPPED)
> +		return IRQ_NONE;
> +
> +	if (priv->pre_irq)
> +		priv->pre_irq(priv);
> +
> +	while (n < CC770_MAX_IRQ) {
> +		/* Read the highest pending interrupt request */
> +		intid = cc770_read_reg(priv, interrupt);
> +		if (!intid)
> +			break;
> +		n++;
> +
> +		if (intid == 1) {
> +			/* Exit in case of bus-off */
> +			if (cc770_status_interrupt(dev))
> +				break;
> +		} else {
> +			o = intid2obj(intid);
> +
> +			if (o >= CC770_OBJ_MAX) {
> +				netdev_err(dev, "Unexpected interrupt id %d\n",
> +					   intid);
> +				continue;
> +			}
> +
> +			if (priv->obj_flags[o] & CC770_OBJ_FLAG_RTR)
> +				cc770_rtr_interrupt(dev, o);
> +			else if (priv->obj_flags[o] & CC770_OBJ_FLAG_RX)
> +				cc770_rx_interrupt(dev, o);
> +			else
> +				cc770_tx_interrupt(dev, o);
> +		}
> +	}
> +
> +	if (priv->post_irq)
> +		priv->post_irq(priv);
> +
> +	if (n >= CC770_MAX_IRQ)
> +		netdev_dbg(dev, "%d messages handled in ISR", n);
> +
> +	return (n) ? IRQ_HANDLED : IRQ_NONE;
> +}
> +
> +static int cc770_open(struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +	int err;
> +
> +	/* set chip into reset mode */
> +	set_reset_mode(dev);
> +
> +	/* common open */
> +	err = open_candev(dev);
> +	if (err)
> +		return err;
> +
> +	err = request_irq(dev->irq, &cc770_interrupt, priv->irq_flags,
> +			  dev->name, (void *)dev);

the (void *) cast ist not needed

> +	if (err) {
> +		close_candev(dev);
> +		return -EAGAIN;
> +	}
> +
> +	/* init and start chip */
> +	cc770_start(dev);
> +	priv->open_time = jiffies;

open_time is used to track if the netdev is open, right? Can we use
"ndev->flags & IFF_UP" instead?

> +
> +	netif_start_queue(dev);
> +
> +	return 0;
> +}
> +
> +static int cc770_close(struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +
> +	netif_stop_queue(dev);
> +	set_reset_mode(dev);
> +
> +	free_irq(dev->irq, (void *)dev);
cast not needed
> +	close_candev(dev);
> +
> +	priv->open_time = 0;
> +
> +	return 0;
> +}
> +
> +struct net_device *alloc_cc770dev(int sizeof_priv)
> +{
> +	struct net_device *dev;
> +	struct cc770_priv *priv;
> +
> +	dev = alloc_candev(sizeof(struct cc770_priv) + sizeof_priv,
> +			   CC770_ECHO_SKB_MAX);
> +	if (!dev)
> +		return NULL;
> +
> +	priv = netdev_priv(dev);
> +
> +	priv->dev = dev;
> +	priv->can.bittiming_const = &cc770_bittiming_const;
> +	priv->can.do_set_bittiming = cc770_set_bittiming;
> +	priv->can.do_set_mode = cc770_set_mode;
> +	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
> +
> +	memcpy(priv->obj_flags, cc770_obj_flags, sizeof(cc770_obj_flags));
> +
> +	if (sizeof_priv)
> +		priv->priv = (void *)priv + sizeof(struct cc770_priv);
> +
> +	return dev;
> +}
> +EXPORT_SYMBOL_GPL(alloc_cc770dev);
> +
> +void free_cc770dev(struct net_device *dev)
> +{
> +	free_candev(dev);
> +}
> +EXPORT_SYMBOL_GPL(free_cc770dev);
> +
> +static const struct net_device_ops cc770_netdev_ops = {
> +	.ndo_open = cc770_open,
> +	.ndo_stop = cc770_close,
> +	.ndo_start_xmit = cc770_start_xmit,
> +};
> +
> +int register_cc770dev(struct net_device *dev)
> +{
> +	struct cc770_priv *priv = netdev_priv(dev);
> +
> +	if (!cc770_probe_chip(dev))
> +		return -ENODEV;
> +
> +	dev->netdev_ops = &cc770_netdev_ops;
> +
> +	dev->flags |= IFF_ECHO;	/* we support local echo */
> +
> +	/* Should we use additional functions? */
> +	if (!i82527_compat && priv->control_normal_mode & CTRL_EAF) {
> +		priv->control_normal_mode = CTRL_IE | CTRL_EAF | CTRL_EIE;
> +		netdev_dbg(dev, "i82527 mode with additional functions\n");
> +	} else {
> +		priv->control_normal_mode = CTRL_IE | CTRL_EIE;
> +		netdev_dbg(dev, "strict i82527 compatibility mode\n");
> +	}
> +
> +	chipset_init(priv);
> +	set_reset_mode(dev);
> +
> +	return register_candev(dev);
> +}
> +EXPORT_SYMBOL_GPL(register_cc770dev);
> +
> +void unregister_cc770dev(struct net_device *dev)
> +{
> +	set_reset_mode(dev);
> +	unregister_candev(dev);
> +}
> +EXPORT_SYMBOL_GPL(unregister_cc770dev);
> +
> +static __init int cc770_init(void)
> +{
> +	if (msgobj15_eff) {
> +		cc770_obj_flags[CC770_OBJ_RX0] |= CC770_OBJ_FLAG_EFF;
> +		cc770_obj_flags[CC770_OBJ_RX1] &= ~CC770_OBJ_FLAG_EFF;
> +	}
> +
> +	pr_info("%s CAN netdevice driver\n", DRV_NAME);

You can add a #define pr_fmt(fmt), to get rid of the "%s", DRV_NAME.

> +
> +	return 0;
> +}
> +module_init(cc770_init);
> +
> +static __exit void cc770_exit(void)
> +{
> +	pr_info("%s: driver removed\n", DRV_NAME);
> +}
> +module_exit(cc770_exit);
> diff --git a/drivers/net/can/cc770/cc770.h b/drivers/net/can/cc770/cc770.h
> new file mode 100644
> index 0000000..c6b5800
> --- /dev/null
> +++ b/drivers/net/can/cc770/cc770.h
> @@ -0,0 +1,234 @@
> +/*
> + * cc770.h - Bosch CC770 and Intel AN82527 network device driver
> + *
> + * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
> + *
> + * Derived from the old Socket-CAN i82527 driver:
> + *
> + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of Volkswagen nor the names of its contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
> + *
> + * Alternatively, provided that this notice is retained in full, this
> + * software may be distributed under the terms of the GNU General
> + * Public License ("GPL") version 2, in which case the provisions of the
> + * GPL apply INSTEAD OF those given above.
> + *
> + * The provided data structures and external interfaces from this code
> + * are not restricted to be used by modules with a GPL compatible license.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + *
> + * Send feedback to <socketcan-users@lists.berlios.de>

please remove

> + */
> +
> +#ifndef CC770_DEV_H
> +#define CC770_DEV_H
> +
> +#include <linux/can/dev.h>
> +
> +struct cc770_msgobj {
> +	u8 ctrl0;
> +	u8 ctrl1;
> +	u8 id[4];
> +	u8 config;
> +	u8 data[8];
> +	u8 dontuse;		/* padding */
> +} __attribute__ ((packed));
> +
> +struct cc770_regs {
> +	union {
> +		struct cc770_msgobj msgobj[16]; /* Message object 1..15 */
> +		struct {
> +			u8 control;		/* Control Register */
> +			u8 status;		/* Status Register */
> +			u8 cpu_interface;	/* CPU Interface Register */
> +			u8 dontuse1;
> +			u8 high_speed_read[2];	/* High Speed Read */
> +			u8 global_mask_std[2];	/* Standard Global Mask */
> +			u8 global_mask_ext[4];	/* Extended Global Mask */
> +			u8 msg15_mask[4];	/* Message 15 Mask */
> +			u8 dontuse2[15];
> +			u8 clkout;		/* Clock Out Register */
> +			u8 dontuse3[15];
> +			u8 bus_config;		/* Bus Configuration Register */
> +			u8 dontuse4[15];
> +			u8 bit_timing_0;	/* Bit Timing Register byte 0 */
> +			u8 dontuse5[15];
> +			u8 bit_timing_1;	/* Bit Timing Register byte 1 */
> +			u8 dontuse6[15];
> +			u8 interrupt;		/* Interrupt Register */
> +			u8 dontuse7[15];
> +			u8 rx_error_counter;	/* Receive Error Counter */
> +			u8 dontuse8[15];
> +			u8 tx_error_counter;	/* Transmit Error Counter */
> +			u8 dontuse9[31];
> +			u8 p1_conf;
> +			u8 dontuse10[15];
> +			u8 p2_conf;
> +			u8 dontuse11[15];
> +			u8 p1_in;
> +			u8 dontuse12[15];
> +			u8 p2_in;
> +			u8 dontuse13[15];
> +			u8 p1_out;
> +			u8 dontuse14[15];
> +			u8 p2_out;
> +			u8 dontuse15[15];
> +			u8 serial_reset_addr;
> +		};
> +	};
> +} __attribute__ ((packed));
> +
> +/* Control Register (0x00) */
> +#define CTRL_INI	0x01	/* Initialization */
> +#define CTRL_IE		0x02	/* Interrupt Enable */
> +#define CTRL_SIE	0x04	/* Status Interrupt Enable */
> +#define CTRL_EIE	0x08	/* Error Interrupt Enable */
> +#define CTRL_EAF	0x20	/* Enable additional functions */
> +#define CTRL_CCE	0x40	/* Change Configuration Enable */
> +
> +/* Status Register (0x01) */
> +#define STAT_LEC_STUFF	0x01	/* Stuff error */
> +#define STAT_LEC_FORM	0x02	/* Form error */
> +#define STAT_LEC_ACK	0x03	/* Acknowledgement error */
> +#define STAT_LEC_BIT1	0x04	/* Bit1 error */
> +#define STAT_LEC_BIT0	0x05	/* Bit0 error */
> +#define STAT_LEC_CRC	0x06	/* CRC error */
> +#define STAT_LEC_MASK	0x07	/* Last Error Code mask */
> +#define STAT_TXOK	0x08	/* Transmit Message Successfully */
> +#define STAT_RXOK	0x10	/* Receive Message Successfully */
> +#define STAT_WAKE	0x20	/* Wake Up Status */
> +#define STAT_WARN	0x40	/* Warning Status */
> +#define STAT_BOFF	0x80	/* Bus Off Status */
> +
> +/*
> + * CPU Interface Register (0x02)
> + * Clock Out Register (0x1f)
> + * Bus Configuration Register (0x2f)
> + *
> + * see include/linux/can/platform/cc770.h
> + */
> +
> +/* Message Control Register 0 (Base Address + 0x0) */
> +#define INTPND_RES	0x01	/* No Interrupt pending */
> +#define INTPND_SET	0x02	/* Interrupt pending */
> +#define INTPND_UNC	0x03
> +#define RXIE_RES	0x04	/* Receive Interrupt Disable */
> +#define RXIE_SET	0x08	/* Receive Interrupt Enable */
> +#define RXIE_UNC	0x0c
> +#define TXIE_RES	0x10	/* Transmit Interrupt Disable */
> +#define TXIE_SET	0x20	/* Transmit Interrupt Enable */
> +#define TXIE_UNC	0x30
> +#define MSGVAL_RES	0x40	/* Message Invalid */
> +#define MSGVAL_SET	0x80	/* Message Valid */
> +#define MSGVAL_UNC	0xc0
> +
> +/* Message Control Register 1 (Base Address + 0x01) */
> +#define NEWDAT_RES	0x01	/* No New Data */
> +#define NEWDAT_SET	0x02	/* New Data */
> +#define NEWDAT_UNC	0x03
> +#define MSGLST_RES	0x04	/* No Message Lost */
> +#define MSGLST_SET	0x08	/* Message Lost */
> +#define MSGLST_UNC	0x0c
> +#define CPUUPD_RES	0x04	/* No CPU Updating */
> +#define CPUUPD_SET	0x08	/* CPU Updating */
> +#define CPUUPD_UNC	0x0c
> +#define TXRQST_RES	0x10	/* No Transmission Request */
> +#define TXRQST_SET	0x20	/* Transmission Request */
> +#define TXRQST_UNC	0x30
> +#define RMTPND_RES	0x40	/* No Remote Request Pending */
> +#define RMTPND_SET	0x80	/* Remote Request Pending */
> +#define RMTPND_UNC	0xc0
> +
> +/* Message Configuration Register (Base Address + 0x06) */
> +#define MSGCFG_XTD	0x04	/* Extended Identifier */
> +#define MSGCFG_DIR	0x08	/* Direction is Transmit */
> +
> +#define MSGOBJ_FIRST	1
> +#define MSGOBJ_LAST	15
> +
> +#define CC770_IO_SIZE	0x100
> +#define CC770_MAX_IRQ	20	/* max. number of interrupts handled in ISR */
> +
> +#define CC770_ECHO_SKB_MAX	1
> +
> +#define cc770_read_reg(priv, member)					\
> +	priv->read_reg(priv, offsetof(struct cc770_regs, member))
> +
> +#define cc770_write_reg(priv, member, value)				\
> +	priv->write_reg(priv, offsetof(struct cc770_regs, member), value)
> +
> +/*
> + * Message objects and flags used by this driver
> + */
> +#define CC770_OBJ_FLAG_RX 	0x01
> +#define CC770_OBJ_FLAG_RTR	0x02
> +#define CC770_OBJ_FLAG_EFF	0x04
> +
> +enum {
> +	CC770_OBJ_RX0 = 0,	/* for receiving normal messages */
> +	CC770_OBJ_RX1,		/* for receiving normal messages */
> +	CC770_OBJ_RX_RTR0,	/* for receiving remote transmission requests */
> +	CC770_OBJ_RX_RTR1,	/* for receiving remote transmission requests */
> +	CC770_OBJ_TX,		/* for sending messages */
> +	CC770_OBJ_MAX
> +};
> +
> +#define obj2msgobj(o)	(MSGOBJ_LAST - (o)) /* message object 11..15 */
> +
> +/*
> + * CC770 private data structure
> + */
> +struct cc770_priv {
> +	struct can_priv can;	/* must be the first member */
> +	int open_time;
> +	struct sk_buff *echo_skb;
> +
> +	/* the lower-layer is responsible for appropriate locking */
> +	u8 (*read_reg)(const struct cc770_priv *priv, int reg);
> +	void (*write_reg)(const struct cc770_priv *priv, int reg, u8 val);
> +	void (*pre_irq)(const struct cc770_priv *priv);
> +	void (*post_irq)(const struct cc770_priv *priv);
> +
> +	void *priv;		/* for board-specific data */
> +	struct net_device *dev;
> +
> +	void __iomem *reg_base;	/* ioremap'ed address to registers */
> +	unsigned long irq_flags;	/* for request_irq() */
> +
> +	unsigned char obj_flags[CC770_OBJ_MAX];
> +	u8 control_normal_mode;	/* Control register for normal mode */
> +	u8 cpu_interface;	/* CPU interface register */
> +	u8 clkout;		/* Clock out register */
> +	u8 bus_config;		/* Bus conffiguration register */
> +};
> +
> +struct net_device *alloc_cc770dev(int sizeof_priv);
> +void free_cc770dev(struct net_device *dev);
> +int register_cc770dev(struct net_device *dev);
> +void unregister_cc770dev(struct net_device *dev);
> +
> +#endif /* CC770_DEV_H */
> diff --git a/include/linux/can/platform/cc770.h b/include/linux/can/platform/cc770.h
> new file mode 100644
> index 0000000..c4ed994
> --- /dev/null
> +++ b/include/linux/can/platform/cc770.h
> @@ -0,0 +1,33 @@
> +#ifndef _CAN_PLATFORM_CC770_H_
> +#define _CAN_PLATFORM_CC770_H_
> +
> +/* CPU Interface Register (0x02) */
> +#define CPUIF_CEN	0x01	/* Clock Out Enable */
> +#define CPUIF_MUX	0x04	/* Multiplex */
> +#define CPUIF_SLP	0x08	/* Sleep */
> +#define CPUIF_PWD	0x10	/* Power Down Mode */
> +#define CPUIF_DMC	0x20	/* Divide Memory Clock */
> +#define CPUIF_DSC	0x40	/* Divide System Clock */
> +#define CPUIF_RST	0x80	/* Hardware Reset Status */
> +
> +/* Clock Out Register (0x1f) */
> +#define CLKOUT_CD_MASK  0x0f	/* Clock Divider mask */
> +#define CLKOUT_SL_MASK	0x30	/* Slew Rate mask */
> +#define CLKOUT_SL_SHIFT	4
> +
> +/* Bus Configuration Register (0x2f) */
> +#define BUSCFG_DR0	0x01	/* Disconnect RX0 Input / Select RX input */
> +#define BUSCFG_DR1	0x02	/* Disconnect RX1 Input / Silent mode */
> +#define BUSCFG_DT1	0x08	/* Disconnect TX1 Output */
> +#define BUSCFG_POL	0x20	/* Polarity dominant or recessive */
> +#define BUSCFG_CBY	0x40	/* Input Comparator Bypass */
> +
> +struct cc770_platform_data {
> +	u32 osc_freq;	/* CAN bus oscillator frequency in Hz */
> +
> +	u8 cir;	 	/* CPU Interface Register */
> +	u8 cor;		/* Clock Out Register */
> +	u8 bcr;		/* Bus Configuration Register */
> +};
> +
> +#endif	/* !_CAN_PLATFORM_CC770_H_ */


-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply

* [PATCH net-next v3 0/4] can: cc770: add support for the Bosch CC770 and Intel AN82527
From: Wolfgang Grandegger @ 2011-11-28 11:30 UTC (permalink / raw)
  To: netdev
  Cc: linux-can, socketcan-users, IreneV, Stanislav Yelenskiy,
	Wolfgang Zarre, Wolfgang Grandegger

Already since a while we have support for the Bosch CC770 and Intel
AN82527 CAN controllers in our out-of-tree Socket-CAN repository.

In the meantime I found a TQM855L board with two AN82527 on it,
which allowed me to provide and test a generic platform driver
as well.

Changes since v1:

- remove version.h includes
- some minor corrections in the ISA bus driver
- add platform header file to the driver core
- add generic platform driver
- add and update device tree nodes for tqm8xx and tqm8548

Changes since v2:

- correct license text as suggest by Oliver Hartkopp
- use the new module_platform_driver function
- provide get_berr_counter callback for cc770
- improve CAN error state change handling
- more comprehensive cc770_isa driver description

It would be nice if somebody else could test the driver, especially
the ISA driver (I don't have hardware at hand).

Wolfgang.

Wolfgang Grandegger (4):
  can: cc770: add driver core for the Bosch CC770 and Intel AN82527
  can: cc770: add legacy ISA bus driver for the CC770 and AN82527
  can: cc770: add platform bus driver for the CC770 and AN82527
  powerpc: tqm8548/tqm8xx: add and update CAN device nodes

 .../devicetree/bindings/net/can/cc770.txt          |   56 ++
 arch/powerpc/boot/dts/tqm8548-bigflash.dts         |   19 +-
 arch/powerpc/boot/dts/tqm8548.dts                  |   19 +-
 arch/powerpc/boot/dts/tqm8xx.dts                   |   25 +
 drivers/net/can/Kconfig                            |    2 +
 drivers/net/can/Makefile                           |    1 +
 drivers/net/can/cc770/Kconfig                      |   21 +
 drivers/net/can/cc770/Makefile                     |    9 +
 drivers/net/can/cc770/cc770.c                      |  900 ++++++++++++++++++++
 drivers/net/can/cc770/cc770.h                      |  207 +++++
 drivers/net/can/cc770/cc770_isa.c                  |  372 ++++++++
 drivers/net/can/cc770/cc770_platform.c             |  280 ++++++
 include/linux/can/platform/cc770.h                 |   33 +
 13 files changed, 1934 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/can/cc770.txt
 create mode 100644 drivers/net/can/cc770/Kconfig
 create mode 100644 drivers/net/can/cc770/Makefile
 create mode 100644 drivers/net/can/cc770/cc770.c
 create mode 100644 drivers/net/can/cc770/cc770.h
 create mode 100644 drivers/net/can/cc770/cc770_isa.c
 create mode 100644 drivers/net/can/cc770/cc770_platform.c
 create mode 100644 include/linux/can/platform/cc770.h

-- 
1.7.4.1


^ permalink raw reply

* [PATCH net-next v3 1/4] can: cc770: add driver core for the Bosch CC770 and Intel AN82527
From: Wolfgang Grandegger @ 2011-11-28 11:30 UTC (permalink / raw)
  To: netdev
  Cc: linux-can, socketcan-users, IreneV, Stanislav Yelenskiy,
	Wolfgang Zarre, Wolfgang Grandegger
In-Reply-To: <1322479858-4874-1-git-send-email-wg@grandegger.com>

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
 drivers/net/can/Kconfig            |    2 +
 drivers/net/can/Makefile           |    1 +
 drivers/net/can/cc770/Kconfig      |    3 +
 drivers/net/can/cc770/Makefile     |    7 +
 drivers/net/can/cc770/cc770.c      |  900 ++++++++++++++++++++++++++++++++++++
 drivers/net/can/cc770/cc770.h      |  207 +++++++++
 include/linux/can/platform/cc770.h |   33 ++
 7 files changed, 1153 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/cc770/Kconfig
 create mode 100644 drivers/net/can/cc770/Makefile
 create mode 100644 drivers/net/can/cc770/cc770.c
 create mode 100644 drivers/net/can/cc770/cc770.h
 create mode 100644 include/linux/can/platform/cc770.h

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index f6c98fb..ab45758 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -116,6 +116,8 @@ source "drivers/net/can/sja1000/Kconfig"
 
 source "drivers/net/can/c_can/Kconfig"
 
+source "drivers/net/can/cc770/Kconfig"
+
 source "drivers/net/can/usb/Kconfig"
 
 source "drivers/net/can/softing/Kconfig"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 24ebfe8..938be37 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -14,6 +14,7 @@ obj-y				+= softing/
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
 obj-$(CONFIG_CAN_MSCAN)		+= mscan/
 obj-$(CONFIG_CAN_C_CAN)		+= c_can/
+obj-$(CONFIG_CAN_CC770)		+= cc770/
 obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
diff --git a/drivers/net/can/cc770/Kconfig b/drivers/net/can/cc770/Kconfig
new file mode 100644
index 0000000..225131b
--- /dev/null
+++ b/drivers/net/can/cc770/Kconfig
@@ -0,0 +1,3 @@
+menuconfig CAN_CC770
+	tristate "Bosch CC770 and Intel AN82527 devices"
+	depends on CAN_DEV && HAS_IOMEM
diff --git a/drivers/net/can/cc770/Makefile b/drivers/net/can/cc770/Makefile
new file mode 100644
index 0000000..34e8180
--- /dev/null
+++ b/drivers/net/can/cc770/Makefile
@@ -0,0 +1,7 @@
+#
+#  Makefile for the Bosch CC770 CAN controller drivers.
+#
+
+obj-$(CONFIG_CAN_CC770) += cc770.o
+
+ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
new file mode 100644
index 0000000..f3d80dc
--- /dev/null
+++ b/drivers/net/can/cc770/cc770.c
@@ -0,0 +1,900 @@
+/*
+ * Core driver for the CC770 and AN82527 CAN controllers
+ *
+ * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+#include <linux/can/dev.h>
+#include <linux/can/platform/cc770.h>
+
+#include "cc770.h"
+
+#define DRV_NAME  "cc770"
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver");
+
+/*
+ * The CC770 is a CAN controller from Bosch, which is 100% compatible
+ * with the AN82527 from Intel, but with "bugs" being fixed and some
+ * additional functionality, mainly:
+ *
+ * 1. RX and TX error counters are readable.
+ * 2. Support of silent (listen-only) mode.
+ * 3. Message object 15 can receive all types of frames, also RTR and EFF.
+ *
+ * Details are available from Bosch's "CC770_Product_Info_2007-01.pdf",
+ * which explains in detail the compatibility between the CC770 and the
+ * 82527. This driver use the additional functionality 3. on real CC770
+ * devices. Unfortunately, the CC770 does still not store the message
+ * identifier of received remote transmission request frames and
+ * therefore it's set to 0.
+ *
+ * The message objects 1..14 can be used for TX and RX while the message
+ * objects 15 is optimized for RX. It has a shadow register for reliable
+ * data receiption under heavy bus load. Therefore it makes sense to use
+ * this message object for the needed use case. The frame type (EFF/SFF)
+ * for the message object 15 can be defined via kernel module parameter
+ * "msgobj15_eff". If not equal 0, it will receive 29-bit EFF frames,
+ * otherwise 11 bit SFF messages.
+ */
+static int msgobj15_eff;
+module_param(msgobj15_eff, int, S_IRUGO);
+MODULE_PARM_DESC(msgobj15_eff, "Extended 29-bit frames for message object 15 "
+		 "(default: 11-bit standard frames)");
+
+static int i82527_compat;
+module_param(i82527_compat, int, S_IRUGO);
+MODULE_PARM_DESC(i82527_compat, "Strict Intel 82527 comptibility mode "
+		 "without using additional functions");
+
+/*
+ * This driver uses the last 5 message objects 11..15. The definitions
+ * and structure below allows to configure and assign them to the real
+ * message object.
+ */
+static unsigned char cc770_obj_flags[CC770_OBJ_MAX] = {
+	[CC770_OBJ_RX0] = CC770_OBJ_FLAG_RX,
+	[CC770_OBJ_RX1] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_EFF,
+	[CC770_OBJ_RX_RTR0] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_RTR,
+	[CC770_OBJ_RX_RTR1] = CC770_OBJ_FLAG_RX | CC770_OBJ_FLAG_RTR |
+			      CC770_OBJ_FLAG_EFF,
+	[CC770_OBJ_TX] = 0,
+};
+
+static struct can_bittiming_const cc770_bittiming_const = {
+	.name = DRV_NAME,
+	.tseg1_min = 1,
+	.tseg1_max = 16,
+	.tseg2_min = 1,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 64,
+	.brp_inc = 1,
+};
+
+static inline int intid2obj(unsigned int intid)
+{
+	if (intid == 2)
+		return 0;
+	else
+		return MSGOBJ_LAST + 2 - intid;
+}
+
+static void enable_all_objs(const struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	u8 msgcfg;
+	unsigned char obj_flags;
+	unsigned int o, mo;
+
+	for (o = 0; o <  CC770_OBJ_MAX; o++) {
+		obj_flags = priv->obj_flags[o];
+		mo = obj2msgobj(o);
+
+		if (obj_flags & CC770_OBJ_FLAG_RX) {
+			/*
+			 * We don't need extra objects for RTR and EFF if
+			 * the additional CC770 functions are enabled.
+			 */
+			if (priv->control_normal_mode & CTRL_EAF) {
+				if (o > 0)
+					continue;
+				netdev_dbg(dev, "Message object %d for "
+					   "RX data, RTR, SFF and EFF\n", mo);
+			} else {
+				netdev_dbg(dev,
+					   "Message object %d for RX %s %s\n",
+					   mo, obj_flags & CC770_OBJ_FLAG_RTR ?
+					   "RTR" : "data",
+					   obj_flags & CC770_OBJ_FLAG_EFF ?
+					   "EFF" : "SFF");
+			}
+
+			if (obj_flags & CC770_OBJ_FLAG_EFF)
+				msgcfg = MSGCFG_XTD;
+			else
+				msgcfg = 0;
+			if (obj_flags & CC770_OBJ_FLAG_RTR)
+				msgcfg |= MSGCFG_DIR;
+
+			cc770_write_reg(priv, msgobj[mo].config, msgcfg);
+			cc770_write_reg(priv, msgobj[mo].ctrl0,
+					MSGVAL_SET | TXIE_RES |
+					RXIE_SET | INTPND_RES);
+
+			if (obj_flags & CC770_OBJ_FLAG_RTR)
+				cc770_write_reg(priv, msgobj[mo].ctrl1,
+						NEWDAT_RES | CPUUPD_SET |
+						TXRQST_RES | RMTPND_RES);
+			else
+				cc770_write_reg(priv, msgobj[mo].ctrl1,
+						NEWDAT_RES | MSGLST_RES |
+						TXRQST_RES | RMTPND_RES);
+		} else {
+			netdev_dbg(dev, "Message object %d for "
+				   "TX data, RTR, SFF and EFF\n", mo);
+
+			cc770_write_reg(priv, msgobj[mo].ctrl1,
+					RMTPND_RES | TXRQST_RES |
+					CPUUPD_RES | NEWDAT_RES);
+			cc770_write_reg(priv, msgobj[mo].ctrl0,
+					MSGVAL_RES | TXIE_RES |
+					RXIE_RES | INTPND_RES);
+		}
+	}
+}
+
+static void disable_all_objs(const struct cc770_priv *priv)
+{
+	int i, mo;
+
+	for (i = 0; i <  CC770_OBJ_MAX; i++) {
+		mo = obj2msgobj(i);
+
+		if (priv->obj_flags[i] & CC770_OBJ_FLAG_RX) {
+			if (i > 0 && priv->control_normal_mode & CTRL_EAF)
+				continue;
+
+			cc770_write_reg(priv, msgobj[mo].ctrl1,
+					NEWDAT_RES | MSGLST_RES |
+					TXRQST_RES | RMTPND_RES);
+			cc770_write_reg(priv, msgobj[mo].ctrl0,
+					MSGVAL_RES | TXIE_RES |
+					RXIE_RES | INTPND_RES);
+		} else {
+			/* Clear message object for send */
+			cc770_write_reg(priv, msgobj[mo].ctrl1,
+					RMTPND_RES | TXRQST_RES |
+					CPUUPD_RES | NEWDAT_RES);
+			cc770_write_reg(priv, msgobj[mo].ctrl0,
+					MSGVAL_RES | TXIE_RES |
+					RXIE_RES | INTPND_RES);
+		}
+	}
+}
+
+static void set_reset_mode(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+
+	/* Enable configuration and puts chip in bus-off, disable interrupts */
+	cc770_write_reg(priv, control, CTRL_CCE | CTRL_INI);
+
+	priv->can.state = CAN_STATE_STOPPED;
+
+	/* Clear interrupts */
+	cc770_read_reg(priv, interrupt);
+
+	/* Clear status register */
+	cc770_write_reg(priv, status, 0);
+
+	/* Disable all used message objects */
+	disable_all_objs(priv);
+}
+
+static void set_normal_mode(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+
+	/* Clear interrupts */
+	cc770_read_reg(priv, interrupt);
+
+	/* Clear status register and pre-set last error code */
+	cc770_write_reg(priv, status, STAT_LEC_MASK);
+
+	/* Enable all used message objects*/
+	enable_all_objs(dev);
+
+	/*
+	 * Clear bus-off, interrupts only for errors,
+	 * not for status change
+	 */
+	cc770_write_reg(priv, control, priv->control_normal_mode);
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+}
+
+static void chipset_init(struct cc770_priv *priv)
+{
+	int mo, id, data;
+
+	/* Enable configuration and put chip in bus-off, disable interrupts */
+	cc770_write_reg(priv, control, (CTRL_CCE | CTRL_INI));
+
+	/* Set CLKOUT divider and slew rates */
+	cc770_write_reg(priv, clkout, priv->clkout);
+
+	/* Configure CPU interface / CLKOUT enable */
+	cc770_write_reg(priv, cpu_interface, priv->cpu_interface);
+
+	/* Set bus configuration  */
+	cc770_write_reg(priv, bus_config, priv->bus_config);
+
+	/* Clear interrupts */
+	cc770_read_reg(priv, interrupt);
+
+	/* Clear status register */
+	cc770_write_reg(priv, status, 0);
+
+	/* Clear and invalidate message objects */
+	for (mo = MSGOBJ_FIRST; mo <= MSGOBJ_LAST; mo++) {
+		cc770_write_reg(priv, msgobj[mo].ctrl0,
+				INTPND_UNC | RXIE_RES |
+				TXIE_RES | MSGVAL_RES);
+		cc770_write_reg(priv, msgobj[mo].ctrl0,
+				INTPND_RES | RXIE_RES |
+				TXIE_RES | MSGVAL_RES);
+		cc770_write_reg(priv, msgobj[mo].ctrl1,
+				NEWDAT_RES | MSGLST_RES |
+				TXRQST_RES | RMTPND_RES);
+		for (data = 0; data < 8; data++)
+			cc770_write_reg(priv, msgobj[mo].data[data], 0);
+		for (id = 0; id < 4; id++)
+			cc770_write_reg(priv, msgobj[mo].id[id], 0);
+		cc770_write_reg(priv, msgobj[mo].config, 0);
+	}
+
+	/* Set all global ID masks to "don't care" */
+	cc770_write_reg(priv, global_mask_std[0], 0);
+	cc770_write_reg(priv, global_mask_std[1], 0);
+	cc770_write_reg(priv, global_mask_ext[0], 0);
+	cc770_write_reg(priv, global_mask_ext[1], 0);
+	cc770_write_reg(priv, global_mask_ext[2], 0);
+	cc770_write_reg(priv, global_mask_ext[3], 0);
+
+}
+
+static int cc770_probe_chip(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+
+	/* Enable configuration, put chip in bus-off, disable ints */
+	cc770_write_reg(priv, control, CTRL_CCE | CTRL_EAF | CTRL_INI);
+	/* Configure cpu interface / CLKOUT disable */
+	cc770_write_reg(priv, cpu_interface, priv->cpu_interface);
+
+	/*
+	 * Check if hardware reset is still inactive or maybe there
+	 * is no chip in this address space
+	 */
+	if (cc770_read_reg(priv, cpu_interface) & CPUIF_RST) {
+		netdev_info(dev, "probing @0x%p failed (reset)\n",
+			    priv->reg_base);
+		return 0;
+	}
+
+	/* Write and read back test pattern */
+	cc770_write_reg(priv, msgobj[1].data[1], 0x25);
+	cc770_write_reg(priv, msgobj[2].data[3], 0x52);
+	cc770_write_reg(priv, msgobj[10].data[6], 0xc3);
+	if ((cc770_read_reg(priv, msgobj[1].data[1]) != 0x25) ||
+	    (cc770_read_reg(priv, msgobj[2].data[3]) != 0x52) ||
+	    (cc770_read_reg(priv, msgobj[10].data[6]) != 0xc3)) {
+		netdev_info(dev, "probing @0x%p failed (pattern)\n",
+			    priv->reg_base);
+		return 0;
+	}
+
+	/* Check if this chip is a CC770 supporting additional functions */
+	if (cc770_read_reg(priv, control) & CTRL_EAF)
+		priv->control_normal_mode |= CTRL_EAF;
+
+	return 1;
+}
+
+static void cc770_start(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+
+	/* leave reset mode */
+	if (priv->can.state != CAN_STATE_STOPPED)
+		set_reset_mode(dev);
+
+	/* leave reset mode */
+	set_normal_mode(dev);
+}
+
+static int cc770_set_mode(struct net_device *dev, enum can_mode mode)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+
+	if (!priv->open_time)
+		return -EINVAL;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		cc770_start(dev);
+		if (netif_queue_stopped(dev))
+			netif_wake_queue(dev);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int cc770_set_bittiming(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	u8 btr0, btr1;
+
+	btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
+	btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
+		(((bt->phase_seg2 - 1) & 0x7) << 4);
+	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+		btr1 |= 0x80;
+
+	netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
+
+	cc770_write_reg(priv, bit_timing_0, btr0);
+	cc770_write_reg(priv, bit_timing_1, btr1);
+
+	return 0;
+}
+
+static int cc770_get_berr_counter(const struct net_device *dev,
+				  struct can_berr_counter *bec)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+
+	bec->txerr = cc770_read_reg(priv, tx_error_counter);
+	bec->rxerr = cc770_read_reg(priv, rx_error_counter);
+
+	return 0;
+}
+
+static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf = (struct can_frame *)skb->data;
+	unsigned int mo = obj2msgobj(CC770_OBJ_TX);
+	u8 dlc, rtr;
+	u32 id;
+	int i;
+
+	if (can_dropped_invalid_skb(dev, skb))
+		return NETDEV_TX_OK;
+
+	if ((cc770_read_reg(priv,
+			    msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) {
+		netdev_err(dev, "TX register is still occupied!\n");
+		return NETDEV_TX_BUSY;
+	}
+
+	netif_stop_queue(dev);
+
+	dlc = cf->can_dlc;
+	id = cf->can_id;
+	if (cf->can_id & CAN_RTR_FLAG)
+		rtr = 0;
+	else
+		rtr = MSGCFG_DIR;
+	cc770_write_reg(priv, msgobj[mo].ctrl1,
+			RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES);
+	cc770_write_reg(priv, msgobj[mo].ctrl0,
+			MSGVAL_SET | TXIE_SET | RXIE_RES | INTPND_RES);
+	if (id & CAN_EFF_FLAG) {
+		id &= CAN_EFF_MASK;
+		cc770_write_reg(priv, msgobj[mo].config,
+				(dlc << 4) + rtr + MSGCFG_XTD);
+		cc770_write_reg(priv, msgobj[mo].id[3],
+				(id << 3) & 0xFFU);
+		cc770_write_reg(priv, msgobj[mo].id[2],
+				(id >> 5) & 0xFFU);
+		cc770_write_reg(priv, msgobj[mo].id[1],
+				(id >> 13) & 0xFFU);
+		cc770_write_reg(priv, msgobj[mo].id[0],
+				(id >> 21) & 0xFFU);
+	} else {
+		id &= CAN_SFF_MASK;
+		cc770_write_reg(priv, msgobj[mo].config,
+				(dlc << 4) + rtr);
+		cc770_write_reg(priv, msgobj[mo].id[0],
+				(id >> 3) & 0xFFU);
+		cc770_write_reg(priv, msgobj[mo].id[1],
+				(id << 5) & 0xFFU);
+	}
+
+	dlc &= 0x0f;		/* restore length only */
+	for (i = 0; i < dlc; i++)
+		cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]);
+
+	cc770_write_reg(priv, msgobj[mo].ctrl1,
+			RMTPND_RES | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
+
+	stats->tx_bytes += dlc;
+
+	can_put_echo_skb(skb, dev, 0);
+
+	/*
+	 * HM: We had some cases of repeated IRQs so make sure the
+	 * INT is acknowledged I know it's already further up, but
+	 * doing again fixed the issue
+	 */
+	cc770_write_reg(priv, msgobj[mo].ctrl0,
+			MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES);
+
+	return NETDEV_TX_OK;
+}
+
+static void cc770_rx(struct net_device *dev, unsigned int mo, u8 ctrl1)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	u8 config;
+	u32 id;
+	int i;
+
+	skb = alloc_can_skb(dev, &cf);
+	if (skb == NULL)
+		return;
+
+	config = cc770_read_reg(priv, msgobj[mo].config);
+
+	if (ctrl1 & RMTPND_SET) {
+		/*
+		 * Unfortunately, the chip does not store the real message
+		 * identifier of the received remote transmission request
+		 * frame. Therefore we set it to 0.
+		 */
+		cf->can_id = CAN_RTR_FLAG;
+		if (config & MSGCFG_XTD)
+			cf->can_id |= CAN_EFF_FLAG;
+		cf->can_dlc = 0;
+	} else {
+		if (config & MSGCFG_XTD) {
+			id = cc770_read_reg(priv, msgobj[mo].id[3]);
+			id |= cc770_read_reg(priv, msgobj[mo].id[2]) << 8;
+			id |= cc770_read_reg(priv, msgobj[mo].id[1]) << 16;
+			id |= cc770_read_reg(priv, msgobj[mo].id[0]) << 24;
+			id >>= 3;
+			id |= CAN_EFF_FLAG;
+		} else {
+			id = cc770_read_reg(priv, msgobj[mo].id[1]);
+			id |= cc770_read_reg(priv, msgobj[mo].id[0]) << 8;
+			id >>= 5;
+		}
+
+		cf->can_id = id;
+		cf->can_dlc = get_can_dlc((config & 0xf0) >> 4);
+		for (i = 0; i < cf->can_dlc; i++)
+			cf->data[i] = cc770_read_reg(priv, msgobj[mo].data[i]);
+	}
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+}
+
+static int cc770_err(struct net_device *dev, u8 status)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	u8 lec;
+
+	netdev_dbg(dev, "status interrupt (%#x)\n", status);
+
+	skb = alloc_can_err_skb(dev, &cf);
+	if (skb == NULL)
+		return -ENOMEM;
+
+	/* Use extended functions of the CC770 */
+	if (priv->control_normal_mode & CTRL_EAF) {
+		cf->data[6] = cc770_read_reg(priv, tx_error_counter);
+		cf->data[7] = cc770_read_reg(priv, rx_error_counter);
+	}
+
+	if (status & STAT_BOFF) {
+		/* Disable interrupts */
+		cc770_write_reg(priv, control, CTRL_INI);
+		cf->can_id |= CAN_ERR_BUSOFF;
+		priv->can.state = CAN_STATE_BUS_OFF;
+		can_bus_off(dev);
+	} else if (status & STAT_WARN) {
+		cf->can_id |= CAN_ERR_CRTL;
+		/* Only the CC770 does show error passive */
+		if (cf->data[7] > 127) {
+			cf->data[1] = CAN_ERR_CRTL_RX_PASSIVE |
+				CAN_ERR_CRTL_TX_PASSIVE;
+			priv->can.state = CAN_STATE_ERROR_PASSIVE;
+			priv->can.can_stats.error_passive++;
+		} else {
+			cf->data[1] = CAN_ERR_CRTL_RX_WARNING |
+				CAN_ERR_CRTL_TX_WARNING;
+			priv->can.state = CAN_STATE_ERROR_WARNING;
+			priv->can.can_stats.error_warning++;
+		}
+	} else {
+		/* Back to error avtive */
+		cf->can_id |= CAN_ERR_PROT;
+		cf->data[2] = CAN_ERR_PROT_ACTIVE;
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+	}
+
+	lec = status & STAT_LEC_MASK;
+	if (lec < 7 && lec > 0) {
+		if (lec == STAT_LEC_ACK) {
+			cf->can_id |= CAN_ERR_ACK;
+		} else {
+			cf->can_id |= CAN_ERR_PROT;
+			switch (lec) {
+			case STAT_LEC_STUFF:
+				cf->data[2] |= CAN_ERR_PROT_STUFF;
+				break;
+			case STAT_LEC_FORM:
+				cf->data[2] |= CAN_ERR_PROT_FORM;
+				break;
+			case STAT_LEC_BIT1:
+				cf->data[2] |= CAN_ERR_PROT_BIT1;
+				break;
+			case STAT_LEC_BIT0:
+				cf->data[2] |= CAN_ERR_PROT_BIT0;
+				break;
+			case STAT_LEC_CRC:
+				cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
+				break;
+			}
+		}
+	}
+
+	netif_rx(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	return 0;
+}
+
+static int cc770_status_interrupt(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	u8 status;
+
+	status = cc770_read_reg(priv, status);
+	/* Reset the status register including RXOK and TXOK */
+	cc770_write_reg(priv, status, STAT_LEC_MASK);
+
+	if (status & (STAT_WARN | STAT_BOFF) ||
+	    (status & STAT_LEC_MASK) != STAT_LEC_MASK) {
+		cc770_err(dev, status);
+		return status & STAT_BOFF;
+	}
+
+	return 0;
+}
+
+static void cc770_rx_interrupt(struct net_device *dev, unsigned int o)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	unsigned int mo = obj2msgobj(o);
+	u8 ctrl1;
+
+	while (1) {
+		ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
+
+		if (!(ctrl1 & NEWDAT_SET))  {
+			/* Check for RTR if additional functions are enabled */
+			if (priv->control_normal_mode & CTRL_EAF) {
+				if (!(cc770_read_reg(priv, msgobj[mo].ctrl0) &
+				      INTPND_SET))
+					break;
+			} else {
+				break;
+			}
+		}
+
+		if (ctrl1 & MSGLST_SET) {
+			stats->rx_over_errors++;
+			stats->rx_errors++;
+		}
+		if (mo < MSGOBJ_LAST)
+			cc770_write_reg(priv, msgobj[mo].ctrl1,
+					NEWDAT_RES | MSGLST_RES |
+					TXRQST_UNC | RMTPND_UNC);
+		cc770_rx(dev, mo, ctrl1);
+
+		cc770_write_reg(priv, msgobj[mo].ctrl0,
+				MSGVAL_SET | TXIE_RES |
+				RXIE_SET | INTPND_RES);
+		cc770_write_reg(priv, msgobj[mo].ctrl1,
+				NEWDAT_RES | MSGLST_RES |
+				TXRQST_RES | RMTPND_RES);
+	}
+}
+
+static void cc770_rtr_interrupt(struct net_device *dev, unsigned int o)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	unsigned int mo = obj2msgobj(o);
+	u8 ctrl0, ctrl1;
+
+	while (1) {
+		ctrl0 = cc770_read_reg(priv, msgobj[mo].ctrl0);
+		if (!(ctrl0 & INTPND_SET))
+			break;
+
+		ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
+		cc770_rx(dev, mo, ctrl1);
+
+		cc770_write_reg(priv, msgobj[mo].ctrl0,
+				MSGVAL_SET | TXIE_RES |
+				RXIE_SET | INTPND_RES);
+		cc770_write_reg(priv, msgobj[mo].ctrl1,
+				NEWDAT_RES | CPUUPD_SET |
+				TXRQST_RES | RMTPND_RES);
+	}
+}
+
+static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	unsigned int mo = obj2msgobj(o);
+
+	/* Nothing more to send, switch off interrupts */
+	cc770_write_reg(priv, msgobj[mo].ctrl0,
+			MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
+	/*
+	 * We had some cases of repeated IRQ so make sure the
+	 * INT is acknowledged
+	 */
+	cc770_write_reg(priv, msgobj[mo].ctrl0,
+			MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES);
+
+	stats->tx_packets++;
+	can_get_echo_skb(dev, 0);
+	netif_wake_queue(dev);
+}
+
+irqreturn_t cc770_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct cc770_priv *priv = netdev_priv(dev);
+	u8 intid;
+	int o, n = 0;
+
+	/* Shared interrupts and IRQ off? */
+	if (priv->can.state == CAN_STATE_STOPPED)
+		return IRQ_NONE;
+
+	if (priv->pre_irq)
+		priv->pre_irq(priv);
+
+	while (n < CC770_MAX_IRQ) {
+		/* Read the highest pending interrupt request */
+		intid = cc770_read_reg(priv, interrupt);
+		if (!intid)
+			break;
+		n++;
+
+		if (intid == 1) {
+			/* Exit in case of bus-off */
+			if (cc770_status_interrupt(dev))
+				break;
+		} else {
+			o = intid2obj(intid);
+
+			if (o >= CC770_OBJ_MAX) {
+				netdev_err(dev, "Unexpected interrupt id %d\n",
+					   intid);
+				continue;
+			}
+
+			if (priv->obj_flags[o] & CC770_OBJ_FLAG_RTR)
+				cc770_rtr_interrupt(dev, o);
+			else if (priv->obj_flags[o] & CC770_OBJ_FLAG_RX)
+				cc770_rx_interrupt(dev, o);
+			else
+				cc770_tx_interrupt(dev, o);
+		}
+	}
+
+	if (priv->post_irq)
+		priv->post_irq(priv);
+
+	if (n >= CC770_MAX_IRQ)
+		netdev_dbg(dev, "%d messages handled in ISR", n);
+
+	return (n) ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int cc770_open(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+	int err;
+
+	/* set chip into reset mode */
+	set_reset_mode(dev);
+
+	/* common open */
+	err = open_candev(dev);
+	if (err)
+		return err;
+
+	err = request_irq(dev->irq, &cc770_interrupt, priv->irq_flags,
+			  dev->name, (void *)dev);
+	if (err) {
+		close_candev(dev);
+		return -EAGAIN;
+	}
+
+	/* init and start chip */
+	cc770_start(dev);
+	priv->open_time = jiffies;
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int cc770_close(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	set_reset_mode(dev);
+
+	free_irq(dev->irq, (void *)dev);
+	close_candev(dev);
+
+	priv->open_time = 0;
+
+	return 0;
+}
+
+struct net_device *alloc_cc770dev(int sizeof_priv)
+{
+	struct net_device *dev;
+	struct cc770_priv *priv;
+
+	dev = alloc_candev(sizeof(struct cc770_priv) + sizeof_priv,
+			   CC770_ECHO_SKB_MAX);
+	if (!dev)
+		return NULL;
+
+	priv = netdev_priv(dev);
+
+	priv->dev = dev;
+	priv->can.bittiming_const = &cc770_bittiming_const;
+	priv->can.do_set_bittiming = cc770_set_bittiming;
+	priv->can.do_set_mode = cc770_set_mode;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+
+	memcpy(priv->obj_flags, cc770_obj_flags, sizeof(cc770_obj_flags));
+
+	if (sizeof_priv)
+		priv->priv = (void *)priv + sizeof(struct cc770_priv);
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(alloc_cc770dev);
+
+void free_cc770dev(struct net_device *dev)
+{
+	free_candev(dev);
+}
+EXPORT_SYMBOL_GPL(free_cc770dev);
+
+static const struct net_device_ops cc770_netdev_ops = {
+	.ndo_open = cc770_open,
+	.ndo_stop = cc770_close,
+	.ndo_start_xmit = cc770_start_xmit,
+};
+
+int register_cc770dev(struct net_device *dev)
+{
+	struct cc770_priv *priv = netdev_priv(dev);
+
+	if (!cc770_probe_chip(dev))
+		return -ENODEV;
+
+	dev->netdev_ops = &cc770_netdev_ops;
+
+	dev->flags |= IFF_ECHO;	/* we support local echo */
+
+	/* Should we use additional functions? */
+	if (!i82527_compat && priv->control_normal_mode & CTRL_EAF) {
+		priv->can.do_get_berr_counter = cc770_get_berr_counter;
+		priv->control_normal_mode = CTRL_IE | CTRL_EAF | CTRL_EIE;
+		netdev_dbg(dev, "i82527 mode with additional functions\n");
+	} else {
+		priv->control_normal_mode = CTRL_IE | CTRL_EIE;
+		netdev_dbg(dev, "strict i82527 compatibility mode\n");
+	}
+
+	chipset_init(priv);
+	set_reset_mode(dev);
+
+	return register_candev(dev);
+}
+EXPORT_SYMBOL_GPL(register_cc770dev);
+
+void unregister_cc770dev(struct net_device *dev)
+{
+	set_reset_mode(dev);
+	unregister_candev(dev);
+}
+EXPORT_SYMBOL_GPL(unregister_cc770dev);
+
+static __init int cc770_init(void)
+{
+	if (msgobj15_eff) {
+		cc770_obj_flags[CC770_OBJ_RX0] |= CC770_OBJ_FLAG_EFF;
+		cc770_obj_flags[CC770_OBJ_RX1] &= ~CC770_OBJ_FLAG_EFF;
+	}
+
+	pr_info("%s CAN netdevice driver\n", DRV_NAME);
+
+	return 0;
+}
+module_init(cc770_init);
+
+static __exit void cc770_exit(void)
+{
+	pr_info("%s: driver removed\n", DRV_NAME);
+}
+module_exit(cc770_exit);
diff --git a/drivers/net/can/cc770/cc770.h b/drivers/net/can/cc770/cc770.h
new file mode 100644
index 0000000..978528c
--- /dev/null
+++ b/drivers/net/can/cc770/cc770.h
@@ -0,0 +1,207 @@
+/*
+ * Core driver for the CC770 and AN82527 CAN controllers
+ *
+ * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CC770_DEV_H
+#define CC770_DEV_H
+
+#include <linux/can/dev.h>
+
+struct cc770_msgobj {
+	u8 ctrl0;
+	u8 ctrl1;
+	u8 id[4];
+	u8 config;
+	u8 data[8];
+	u8 dontuse;		/* padding */
+} __attribute__ ((packed));
+
+struct cc770_regs {
+	union {
+		struct cc770_msgobj msgobj[16]; /* Message object 1..15 */
+		struct {
+			u8 control;		/* Control Register */
+			u8 status;		/* Status Register */
+			u8 cpu_interface;	/* CPU Interface Register */
+			u8 dontuse1;
+			u8 high_speed_read[2];	/* High Speed Read */
+			u8 global_mask_std[2];	/* Standard Global Mask */
+			u8 global_mask_ext[4];	/* Extended Global Mask */
+			u8 msg15_mask[4];	/* Message 15 Mask */
+			u8 dontuse2[15];
+			u8 clkout;		/* Clock Out Register */
+			u8 dontuse3[15];
+			u8 bus_config;		/* Bus Configuration Register */
+			u8 dontuse4[15];
+			u8 bit_timing_0;	/* Bit Timing Register byte 0 */
+			u8 dontuse5[15];
+			u8 bit_timing_1;	/* Bit Timing Register byte 1 */
+			u8 dontuse6[15];
+			u8 interrupt;		/* Interrupt Register */
+			u8 dontuse7[15];
+			u8 rx_error_counter;	/* Receive Error Counter */
+			u8 dontuse8[15];
+			u8 tx_error_counter;	/* Transmit Error Counter */
+			u8 dontuse9[31];
+			u8 p1_conf;
+			u8 dontuse10[15];
+			u8 p2_conf;
+			u8 dontuse11[15];
+			u8 p1_in;
+			u8 dontuse12[15];
+			u8 p2_in;
+			u8 dontuse13[15];
+			u8 p1_out;
+			u8 dontuse14[15];
+			u8 p2_out;
+			u8 dontuse15[15];
+			u8 serial_reset_addr;
+		};
+	};
+} __attribute__ ((packed));
+
+/* Control Register (0x00) */
+#define CTRL_INI	0x01	/* Initialization */
+#define CTRL_IE		0x02	/* Interrupt Enable */
+#define CTRL_SIE	0x04	/* Status Interrupt Enable */
+#define CTRL_EIE	0x08	/* Error Interrupt Enable */
+#define CTRL_EAF	0x20	/* Enable additional functions */
+#define CTRL_CCE	0x40	/* Change Configuration Enable */
+
+/* Status Register (0x01) */
+#define STAT_LEC_STUFF	0x01	/* Stuff error */
+#define STAT_LEC_FORM	0x02	/* Form error */
+#define STAT_LEC_ACK	0x03	/* Acknowledgement error */
+#define STAT_LEC_BIT1	0x04	/* Bit1 error */
+#define STAT_LEC_BIT0	0x05	/* Bit0 error */
+#define STAT_LEC_CRC	0x06	/* CRC error */
+#define STAT_LEC_MASK	0x07	/* Last Error Code mask */
+#define STAT_TXOK	0x08	/* Transmit Message Successfully */
+#define STAT_RXOK	0x10	/* Receive Message Successfully */
+#define STAT_WAKE	0x20	/* Wake Up Status */
+#define STAT_WARN	0x40	/* Warning Status */
+#define STAT_BOFF	0x80	/* Bus Off Status */
+
+/*
+ * CPU Interface Register (0x02)
+ * Clock Out Register (0x1f)
+ * Bus Configuration Register (0x2f)
+ *
+ * see include/linux/can/platform/cc770.h
+ */
+
+/* Message Control Register 0 (Base Address + 0x0) */
+#define INTPND_RES	0x01	/* No Interrupt pending */
+#define INTPND_SET	0x02	/* Interrupt pending */
+#define INTPND_UNC	0x03
+#define RXIE_RES	0x04	/* Receive Interrupt Disable */
+#define RXIE_SET	0x08	/* Receive Interrupt Enable */
+#define RXIE_UNC	0x0c
+#define TXIE_RES	0x10	/* Transmit Interrupt Disable */
+#define TXIE_SET	0x20	/* Transmit Interrupt Enable */
+#define TXIE_UNC	0x30
+#define MSGVAL_RES	0x40	/* Message Invalid */
+#define MSGVAL_SET	0x80	/* Message Valid */
+#define MSGVAL_UNC	0xc0
+
+/* Message Control Register 1 (Base Address + 0x01) */
+#define NEWDAT_RES	0x01	/* No New Data */
+#define NEWDAT_SET	0x02	/* New Data */
+#define NEWDAT_UNC	0x03
+#define MSGLST_RES	0x04	/* No Message Lost */
+#define MSGLST_SET	0x08	/* Message Lost */
+#define MSGLST_UNC	0x0c
+#define CPUUPD_RES	0x04	/* No CPU Updating */
+#define CPUUPD_SET	0x08	/* CPU Updating */
+#define CPUUPD_UNC	0x0c
+#define TXRQST_RES	0x10	/* No Transmission Request */
+#define TXRQST_SET	0x20	/* Transmission Request */
+#define TXRQST_UNC	0x30
+#define RMTPND_RES	0x40	/* No Remote Request Pending */
+#define RMTPND_SET	0x80	/* Remote Request Pending */
+#define RMTPND_UNC	0xc0
+
+/* Message Configuration Register (Base Address + 0x06) */
+#define MSGCFG_XTD	0x04	/* Extended Identifier */
+#define MSGCFG_DIR	0x08	/* Direction is Transmit */
+
+#define MSGOBJ_FIRST	1
+#define MSGOBJ_LAST	15
+
+#define CC770_IO_SIZE	0x100
+#define CC770_MAX_IRQ	20	/* max. number of interrupts handled in ISR */
+
+#define CC770_ECHO_SKB_MAX	1
+
+#define cc770_read_reg(priv, member)					\
+	priv->read_reg(priv, offsetof(struct cc770_regs, member))
+
+#define cc770_write_reg(priv, member, value)				\
+	priv->write_reg(priv, offsetof(struct cc770_regs, member), value)
+
+/*
+ * Message objects and flags used by this driver
+ */
+#define CC770_OBJ_FLAG_RX 	0x01
+#define CC770_OBJ_FLAG_RTR	0x02
+#define CC770_OBJ_FLAG_EFF	0x04
+
+enum {
+	CC770_OBJ_RX0 = 0,	/* for receiving normal messages */
+	CC770_OBJ_RX1,		/* for receiving normal messages */
+	CC770_OBJ_RX_RTR0,	/* for receiving remote transmission requests */
+	CC770_OBJ_RX_RTR1,	/* for receiving remote transmission requests */
+	CC770_OBJ_TX,		/* for sending messages */
+	CC770_OBJ_MAX
+};
+
+#define obj2msgobj(o)	(MSGOBJ_LAST - (o)) /* message object 11..15 */
+
+/*
+ * CC770 private data structure
+ */
+struct cc770_priv {
+	struct can_priv can;	/* must be the first member */
+	int open_time;
+	struct sk_buff *echo_skb;
+
+	/* the lower-layer is responsible for appropriate locking */
+	u8 (*read_reg)(const struct cc770_priv *priv, int reg);
+	void (*write_reg)(const struct cc770_priv *priv, int reg, u8 val);
+	void (*pre_irq)(const struct cc770_priv *priv);
+	void (*post_irq)(const struct cc770_priv *priv);
+
+	void *priv;		/* for board-specific data */
+	struct net_device *dev;
+
+	void __iomem *reg_base;	/* ioremap'ed address to registers */
+	unsigned long irq_flags;	/* for request_irq() */
+
+	unsigned char obj_flags[CC770_OBJ_MAX];
+	u8 control_normal_mode;	/* Control register for normal mode */
+	u8 cpu_interface;	/* CPU interface register */
+	u8 clkout;		/* Clock out register */
+	u8 bus_config;		/* Bus conffiguration register */
+};
+
+struct net_device *alloc_cc770dev(int sizeof_priv);
+void free_cc770dev(struct net_device *dev);
+int register_cc770dev(struct net_device *dev);
+void unregister_cc770dev(struct net_device *dev);
+
+#endif /* CC770_DEV_H */
diff --git a/include/linux/can/platform/cc770.h b/include/linux/can/platform/cc770.h
new file mode 100644
index 0000000..c4ed994
--- /dev/null
+++ b/include/linux/can/platform/cc770.h
@@ -0,0 +1,33 @@
+#ifndef _CAN_PLATFORM_CC770_H_
+#define _CAN_PLATFORM_CC770_H_
+
+/* CPU Interface Register (0x02) */
+#define CPUIF_CEN	0x01	/* Clock Out Enable */
+#define CPUIF_MUX	0x04	/* Multiplex */
+#define CPUIF_SLP	0x08	/* Sleep */
+#define CPUIF_PWD	0x10	/* Power Down Mode */
+#define CPUIF_DMC	0x20	/* Divide Memory Clock */
+#define CPUIF_DSC	0x40	/* Divide System Clock */
+#define CPUIF_RST	0x80	/* Hardware Reset Status */
+
+/* Clock Out Register (0x1f) */
+#define CLKOUT_CD_MASK  0x0f	/* Clock Divider mask */
+#define CLKOUT_SL_MASK	0x30	/* Slew Rate mask */
+#define CLKOUT_SL_SHIFT	4
+
+/* Bus Configuration Register (0x2f) */
+#define BUSCFG_DR0	0x01	/* Disconnect RX0 Input / Select RX input */
+#define BUSCFG_DR1	0x02	/* Disconnect RX1 Input / Silent mode */
+#define BUSCFG_DT1	0x08	/* Disconnect TX1 Output */
+#define BUSCFG_POL	0x20	/* Polarity dominant or recessive */
+#define BUSCFG_CBY	0x40	/* Input Comparator Bypass */
+
+struct cc770_platform_data {
+	u32 osc_freq;	/* CAN bus oscillator frequency in Hz */
+
+	u8 cir;	 	/* CPU Interface Register */
+	u8 cor;		/* Clock Out Register */
+	u8 bcr;		/* Bus Configuration Register */
+};
+
+#endif	/* !_CAN_PLATFORM_CC770_H_ */
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH net-next v3 2/4] can: cc770: add legacy ISA bus driver for the CC770 and AN82527
From: Wolfgang Grandegger @ 2011-11-28 11:30 UTC (permalink / raw)
  To: netdev
  Cc: linux-can, socketcan-users, IreneV, Stanislav Yelenskiy,
	Wolfgang Zarre, Wolfgang Grandegger
In-Reply-To: <1322479858-4874-1-git-send-email-wg@grandegger.com>

This patch adds support for legacy Bosch CC770 and Intel AN82527 CAN
controllers on the ISA or PC-104 bus. The I/O port or memory address
and the IRQ number must be specified via module parameters:

  insmod cc770_isa.ko port=0x310,0x380 irq=7,11

for ISA devices using I/O ports or:

  insmod cc770_isa.ko mem=0xd1000,0xd1000 irq=7,11

for memory mapped ISA devices.

Indirect access via address and data port is supported as well:

  insmod cc770_isa.ko port=0x310,0x380 indirect=1 irq=7,11

Furthermore, the following mode parameter can be defined:

  clk: External oscillator clock frequency (default=16000000 [16 MHz])
  cir: CPU interface register (default=0x40 [DSC])
  bcr, Bus configuration register (default=0x40 [CBY])
  cor, Clockout register (default=0x00)

Note: for clk, cir, bcr and cor, the first argument re-defines the
default for all other devices, e.g.:

  insmod cc770_isa.ko mem=0xd1000,0xd1000 irq=7,11 clk=24000000

is equivalent to

  insmod cc770_isa.ko mem=0xd1000,0xd1000 irq=7,11 clk=24000000,24000000

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
 drivers/net/can/cc770/Kconfig     |   11 +
 drivers/net/can/cc770/Makefile    |    1 +
 drivers/net/can/cc770/cc770_isa.c |  372 +++++++++++++++++++++++++++++++++++++
 3 files changed, 384 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/cc770/cc770_isa.c

diff --git a/drivers/net/can/cc770/Kconfig b/drivers/net/can/cc770/Kconfig
index 225131b..28e4d48 100644
--- a/drivers/net/can/cc770/Kconfig
+++ b/drivers/net/can/cc770/Kconfig
@@ -1,3 +1,14 @@
 menuconfig CAN_CC770
 	tristate "Bosch CC770 and Intel AN82527 devices"
 	depends on CAN_DEV && HAS_IOMEM
+
+if CAN_CC770
+
+config CAN_CC770_ISA
+	tristate "ISA Bus based legacy CC770 driver"
+	---help---
+	  This driver adds legacy support for CC770 and AN82527 chips
+	  connected to the ISA bus using I/O port, memory mapped or
+	  indirect access.
+
+endif
diff --git a/drivers/net/can/cc770/Makefile b/drivers/net/can/cc770/Makefile
index 34e8180..872ecff 100644
--- a/drivers/net/can/cc770/Makefile
+++ b/drivers/net/can/cc770/Makefile
@@ -3,5 +3,6 @@
 #
 
 obj-$(CONFIG_CAN_CC770) += cc770.o
+obj-$(CONFIG_CAN_CC770_ISA) += cc770_isa.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c
new file mode 100644
index 0000000..6eae4af
--- /dev/null
+++ b/drivers/net/can/cc770/cc770_isa.c
@@ -0,0 +1,372 @@
+/*
+ * Driver for CC770 and AN82527 CAN controllers on the legacy ISA bus
+ *
+ * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Bosch CC770 and Intel AN82527 CAN controllers on the ISA or PC-104 bus.
+ * The I/O port or memory address and the IRQ number must be specified via
+ * module parameters:
+ *
+ *   insmod cc770_isa.ko port=0x310,0x380 irq=7,11
+ *
+ * for ISA devices using I/O ports or:
+ *
+ *   insmod cc770_isa.ko mem=0xd1000,0xd1000 irq=7,11
+ *
+ * for memory mapped ISA devices.
+ *
+ * Indirect access via address and data port is supported as well:
+ *
+ *   insmod cc770_isa.ko port=0x310,0x380 indirect=1 irq=7,11
+ *
+ * Furthermore, the following mode parameter can be defined:
+ *
+ *   clk: External oscillator clock frequency (default=16000000 [16 MHz])
+ *   cir: CPU interface register (default=0x40 [DSC])
+ *   bcr, Bus configuration register (default=0x40 [CBY])
+ *   cor, Clockout register (default=0x00)
+ *
+ * Note: for clk, cir, bcr and cor, the first argument re-defines the
+ * default for all other devices, e.g.:
+ *
+ *   insmod cc770_isa.ko mem=0xd1000,0xd1000 irq=7,11 clk=24000000
+ *
+ * is equivalent to
+ *
+ *   insmod cc770_isa.ko mem=0xd1000,0xd1000 irq=7,11 clk=24000000,24000000
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+
+#include "cc770.h"
+
+#define DRV_NAME "cc770_isa"
+
+#define MAXDEV 8
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for CC770 on the ISA bus");
+MODULE_LICENSE("GPL v2");
+
+#define CLK_DEFAULT	16000000	/* 16 MHz */
+#define COR_DEFAULT	0x00
+#define BCR_DEFAULT	BUSCFG_CBY
+
+static unsigned long port[MAXDEV];
+static unsigned long mem[MAXDEV];
+static int __devinitdata irq[MAXDEV];
+static int __devinitdata clk[MAXDEV];
+static u8 __devinitdata cir[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static u8 __devinitdata cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static u8 __devinitdata bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static int __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+
+module_param_array(port, ulong, NULL, S_IRUGO);
+MODULE_PARM_DESC(port, "I/O port number");
+
+module_param_array(mem, ulong, NULL, S_IRUGO);
+MODULE_PARM_DESC(mem, "I/O memory address");
+
+module_param_array(indirect, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(indirect, "Indirect access via address and data port");
+
+module_param_array(irq, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(irq, "IRQ number");
+
+module_param_array(clk, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(clk, "External oscillator clock frequency "
+		 "(default=16000000 [16 MHz])");
+
+module_param_array(cir, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(cir, "CPU interface register (default=0x40 [DSC])");
+
+module_param_array(cor, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(cor, "Clockout register (default=0x00)");
+
+module_param_array(bcr, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bcr, "Bus configuration register (default=0x40 [CBY])");
+
+#define CC770_IOSIZE          0x20
+#define CC770_IOSIZE_INDIRECT 0x02
+
+static struct platform_device *cc770_isa_devs[MAXDEV];
+
+static u8 cc770_isa_mem_read_reg(const struct cc770_priv *priv, int reg)
+{
+	return readb(priv->reg_base + reg);
+}
+
+static void cc770_isa_mem_write_reg(const struct cc770_priv *priv,
+				      int reg, u8 val)
+{
+	writeb(val, priv->reg_base + reg);
+}
+
+static u8 cc770_isa_port_read_reg(const struct cc770_priv *priv, int reg)
+{
+	return inb((unsigned long)priv->reg_base + reg);
+}
+
+static void cc770_isa_port_write_reg(const struct cc770_priv *priv,
+				       int reg, u8 val)
+{
+	outb(val, (unsigned long)priv->reg_base + reg);
+}
+
+static u8 cc770_isa_port_read_reg_indirect(const struct cc770_priv *priv,
+					     int reg)
+{
+	unsigned long base = (unsigned long)priv->reg_base;
+
+	outb(reg, base);
+	return inb(base + 1);
+}
+
+static void cc770_isa_port_write_reg_indirect(const struct cc770_priv *priv,
+						int reg, u8 val)
+{
+	unsigned long base = (unsigned long)priv->reg_base;
+
+	outb(reg, base);
+	outb(val, base + 1);
+}
+
+static int __devinit cc770_isa_probe(struct platform_device *pdev)
+{
+	struct net_device *dev;
+	struct cc770_priv *priv;
+	void __iomem *base = NULL;
+	int iosize = CC770_IOSIZE;
+	int idx = pdev->id;
+	int err;
+	u32 clktmp;
+
+	dev_dbg(&pdev->dev, "probing idx=%d: port=%#lx, mem=%#lx, irq=%d\n",
+		idx, port[idx], mem[idx], irq[idx]);
+	if (mem[idx]) {
+		if (!request_mem_region(mem[idx], iosize, DRV_NAME)) {
+			err = -EBUSY;
+			goto exit;
+		}
+		base = ioremap_nocache(mem[idx], iosize);
+		if (!base) {
+			err = -ENOMEM;
+			goto exit_release;
+		}
+	} else {
+		if (indirect[idx] > 0 ||
+		    (indirect[idx] == -1 && indirect[0] > 0))
+			iosize = CC770_IOSIZE_INDIRECT;
+		if (!request_region(port[idx], iosize, DRV_NAME)) {
+			err = -EBUSY;
+			goto exit;
+		}
+	}
+
+	dev = alloc_cc770dev(0);
+	if (!dev) {
+		err = -ENOMEM;
+		goto exit_unmap;
+	}
+	priv = netdev_priv(dev);
+
+	dev->irq = irq[idx];
+	priv->irq_flags = IRQF_SHARED;
+	if (mem[idx]) {
+		priv->reg_base = base;
+		dev->base_addr = mem[idx];
+		priv->read_reg = cc770_isa_mem_read_reg;
+		priv->write_reg = cc770_isa_mem_write_reg;
+	} else {
+		priv->reg_base = (void __iomem *)port[idx];
+		dev->base_addr = port[idx];
+
+		if (iosize == CC770_IOSIZE_INDIRECT) {
+			priv->read_reg = cc770_isa_port_read_reg_indirect;
+			priv->write_reg = cc770_isa_port_write_reg_indirect;
+		} else {
+			priv->read_reg = cc770_isa_port_read_reg;
+			priv->write_reg = cc770_isa_port_write_reg;
+		}
+	}
+
+	if (clk[idx])
+		clktmp = clk[idx];
+	else if (clk[0])
+		clktmp = clk[0];
+	else
+		clktmp = CLK_DEFAULT;
+	priv->can.clock.freq = clktmp;
+
+	if (cir[idx] != 0xff) {
+		priv->cpu_interface = cir[idx] & 0xff;
+	} else if (cir[0] != 0xff) {
+		priv->cpu_interface = cir[0] & 0xff;
+	} else {
+		/* The system clock may not exceed 10 MHz */
+		if (clktmp > 10000000) {
+			priv->cpu_interface |= CPUIF_DSC;
+			clktmp /= 2;
+		}
+		/* The memory clock may not exceed 8 MHz */
+		if (clktmp > 8000000)
+			priv->cpu_interface |= CPUIF_DMC;
+	}
+
+	if (priv->cpu_interface & CPUIF_DSC)
+		priv->can.clock.freq /= 2;
+
+	if (bcr[idx] != 0xff)
+		priv->bus_config = bcr[idx] & 0xff;
+	else if (bcr[0] != 0xff)
+		priv->bus_config = bcr[0] & 0xff;
+	else
+		priv->bus_config = BCR_DEFAULT;
+
+	if (cor[idx] != 0xff)
+		priv->clkout = cor[idx];
+	else if (cor[0] != 0xff)
+		priv->clkout = cor[0] & 0xff;
+	else
+		priv->clkout = COR_DEFAULT;
+
+	dev_set_drvdata(&pdev->dev, dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	err = register_cc770dev(dev);
+	if (err) {
+		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
+			DRV_NAME, err);
+		goto exit_unmap;
+	}
+
+	dev_info(&pdev->dev, "%s device registered (reg_base=0x%p, irq=%d)\n",
+		 DRV_NAME, priv->reg_base, dev->irq);
+	return 0;
+
+ exit_unmap:
+	if (mem[idx])
+		iounmap(base);
+ exit_release:
+	if (mem[idx])
+		release_mem_region(mem[idx], iosize);
+	else
+		release_region(port[idx], iosize);
+ exit:
+	return err;
+}
+
+static int __devexit cc770_isa_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = dev_get_drvdata(&pdev->dev);
+	struct cc770_priv *priv = netdev_priv(dev);
+	int idx = pdev->id;
+
+	unregister_cc770dev(dev);
+	dev_set_drvdata(&pdev->dev, NULL);
+
+	if (mem[idx]) {
+		iounmap(priv->reg_base);
+		release_mem_region(mem[idx], CC770_IOSIZE);
+	} else {
+		if (priv->read_reg == cc770_isa_port_read_reg_indirect)
+			release_region(port[idx], CC770_IOSIZE_INDIRECT);
+		else
+			release_region(port[idx], CC770_IOSIZE);
+	}
+	free_cc770dev(dev);
+
+	return 0;
+}
+
+static struct platform_driver cc770_isa_driver = {
+	.probe = cc770_isa_probe,
+	.remove = __devexit_p(cc770_isa_remove),
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init cc770_isa_init(void)
+{
+	int idx, err;
+
+	for (idx = 0; idx < MAXDEV; idx++) {
+		if ((port[idx] || mem[idx]) && irq[idx]) {
+			cc770_isa_devs[idx] =
+				platform_device_alloc(DRV_NAME, idx);
+			if (!cc770_isa_devs[idx]) {
+				err = -ENOMEM;
+				goto exit_free_devices;
+			}
+			err = platform_device_add(cc770_isa_devs[idx]);
+			if (err) {
+				platform_device_put(cc770_isa_devs[idx]);
+				goto exit_free_devices;
+			}
+			pr_debug("%s: platform device %d: port=%#lx, mem=%#lx, "
+				 "irq=%d\n",
+				 DRV_NAME, idx, port[idx], mem[idx], irq[idx]);
+		} else if (idx == 0 || port[idx] || mem[idx]) {
+				pr_err("%s: insufficient parameters supplied\n",
+				       DRV_NAME);
+				err = -EINVAL;
+				goto exit_free_devices;
+		}
+	}
+
+	err = platform_driver_register(&cc770_isa_driver);
+	if (err)
+		goto exit_free_devices;
+
+	pr_info("Legacy %s driver for max. %d devices registered\n",
+		DRV_NAME, MAXDEV);
+
+	return 0;
+
+exit_free_devices:
+	while (--idx >= 0) {
+		if (cc770_isa_devs[idx])
+			platform_device_unregister(cc770_isa_devs[idx]);
+	}
+
+	return err;
+}
+module_init(cc770_isa_init);
+
+static void __exit cc770_isa_exit(void)
+{
+	int idx;
+
+	platform_driver_unregister(&cc770_isa_driver);
+	for (idx = 0; idx < MAXDEV; idx++) {
+		if (cc770_isa_devs[idx])
+			platform_device_unregister(cc770_isa_devs[idx]);
+	}
+}
+module_exit(cc770_isa_exit);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH net-next v3 4/4] powerpc: tqm8548/tqm8xx: add and update CAN device nodes
From: Wolfgang Grandegger @ 2011-11-28 11:30 UTC (permalink / raw)
  To: netdev
  Cc: linux-can, socketcan-users, IreneV, Stanislav Yelenskiy,
	Wolfgang Zarre, Wolfgang Grandegger, devicetree-discuss,
	linuxppc-dev, Kumar Gala
In-Reply-To: <1322479858-4874-1-git-send-email-wg@grandegger.com>

This patch enables or updates support for the CC770 and AN82527
CAN controller on the TQM8548 and TQM8xx boards.

CC: devicetree-discuss@lists.ozlabs.org
CC: linuxppc-dev@ozlabs.org
CC: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
 arch/powerpc/boot/dts/tqm8548-bigflash.dts |   19 ++++++++++++++-----
 arch/powerpc/boot/dts/tqm8548.dts          |   19 ++++++++++++++-----
 arch/powerpc/boot/dts/tqm8xx.dts           |   25 +++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 9452c3c..d918752 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -352,7 +352,7 @@
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
 			1 0x0 0xf8000000 0x08000000	// NOR FLASH bank 0
-			2 0x0 0xa3000000 0x00008000	// CAN (2 x i82527)
+			2 0x0 0xa3000000 0x00008000	// CAN (2 x CC770)
 			3 0x0 0xa3010000 0x00008000	// NAND FLASH
 
 		>;
@@ -393,18 +393,27 @@
 		};
 
 		/* Note: CAN support needs be enabled in U-Boot */
-		can0@2,0 {
-			compatible = "intel,82527"; // Bosch CC770
+		can@2,0 {
+			compatible = "bosch,cc770"; // Bosch CC770
 			reg = <2 0x0 0x100>;
 			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
+			bosch,clock-out-frequency = <16000000>;
 		};
 
-		can1@2,100 {
-			compatible = "intel,82527"; // Bosch CC770
+		can@2,100 {
+			compatible = "bosch,cc770"; // Bosch CC770
 			reg = <2 0x100 0x100>;
 			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
 		};
 
 		/* Note: NAND support needs to be enabled in U-Boot */
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index 619776f..988d887 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -352,7 +352,7 @@
 		ranges = <
 			0 0x0 0xfc000000 0x04000000	// NOR FLASH bank 1
 			1 0x0 0xf8000000 0x08000000	// NOR FLASH bank 0
-			2 0x0 0xe3000000 0x00008000	// CAN (2 x i82527)
+			2 0x0 0xe3000000 0x00008000	// CAN (2 x CC770)
 			3 0x0 0xe3010000 0x00008000	// NAND FLASH
 
 		>;
@@ -393,18 +393,27 @@
 		};
 
 		/* Note: CAN support needs be enabled in U-Boot */
-		can0@2,0 {
-			compatible = "intel,82527"; // Bosch CC770
+		can@2,0 {
+			compatible = "bosch,cc770"; // Bosch CC770
 			reg = <2 0x0 0x100>;
 			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
+			bosch,clock-out-frequency = <16000000>;
 		};
 
-		can1@2,100 {
-			compatible = "intel,82527"; // Bosch CC770
+		can@2,100 {
+			compatible = "bosch,cc770"; // Bosch CC770
 			reg = <2 0x100 0x100>;
 			interrupts = <4 1>;
 			interrupt-parent = <&mpic>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
 		};
 
 		/* Note: NAND support needs to be enabled in U-Boot */
diff --git a/arch/powerpc/boot/dts/tqm8xx.dts b/arch/powerpc/boot/dts/tqm8xx.dts
index f6da7ec..c3dba25 100644
--- a/arch/powerpc/boot/dts/tqm8xx.dts
+++ b/arch/powerpc/boot/dts/tqm8xx.dts
@@ -57,6 +57,7 @@
 
 		ranges = <
 			0x0 0x0 0x40000000 0x800000
+			0x3 0x0 0xc0000000 0x200
 		>;
 
 		flash@0,0 {
@@ -67,6 +68,30 @@
 			bank-width = <4>;
 			device-width = <2>;
 		};
+
+		/* Note: CAN support needs be enabled in U-Boot */
+		can@3,0 {
+			compatible = "intc,82527";
+			reg = <3 0x0 0x80>;
+			interrupts = <8 1>;
+			interrupt-parent = <&PIC>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
+			bosch,clock-out-frequency = <16000000>;
+		};
+
+		can@3,100 {
+			compatible = "intc,82527";
+			reg = <3 0x100 0x80>;
+			interrupts = <8 1>;
+			interrupt-parent = <&PIC>;
+			bosch,external-clock-frequency = <16000000>;
+			bosch,disconnect-rx1-input;
+			bosch,disconnect-tx1-output;
+			bosch,iso-low-speed-mux;
+		};
 	};
 
 	soc@fff00000 {
-- 
1.7.4.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox