* [net-next 04/10] bnx2x: Enable FC when parallel-detect is used
From: Yaniv Rosner @ 2009-11-05 17:18 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eilong
When parallel detect is used, flow-control is set to the req_fc_auto_adv
instead of none.
Motive: when 577xx is FC configuration is set to AUTO, while LP speed is set to
FORCE mode and FC to force RX/TX, link would come up using parallel detect, and
the FC will be set to NONE since FC capabilities were not negotiated, although
the LP is setting FC to force RX/TX.
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x_link.c | 37 +++++++++++++++++++++++++++++++++++++
drivers/net/bnx2x_reg.h | 4 ++++
2 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c
index bf1021e..4c16a46 100644
--- a/drivers/net/bnx2x_link.c
+++ b/drivers/net/bnx2x_link.c
@@ -1621,6 +1621,39 @@ static u8 bnx2x_ext_phy_resolve_fc(struct link_params *params,
return ret;
}
+static u8 bnx2x_direct_parallel_detect_used(struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u16 pd_10g, status2_1000x;
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_SERDES_DIGITAL,
+ MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
+ &status2_1000x);
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_SERDES_DIGITAL,
+ MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
+ &status2_1000x);
+ if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) {
+ DP(NETIF_MSG_LINK, "1G parallel detect link on port %d\n",
+ params->port);
+ return 1;
+ }
+
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_10G_PARALLEL_DETECT,
+ MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
+ &pd_10g);
+
+ if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) {
+ DP(NETIF_MSG_LINK, "10G parallel detect link on port %d\n",
+ params->port);
+ return 1;
+ }
+ return 0;
+}
static void bnx2x_flow_ctrl_resolve(struct link_params *params,
struct link_vars *vars,
@@ -1639,6 +1672,10 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
(!(vars->phy_flags & PHY_SGMII_FLAG)) &&
(XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
+ if (bnx2x_direct_parallel_detect_used(params)) {
+ vars->flow_ctrl = params->req_fc_auto_adv;
+ return;
+ }
if ((gp_status &
(MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h
index b80fde4..4be9bab 100644
--- a/drivers/net/bnx2x_reg.h
+++ b/drivers/net/bnx2x_reg.h
@@ -4920,6 +4920,8 @@
#define MDIO_REG_BANK_10G_PARALLEL_DETECT 0x8130
+#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS 0x10
+#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK 0x8000
#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL 0x11
#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN 0x1
#define MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK 0x13
@@ -4944,6 +4946,8 @@
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_1G 0x0010
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_100M 0x0008
#define MDIO_SERDES_DIGITAL_A_1000X_STATUS1_SPEED_10M 0x0000
+#define MDIO_SERDES_DIGITAL_A_1000X_STATUS2 0x15
+#define MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED 0x0002
#define MDIO_SERDES_DIGITAL_MISC1 0x18
#define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_MASK 0xE000
#define MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_25M 0x0000
--
1.6.5.2
^ permalink raw reply related
* [net-next 03/10] bnx2x: Miscellaneous debug print and tabs
From: Yaniv Rosner @ 2009-11-05 17:18 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eilong
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x_link.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c
index eabdd11..bf1021e 100644
--- a/drivers/net/bnx2x_link.c
+++ b/drivers/net/bnx2x_link.c
@@ -1350,6 +1350,7 @@ static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params)
static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc)
{
+ struct bnx2x *bp = params->bp;
*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
/* resolve pause mode and advertisement
* Please refer to Table 28B-3 of the 802.3ab-1999 spec */
@@ -1379,6 +1380,7 @@ static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u16 *ieee_fc)
*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
break;
}
+ DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
}
static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
@@ -6143,7 +6145,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
offsetof(struct shmem_region, dev_info.
port_feature_config[params->port].
config));
-
+ DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
/* disable attentions */
vars->link_status = 0;
bnx2x_update_mng(params, vars->link_status);
--
1.6.5.2
^ permalink raw reply related
* [net-next 02/10] bnx2x: Fix CL73 autoneg issues
From: Yaniv Rosner @ 2009-11-05 17:18 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eilong
- Advertise 1G KX4 in CL73 when 1G speed capability is enabled
- Add flow-control negotiation over CL73
- External loopback test on Serdes should be done in FORCE mode, since in
CL73 it is unable to link up with the same core using AUTONEG
- Fix bnx2x_set_led function to support CL73 link leds
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x_link.c | 132 +++++++++++++++++++++++++++++-----------------
drivers/net/bnx2x_link.h | 3 +-
drivers/net/bnx2x_main.c | 16 ++----
drivers/net/bnx2x_reg.h | 18 +++++--
4 files changed, 104 insertions(+), 65 deletions(-)
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c
index b5964cb..eabdd11 100644
--- a/drivers/net/bnx2x_link.c
+++ b/drivers/net/bnx2x_link.c
@@ -1228,7 +1228,7 @@ static void bnx2x_set_autoneg(struct link_params *params,
params->phy_addr,
MDIO_REG_BANK_CL73_USERB0,
MDIO_CL73_USERB0_CL73_UCTRL,
- MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL);
+ 0xe);
/* Enable BAM Station Manager*/
CL45_WR_OVER_CL22(bp, params->port,
@@ -1239,29 +1239,25 @@ static void bnx2x_set_autoneg(struct link_params *params,
MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
- /* Merge CL73 and CL37 aneg resolution */
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
- MDIO_REG_BANK_CL73_USERB0,
- MDIO_CL73_USERB0_CL73_BAM_CTRL3,
- ®_val);
-
- if (params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) {
- /* Set the CL73 AN speed */
+ /* Advertise CL73 link speeds */
CL45_RD_OVER_CL22(bp, params->port,
params->phy_addr,
MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_ADV2,
®_val);
+ if (params->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
+ reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
+ if (params->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+ reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
CL45_WR_OVER_CL22(bp, params->port,
params->phy_addr,
MDIO_REG_BANK_CL73_IEEEB1,
MDIO_CL73_IEEEB1_AN_ADV2,
- reg_val | MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4);
+ reg_val);
- }
/* CL73 Autoneg Enabled */
reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
@@ -1389,12 +1385,23 @@ static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params,
u16 ieee_fc)
{
struct bnx2x *bp = params->bp;
+ u16 val;
/* for AN, we are always publishing full duplex */
CL45_WR_OVER_CL22(bp, params->port,
params->phy_addr,
MDIO_REG_BANK_COMBO_IEEE0,
MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_ADV1, &val);
+ val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
+ val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
+ CL45_WR_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_ADV1, val);
}
static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73)
@@ -1630,21 +1637,49 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
(!(vars->phy_flags & PHY_SGMII_FLAG)) &&
(XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)) {
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
- MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
- &ld_pause);
- CL45_RD_OVER_CL22(bp, params->port,
- params->phy_addr,
- MDIO_REG_BANK_COMBO_IEEE0,
- MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
- &lp_pause);
- pause_result = (ld_pause &
+ if ((gp_status &
+ (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
+ MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
+ (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
+ MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
+
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_ADV1,
+ &ld_pause);
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_CL73_IEEEB1,
+ MDIO_CL73_IEEEB1_AN_LP_ADV1,
+ &lp_pause);
+ pause_result = (ld_pause &
+ MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK)
+ >> 8;
+ pause_result |= (lp_pause &
+ MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK)
+ >> 10;
+ DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
+ pause_result);
+ } else {
+
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_COMBO_IEEE0,
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
+ &ld_pause);
+ CL45_RD_OVER_CL22(bp, params->port,
+ params->phy_addr,
+ MDIO_REG_BANK_COMBO_IEEE0,
+ MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
+ &lp_pause);
+ pause_result = (ld_pause &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
- pause_result |= (lp_pause &
+ pause_result |= (lp_pause &
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
- DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
+ DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
+ pause_result);
+ }
bnx2x_pause_resolve(vars, pause_result);
} else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
(bnx2x_ext_phy_resolve_fc(params, vars))) {
@@ -1990,8 +2025,7 @@ static u8 bnx2x_emac_program(struct link_params *params,
GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
mode);
- bnx2x_set_led(bp, params->port, LED_MODE_OPER,
- line_speed, params->hw_led_mode, params->chip_id);
+ bnx2x_set_led(params, LED_MODE_OPER, line_speed);
return 0;
}
@@ -3547,7 +3581,10 @@ static void bnx2x_init_internal_phy(struct link_params *params,
bnx2x_set_preemphasis(params);
/* forced speed requested? */
- if (vars->line_speed != SPEED_AUTO_NEG) {
+ if (vars->line_speed != SPEED_AUTO_NEG ||
+ ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
+ params->loopback_mode == LOOPBACK_EXT)) {
DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
/* disable autoneg */
@@ -5731,13 +5768,15 @@ u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port,
}
-u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
- u16 hw_led_mode, u32 chip_id)
+u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed)
{
+ u8 port = params->port;
+ u16 hw_led_mode = params->hw_led_mode;
u8 rc = 0;
u32 tmp;
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-
+ u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+ struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
speed, hw_led_mode);
@@ -5752,7 +5791,14 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
break;
case LED_MODE_OPER:
- REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
+ if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
+ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
+ REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
+ } else {
+ REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
+ hw_led_mode);
+ }
+
REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
port*4, 0);
/* Set blinking rate to ~15.9Hz */
@@ -5764,7 +5810,7 @@ u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
EMAC_WR(bp, EMAC_REG_EMAC_LED,
(tmp & (~EMAC_LED_OVERRIDE)));
- if (!CHIP_IS_E1H(bp) &&
+ if (CHIP_IS_E1(bp) &&
((speed == SPEED_2500) ||
(speed == SPEED_1000) ||
(speed == SPEED_100) ||
@@ -6033,10 +6079,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
params->port*4, 0);
- bnx2x_set_led(bp, params->port, LED_MODE_OPER,
- vars->line_speed, params->hw_led_mode,
- params->chip_id);
-
+ bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed);
} else
/* No loopback */
{
@@ -6094,8 +6137,6 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
{
struct bnx2x *bp = params->bp;
u32 ext_phy_config = params->ext_phy_config;
- u16 hw_led_mode = params->hw_led_mode;
- u32 chip_id = params->chip_id;
u8 port = params->port;
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
u32 val = REG_RD(bp, params->shmem_base +
@@ -6130,7 +6171,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
* Hold it as vars low
*/
/* clear link led */
- bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id);
+ bnx2x_set_led(params, LED_MODE_OFF, 0);
if (reset_ext_phy) {
switch (ext_phy_type) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
@@ -6201,9 +6242,7 @@ static u8 bnx2x_update_link_down(struct link_params *params,
u8 port = params->port;
DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
- bnx2x_set_led(bp, port, LED_MODE_OFF,
- 0, params->hw_led_mode,
- params->chip_id);
+ bnx2x_set_led(params, LED_MODE_OFF, 0);
/* indicate no mac active */
vars->mac_type = MAC_TYPE_NONE;
@@ -6240,10 +6279,7 @@ static u8 bnx2x_update_link_up(struct link_params *params,
vars->link_status |= LINK_STATUS_LINK_UP;
if (link_10g) {
bnx2x_bmac_enable(params, vars, 0);
- bnx2x_set_led(bp, port, LED_MODE_OPER,
- SPEED_10000, params->hw_led_mode,
- params->chip_id);
-
+ bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000);
} else {
bnx2x_emac_enable(params, vars, 0);
rc = bnx2x_emac_program(params, vars->line_speed,
diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x_link.h
index f3e2522..40c2981 100644
--- a/drivers/net/bnx2x_link.h
+++ b/drivers/net/bnx2x_link.h
@@ -178,8 +178,7 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
Basically, the CLC takes care of the led for the link, but in case one needs
to set/unset the led unnaturally, set the "mode" to LED_MODE_OPER to
blink the led, and LED_MODE_OFF to set the led off.*/
-u8 bnx2x_set_led(struct bnx2x *bp, u8 port, u8 mode, u32 speed,
- u16 hw_led_mode, u32 chip_id);
+u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed);
#define LED_MODE_OFF 0
#define LED_MODE_OPER 2
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 59b58d8..6f16547 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -10855,7 +10855,6 @@ static void bnx2x_get_ethtool_stats(struct net_device *dev,
static int bnx2x_phys_id(struct net_device *dev, u32 data)
{
struct bnx2x *bp = netdev_priv(dev);
- int port = BP_PORT(bp);
int i;
if (!netif_running(dev))
@@ -10869,13 +10868,10 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
for (i = 0; i < (data * 2); i++) {
if ((i % 2) == 0)
- bnx2x_set_led(bp, port, LED_MODE_OPER, SPEED_1000,
- bp->link_params.hw_led_mode,
- bp->link_params.chip_id);
+ bnx2x_set_led(&bp->link_params, LED_MODE_OPER,
+ SPEED_1000);
else
- bnx2x_set_led(bp, port, LED_MODE_OFF, 0,
- bp->link_params.hw_led_mode,
- bp->link_params.chip_id);
+ bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0);
msleep_interruptible(500);
if (signal_pending(current))
@@ -10883,10 +10879,8 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
}
if (bp->link_vars.link_up)
- bnx2x_set_led(bp, port, LED_MODE_OPER,
- bp->link_vars.line_speed,
- bp->link_params.hw_led_mode,
- bp->link_params.chip_id);
+ bnx2x_set_led(&bp->link_params, LED_MODE_OPER,
+ bp->link_vars.line_speed);
return 0;
}
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h
index aa76cba..b80fde4 100644
--- a/drivers/net/bnx2x_reg.h
+++ b/drivers/net/bnx2x_reg.h
@@ -4772,18 +4772,28 @@
#define PCI_ID_VAL2 0x438
-#define MDIO_REG_BANK_CL73_IEEEB0 0x0
-#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL 0x0
+#define MDIO_REG_BANK_CL73_IEEEB0 0x0
+#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL 0x0
#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN 0x0200
#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN 0x1000
#define MDIO_CL73_IEEEB0_CL73_AN_CONTROL_MAIN_RST 0x8000
-#define MDIO_REG_BANK_CL73_IEEEB1 0x10
-#define MDIO_CL73_IEEEB1_AN_ADV2 0x01
+#define MDIO_REG_BANK_CL73_IEEEB1 0x10
+#define MDIO_CL73_IEEEB1_AN_ADV1 0x00
+#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE 0x0400
+#define MDIO_CL73_IEEEB1_AN_ADV1_ASYMMETRIC 0x0800
+#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH 0x0C00
+#define MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK 0x0C00
+#define MDIO_CL73_IEEEB1_AN_ADV2 0x01
#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M 0x0000
#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX 0x0020
#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 0x0040
#define MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KR 0x0080
+#define MDIO_CL73_IEEEB1_AN_LP_ADV1 0x03
+#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE 0x0400
+#define MDIO_CL73_IEEEB1_AN_LP_ADV1_ASYMMETRIC 0x0800
+#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_BOTH 0x0C00
+#define MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK 0x0C00
#define MDIO_REG_BANK_RX0 0x80b0
#define MDIO_RX0_RX_STATUS 0x10
--
1.6.5.2
^ permalink raw reply related
* [net-next 00/10] bnx2x: Link related changes
From: Yaniv Rosner @ 2009-11-05 17:18 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eilong
Hi Dave,
The following are bnx2x link changes intended for net-next.
Thanks,
Yaniv
^ permalink raw reply
* [net-next 01/10] bnx2x: Fix Parallel-Detect settings
From: Yaniv Rosner @ 2009-11-05 17:18 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eilong
Enable Parallel-Detect for 10G and 1G only if the relevant speed capability is enabled
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x_link.c | 15 +++++++++------
1 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c
index e32d337..b5964cb 100644
--- a/drivers/net/bnx2x_link.c
+++ b/drivers/net/bnx2x_link.c
@@ -1107,18 +1107,21 @@ static void bnx2x_set_parallel_detection(struct link_params *params,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
&control2);
-
-
- control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
-
-
+ if (params->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+ control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
+ else
+ control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
+ DP(NETIF_MSG_LINK, "params->speed_cap_mask = 0x%x, control2 = 0x%x\n",
+ params->speed_cap_mask, control2);
CL45_WR_OVER_CL22(bp, params->port,
params->phy_addr,
MDIO_REG_BANK_SERDES_DIGITAL,
MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
control2);
- if (phy_flags & PHY_XGXS_FLAG) {
+ if ((phy_flags & PHY_XGXS_FLAG) &&
+ (params->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
DP(NETIF_MSG_LINK, "XGXS\n");
CL45_WR_OVER_CL22(bp, params->port,
--
1.6.5.2
^ permalink raw reply related
* Re: [RFC] [PATCH] udp: optimize lookup of UDP sockets to by including destination address in the hash key
From: Andi Kleen @ 2009-11-05 15:16 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Andi Kleen, Octavian Purdila, Lucian Adrian Grijincu, netdev
In-Reply-To: <4AF2EA2D.6040301@gmail.com>
On Thu, Nov 05, 2009 at 04:07:25PM +0100, Eric Dumazet wrote:
> Andi Kleen a écrit :
> >> I assume cache is cold or even on other cpu (worst case), dealing with
> >> 100.000+ sockets or so...
> >
> > Other CPU cache hit is actually typically significantly
> > faster than a DRAM access (unless you're talking about a very large NUMA
> > system and a remote CPU far away)
>
> Even if data is dirty in remote CPU cache ?
Some cache protocols have to force dirty data through DRAM, but modern
ones usually do not.
-Andi
^ permalink raw reply
* Re: [RFC] [PATCH] udp: optimize lookup of UDP sockets to by including destination address in the hash key
From: Eric Dumazet @ 2009-11-05 15:07 UTC (permalink / raw)
To: Andi Kleen; +Cc: Octavian Purdila, Lucian Adrian Grijincu, netdev
In-Reply-To: <20091105145428.GS31511@one.firstfloor.org>
Andi Kleen a écrit :
>> I assume cache is cold or even on other cpu (worst case), dealing with
>> 100.000+ sockets or so...
>
> Other CPU cache hit is actually typically significantly
> faster than a DRAM access (unless you're talking about a very large NUMA
> system and a remote CPU far away)
Even if data is dirty in remote CPU cache ?
I dont speak of shared data. (if data is shared, workload mostly fits caches)
>> If workload fits in one CPU cache/registers, we dont mind taking one
>> or two cache lines per object, obviously.
>
> It's more like part of your workload needs to fit.
>
> For example if you use a tree and the higher levels fit into
> the cache, having a few levels in the tree is (approximately) free.
>
> That's why I'm not always fond of large hash tables. They pretty
> much guarantee a lot of cache misses under high load, because
> they have little locality.
We already had this discussion Andi, and you know some servers handle 1.000.000+
sockets, 100.000+ frames per second on XX.XXX different flows, and a binary tree
means 20 accesses before target. Only 5 or 6 first levels are in cache.
Machine is barely usable.
hash table with 2.000.000 slots gives one or two accesses before target,
and rcu is trivial with hash tables.
btree are ok for generalist workloads, and rcu is more complex.
^ permalink raw reply
* Re: [net-next-2.6 PATCH RFC] TCPCT part 1d: generate Responder Cookie
From: Paul E. McKenney @ 2009-11-05 14:59 UTC (permalink / raw)
To: William Allen Simpson
Cc: Eric Dumazet, Linux Kernel Developers,
Linux Kernel Network Developers
In-Reply-To: <4AF2C266.1010603@gmail.com>
On Thu, Nov 05, 2009 at 07:17:42AM -0500, William Allen Simpson wrote:
> Paul E. McKenney wrote:
>> On Tue, Nov 03, 2009 at 05:38:10PM -0500, William Allen Simpson wrote:
>>> Documentation/RCU/checklist.txt #7 says:
>>>
>>> One exception to this rule: rcu_read_lock() and rcu_read_unlock()
>>> may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
>>> in cases where local bottom halves are already known to be
>>> disabled, for example, in irq or softirq context. Commenting
>>> such cases is a must, of course! And the jury is still out on
>>> whether the increased speed is worth it.
>> I strongly suggest using the matching primitives unless you have a
>> really strong reason not to.
> Eric gave contrary advice. But he also suggested (in an earlier message)
> clearing the secrets with a timer, which could be a separate context --
> although much later in time.
>
> As you suggest, I'll use the _bh suffix everywhere until every i is dotted
> and t is crossed. Then, check for efficiency later after thorough
> analysis by experts such as yourself.
>
> This code will be hit on every SYN and SYNACK that has a cookie option.
> But it's just prior to a CPU intensive sha_transform -- in comparison,
> it's trivial.
Had Eric said that this code were performance-critical, where every
nanosecond mattered, that would certainly be good enough for me.
Eric has excellent knowledge of the networking code, certainly much
better than mine. And 10Gb Ethernet is certainly a performance
challenge, and I don't expect 40Gb Ethernet to be any easier.
Of course, I would still argue that the use of rcu_read_lock() rather
than rcu_read_unlock() needs to be commented. And if this sort of
substitution happens a lot, maybe we need a way for it to happen
automatically.
Thanx, Paul
>>> + rcu_assign_pointer(tcp_secret_generating,
>>> + tcp_secret_secondary);
>>> + rcu_assign_pointer(tcp_secret_retiring,
>>> + tcp_secret_primary);
>>> + spin_unlock_bh(&tcp_secret_locker);
>>> + /* call_rcu() or synchronize_rcu() not needed. */
>> Would you be willing to say why? Are you relying on a time delay for a
>> given item to pass through tcp_secret_secondary and tcp_secret_retiring
>> or some such? If so, how do you know that this time delay will always
>> be long enough?
>> Or are you just shuffling the data structures around, without ever
>> freeing them? If so, is it really OK for a given reader to keep a
>> reference to a given item through the full range of shuffling, especially
>> given that it might be accesssing this concurrently with the ->expires
>> assignments above?
>> Either way, could you please expand the comment to give at least some
>> hint to the poor guy reading your code? ;-)
> Yes. Just shuffling the pointers without ever freeing anything. So,
> there's nothing for call_rcu() to do, and nothing else to synchronize
> (only the pointers). This assumes that after _unlock_ any CPU cache
> with an old pointer->expires will hit the _lock_ code, and that will
> update *both* ->expires and the other array elements concurrently?
>
> One of the advantages of this scheme is the new secret is initialized
> while the old secret is still used, and the old secret can continue to
> be verified as old packets arrive. (I originally designed this for
> Photuris [RFC-2522] circa 1995.)
>
> As described in the long header given, each array element goes through
> four (4) states. This is handling the first state transition. It will
> hit at least 2 more locks, pointer updates, and unlocks before reuse.
>
> Also, a great deal of time passes. After being retired (and expired), it
> will be unused for approximately 5 minutes.
>
> All that's a bit long for a comment.
>
> + /*
> + * The retiring data is never freed. Instead, it is
> + * replaced after later pointer updates and a quiet
> + * time of approximately 5 minutes. There is nothing
> + * for call_rcu() or synchronize_rcu() to handle.
> + */
>
> Clear enough?
^ permalink raw reply
* Re: [PATCH] e1000: the power down when running ifdown command
From: Naohiro Ooiwa @ 2009-11-05 14:58 UTC (permalink / raw)
To: Stephen Hemminger
Cc: jeffrey.t.kirsher, jesse.brandeburg, peter.p.waskiewicz.jr,
john.ronciak, davem, Andrew Morton, netdev, svaidy, e1000-devel
In-Reply-To: <20091104080846.5bf4d225@nehalam>
Stephen Hemminger wrote:
> On Wed, 04 Nov 2009 19:23:43 +0900
> Naohiro Ooiwa <nooiwa@miraclelinux.com> wrote:
>
>> Naohiro Ooiwa wrote:
>>> Stephen Hemminger wrote:
>>>> On Sat, 31 Oct 2009 18:39:52 +0900
>>>> Naohiro Ooiwa <nooiwa@miraclelinux.com> wrote:
>>>>
>>>> Does this work with Wake On Lan?
>>> Yes, it works WOL.
>> Sorry, I made a mistake.
>> The WOL doesn't work when my patch applied to kernel.
>> I wasn't myself.
>>
>> I consider the WOL and I will resent the patch.
>> Thank you for your point.
>>
>>
>> thanks,
>> Naohiro Ooiwa
>
>
> Good, thank you for checking. I like the idea of powering down the
> PHY. Some of the drivers have shutdown hooks to power PHY back on
> during shutdown to enable WOL.
>
Thank you so much for your infomation.
Oh, The shutdown hooks is useful.
Thanks.
Naohiro Ooiwa
^ permalink raw reply
* Re: [RFC] [PATCH] udp: optimize lookup of UDP sockets to by including destination address in the hash key
From: Andi Kleen @ 2009-11-05 14:54 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Andi Kleen, Octavian Purdila, Lucian Adrian Grijincu, netdev
In-Reply-To: <4AF2CCD9.7010507@gmail.com>
> I assume cache is cold or even on other cpu (worst case), dealing with
> 100.000+ sockets or so...
Other CPU cache hit is actually typically significantly
faster than a DRAM access (unless you're talking about a very large NUMA
system and a remote CPU far away)
>
> If workload fits in one CPU cache/registers, we dont mind taking one
> or two cache lines per object, obviously.
It's more like part of your workload needs to fit.
For example if you use a tree and the higher levels fit into
the cache, having a few levels in the tree is (approximately) free.
That's why I'm not always fond of large hash tables. They pretty
much guarantee a lot of cache misses under high load, because
they have little locality.
-Andi
--
ak@linux.intel.com -- Speaking for myself only.
^ permalink raw reply
* Re: [PATCH] netfilter: nf_nat_helper: tidy up adjust_tcp_sequence
From: Patrick McHardy @ 2009-11-05 14:53 UTC (permalink / raw)
To: Hannes Eder; +Cc: netdev, netfilter-devel
In-Reply-To: <20090922155911.20008.96214.stgit@jazzy.zrh.corp.google.com>
Hannes Eder wrote:
> The variable 'other_way' gets initialized but is not read afterwards,
> so remove it. Pass the right arguments to a pr_debug call.
>
> While being at tidy up a bit and it fix this checkpatch warning:
> WARNING: suspect code indent for conditional statements
>
> Signed-off-by: Hannes Eder <heder@google.com>
>
Applied with some minor changes (use enum ip_conntrack_dir instead
of int, use function name literally instead of "%s()" with __func__).
^ permalink raw reply
* Re: [PATCH RFC] gianfar: Make polling safe with IRQs disabled
From: Jon Loeliger @ 2009-11-05 14:41 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev, Jason Wessel, Andy Fleming, David Miller, netdev
In-Reply-To: <20091105142028.GB17171@oksana.dev.rtsoft.ru>
>
> Hm, then I'd better remove the #ifdef CONFIG_NETPOLL.
>
> Interestingly though, why conn_track does the polling with irqs
> disabled, could be a bug in the conn_track? Because pretty much
> drivers assume that polling is called with IRQs enabled.
>
> If it's easily reproducible, could you replace the printk() with
> WARN_ON(1) and post the backtrace? Or I can try to reproduce the
> issue if you tell me how.
>
> Thanks!
Yeah, I can reproduce it. I'll try and get that for you.
jdl
^ permalink raw reply
* Re: [PATCH RFC] gianfar: Make polling safe with IRQs disabled
From: Jon Loeliger @ 2009-11-05 14:01 UTC (permalink / raw)
To: Anton Vorontsov
Cc: David Miller, linuxppc-dev, netdev, Andy Fleming, Jason Wessel
In-Reply-To: <20091104225711.GA30844@oksana.dev.rtsoft.ru>
> When using KGDBoE, gianfar driver spits 'Interrupt problem' messages,
> which appears to be a legitimate warning, i.e. we may end up calling
> netif_receive_skb() or vlan_hwaccel_receive_skb() with IRQs disabled.
>
> This patch reworks the RX path so that if netpoll is enabled (the
> only case when the driver don't know from what context the polling
> may be called), we check whether IRQs are disabled, and if so we
> fall back to safe variants of skb receiving functions.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
>
> I'm not sure if this is suitable for mainline since it doesn't
> have KGDBoE support. Jason, if the patch is OK, would you like
> to merge it into KGDB tree?
It's a legitimate problem with or without KGDBoE. I see it
occasionally when conn_track is enabled as well, for example.
jdl
^ permalink raw reply
* [PATCH 3/5] net/irda: push BKL into proto_ops
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
To: linux-kernel
Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
Arnd Bergmann, Samuel Ortiz, netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>
The irda driver uses the BKL implicitly in its protocol
operations. Replace the wrapped proto_ops with explicit
lock_kernel() calls makes the usage more obvious and
shrinks the size of the object code.
The calls t lock_kernel() should eventually all be replaced
by other serialization methods, which requires finding out
The calls t lock_kernel() should eventually all be replaced
by other serialization methods, which requires finding out
which data actually needs protection.
Cc: Samuel Ortiz <samuel@sortiz.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
net/irda/af_irda.c | 331 +++++++++++++++++++++++++++++++++++-----------------
1 files changed, 224 insertions(+), 107 deletions(-)
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index dd35641..7f84866 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -714,11 +714,14 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_irda saddr;
struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk);
+ int err;
+ lock_kernel();
memset(&saddr, 0, sizeof(saddr));
if (peer) {
+ err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ goto out;
saddr.sir_family = AF_IRDA;
saddr.sir_lsap_sel = self->dtsap_sel;
@@ -735,8 +738,10 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
/* uaddr_len come to us uninitialised */
*uaddr_len = sizeof (struct sockaddr_irda);
memcpy(uaddr, &saddr, *uaddr_len);
-
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -748,21 +753,25 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
static int irda_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
+ int err = -EOPNOTSUPP;
IRDA_DEBUG(2, "%s()\n", __func__);
+ lock_kernel();
if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
(sk->sk_type != SOCK_DGRAM))
- return -EOPNOTSUPP;
+ goto out;
if (sk->sk_state != TCP_LISTEN) {
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
- return 0;
+ err = 0;
}
+out:
+ unlock_kernel();
- return -EOPNOTSUPP;
+ return err;
}
/*
@@ -783,36 +792,40 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (addr_len != sizeof(struct sockaddr_irda))
return -EINVAL;
+ lock_kernel();
#ifdef CONFIG_IRDA_ULTRA
/* Special care for Ultra sockets */
if ((sk->sk_type == SOCK_DGRAM) &&
(sk->sk_protocol == IRDAPROTO_ULTRA)) {
self->pid = addr->sir_lsap_sel;
+ err = -EOPNOTSUPP;
if (self->pid & 0x80) {
IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
- return -EOPNOTSUPP;
+ goto out;
}
err = irda_open_lsap(self, self->pid);
if (err < 0)
- return err;
+ goto out;
/* Pretend we are connected */
sock->state = SS_CONNECTED;
sk->sk_state = TCP_ESTABLISHED;
+ err = 0;
- return 0;
+ goto out;
}
#endif /* CONFIG_IRDA_ULTRA */
self->ias_obj = irias_new_object(addr->sir_name, jiffies);
+ err = -ENOMEM;
if (self->ias_obj == NULL)
- return -ENOMEM;
+ goto out;
err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
if (err < 0) {
kfree(self->ias_obj->name);
kfree(self->ias_obj);
- return err;
+ goto out;
}
/* Register with LM-IAS */
@@ -820,7 +833,10 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
self->stsap_sel, IAS_KERNEL_ATTR);
irias_insert_object(self->ias_obj);
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -839,22 +855,26 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
IRDA_DEBUG(2, "%s()\n", __func__);
+ lock_kernel();
err = irda_create(sock_net(sk), newsock, sk->sk_protocol);
if (err)
- return err;
+ goto out;;
+ err = -EINVAL;
if (sock->state != SS_UNCONNECTED)
- return -EINVAL;
+ goto out;
if ((sk = sock->sk) == NULL)
- return -EINVAL;
+ goto out;
+ err = -EOPNOTSUPP;
if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
(sk->sk_type != SOCK_DGRAM))
- return -EOPNOTSUPP;
+ goto out;
+ err = -EINVAL;
if (sk->sk_state != TCP_LISTEN)
- return -EINVAL;
+ goto out;
/*
* The read queue this time is holding sockets ready to use
@@ -875,18 +895,20 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
break;
/* Non blocking operation */
+ err = -EWOULDBLOCK;
if (flags & O_NONBLOCK)
- return -EWOULDBLOCK;
+ goto out;
err = wait_event_interruptible(*(sk->sk_sleep),
skb_peek(&sk->sk_receive_queue));
if (err)
- return err;
+ goto out;
}
newsk = newsock->sk;
+ err = -EIO;
if (newsk == NULL)
- return -EIO;
+ goto out;
newsk->sk_state = TCP_ESTABLISHED;
@@ -894,10 +916,11 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
/* Now attach up the new socket */
new->tsap = irttp_dup(self->tsap, new);
+ err = -EPERM; /* value does not seem to make sense. -arnd */
if (!new->tsap) {
IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
kfree_skb(skb);
- return -1;
+ goto out;
}
new->stsap_sel = new->tsap->stsap_sel;
@@ -921,8 +944,10 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
newsock->state = SS_CONNECTED;
irda_connect_response(new);
-
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -955,28 +980,34 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
IRDA_DEBUG(2, "%s(%p)\n", __func__, self);
+ lock_kernel();
/* Don't allow connect for Ultra sockets */
+ err = -ESOCKTNOSUPPORT;
if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA))
- return -ESOCKTNOSUPPORT;
+ goto out;
if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED;
- return 0; /* Connect completed during a ERESTARTSYS event */
+ err = 0;
+ goto out; /* Connect completed during a ERESTARTSYS event */
}
if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
sock->state = SS_UNCONNECTED;
- return -ECONNREFUSED;
+ err = -ECONNREFUSED;
+ goto out;
}
+ err = -EISCONN; /* No reconnect on a seqpacket socket */
if (sk->sk_state == TCP_ESTABLISHED)
- return -EISCONN; /* No reconnect on a seqpacket socket */
+ goto out;
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
+ err = -EINVAL;
if (addr_len != sizeof(struct sockaddr_irda))
- return -EINVAL;
+ goto out;
/* Check if user supplied any destination device address */
if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) {
@@ -984,7 +1015,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
if (err) {
IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__);
- return err;
+ goto out;
}
} else {
/* Use the one provided by the user */
@@ -1000,7 +1031,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
err = irda_find_lsap_sel(self, addr->sir_name);
if (err) {
IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
- return err;
+ goto out;
}
} else {
/* Directly connect to the remote LSAP
@@ -1025,29 +1056,35 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
self->max_sdu_size_rx, NULL);
if (err) {
IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
- return err;
+ goto out;
}
/* Now the loop */
+ err = -EINPROGRESS;
if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
- return -EINPROGRESS;
+ goto out;
+ err = -ERESTARTSYS;
if (wait_event_interruptible(*(sk->sk_sleep),
(sk->sk_state != TCP_SYN_SENT)))
- return -ERESTARTSYS;
+ goto out;
if (sk->sk_state != TCP_ESTABLISHED) {
sock->state = SS_UNCONNECTED;
err = sock_error(sk);
- return err? err : -ECONNRESET;
+ if (!err)
+ err = -ECONNRESET;
+ goto out;
}
sock->state = SS_CONNECTED;
/* At this point, IrLMP has assigned our source address */
self->saddr = irttp_get_saddr(self->tsap);
-
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
static struct proto irda_proto = {
@@ -1192,6 +1229,7 @@ static int irda_release(struct socket *sock)
if (sk == NULL)
return 0;
+ lock_kernel();
lock_sock(sk);
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
@@ -1210,6 +1248,7 @@ static int irda_release(struct socket *sock)
/* Destroy networking socket if we are the last reference on it,
* i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */
sock_put(sk);
+ unlock_kernel();
/* Notes on socket locking and deallocation... - Jean II
* In theory we should put pairs of sock_hold() / sock_put() to
@@ -1257,28 +1296,37 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+ lock_kernel();
/* Note : socket.c set MSG_EOR on SEQPACKET sockets */
if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
- MSG_NOSIGNAL))
- return -EINVAL;
+ MSG_NOSIGNAL)) {
+ err = -EINVAL;
+ goto out;
+ }
if (sk->sk_shutdown & SEND_SHUTDOWN)
goto out_err;
- if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ err = -ENOTCONN;
+ goto out;
+ }
self = irda_sk(sk);
/* Check if IrTTP is wants us to slow down */
if (wait_event_interruptible(*(sk->sk_sleep),
- (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED)))
- return -ERESTARTSYS;
+ (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) {
+ err = -ERESTARTSYS;
+ goto out;
+ }
/* Check if we are still connected */
- if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ err = -ENOTCONN;
+ goto out;
+ }
/* Check that we don't send out too big frames */
if (len > self->max_data_size) {
@@ -1310,11 +1358,16 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
goto out_err;
}
+
+ unlock_kernel();
/* Tell client how much data we actually sent */
return len;
- out_err:
- return sk_stream_error(sk, msg->msg_flags, err);
+out_err:
+ err = sk_stream_error(sk, msg->msg_flags, err);
+out:
+ unlock_kernel();
+ return err;
}
@@ -1335,13 +1388,14 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(4, "%s()\n", __func__);
+ lock_kernel();
if ((err = sock_error(sk)) < 0)
- return err;
+ goto out;
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err);
if (!skb)
- return err;
+ goto out;
skb_reset_transport_header(skb);
copied = skb->len;
@@ -1369,8 +1423,12 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
irttp_flow_request(self->tsap, FLOW_START);
}
}
-
+ unlock_kernel();
return copied;
+
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -1388,15 +1446,19 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(3, "%s()\n", __func__);
+ lock_kernel();
if ((err = sock_error(sk)) < 0)
- return err;
+ goto out;
+ err = -EINVAL;
if (sock->flags & __SO_ACCEPTCON)
- return(-EINVAL);
+ goto out;
+ err =-EOPNOTSUPP;
if (flags & MSG_OOB)
- return -EOPNOTSUPP;
+ goto out;
+ err = 0;
target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
timeo = sock_rcvtimeo(sk, noblock);
@@ -1408,7 +1470,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
if (skb == NULL) {
DEFINE_WAIT(wait);
- int ret = 0;
+ err = 0;
if (copied >= target)
break;
@@ -1418,25 +1480,25 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
/*
* POSIX 1003.1g mandates this order.
*/
- ret = sock_error(sk);
- if (ret)
+ err = sock_error(sk);
+ if (err)
;
else if (sk->sk_shutdown & RCV_SHUTDOWN)
;
else if (noblock)
- ret = -EAGAIN;
+ err = -EAGAIN;
else if (signal_pending(current))
- ret = sock_intr_errno(timeo);
+ err = sock_intr_errno(timeo);
else if (sk->sk_state != TCP_ESTABLISHED)
- ret = -ENOTCONN;
+ err = -ENOTCONN;
else if (skb_peek(&sk->sk_receive_queue) == NULL)
/* Wait process until data arrives */
schedule();
finish_wait(sk->sk_sleep, &wait);
- if (ret)
- return ret;
+ if (err)
+ goto out;
if (sk->sk_shutdown & RCV_SHUTDOWN)
break;
@@ -1489,7 +1551,9 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
}
}
- return copied;
+out:
+ unlock_kernel();
+ return err ? : copied;
}
/*
@@ -1507,18 +1571,23 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
struct sk_buff *skb;
int err;
+ lock_kernel();
+
IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+ err = -EINVAL;
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
- return -EINVAL;
+ goto out;
if (sk->sk_shutdown & SEND_SHUTDOWN) {
send_sig(SIGPIPE, current, 0);
- return -EPIPE;
+ err = -EPIPE;
+ goto out;
}
+ err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ goto out;
self = irda_sk(sk);
@@ -1535,8 +1604,9 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
skb = sock_alloc_send_skb(sk, len + self->max_header_size,
msg->msg_flags & MSG_DONTWAIT, &err);
+ err = -ENOBUFS;
if (!skb)
- return -ENOBUFS;
+ goto out;
skb_reserve(skb, self->max_header_size);
skb_reset_transport_header(skb);
@@ -1546,7 +1616,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
if (err) {
kfree_skb(skb);
- return err;
+ goto out;
}
/*
@@ -1556,9 +1626,13 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
err = irttp_udata_request(self->tsap, skb);
if (err) {
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
- return err;
+ goto out;
}
+ unlock_kernel();
return len;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -1580,12 +1654,15 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);
+ lock_kernel();
+ err = -EINVAL;
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
- return -EINVAL;
+ goto out;
+ err = -EPIPE;
if (sk->sk_shutdown & SEND_SHUTDOWN) {
send_sig(SIGPIPE, current, 0);
- return -EPIPE;
+ goto out;
}
self = irda_sk(sk);
@@ -1593,16 +1670,18 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
/* Check if an address was specified with sendto. Jean II */
if (msg->msg_name) {
struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name;
+ err = -EINVAL;
/* Check address, extract pid. Jean II */
if (msg->msg_namelen < sizeof(*addr))
- return -EINVAL;
+ goto out;
if (addr->sir_family != AF_IRDA)
- return -EINVAL;
+ goto out;
pid = addr->sir_lsap_sel;
if (pid & 0x80) {
IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
- return -EOPNOTSUPP;
+ err = -EOPNOTSUPP;
+ goto out;
}
} else {
/* Check that the socket is properly bound to an Ultra
@@ -1611,7 +1690,8 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
(sk->sk_state != TCP_ESTABLISHED)) {
IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n",
__func__);
- return -ENOTCONN;
+ err = -ENOTCONN;
+ goto out;
}
/* Use PID from socket */
bound = 1;
@@ -1630,8 +1710,9 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
skb = sock_alloc_send_skb(sk, len + self->max_header_size,
msg->msg_flags & MSG_DONTWAIT, &err);
+ err = -ENOBUFS;
if (!skb)
- return -ENOBUFS;
+ goto out;
skb_reserve(skb, self->max_header_size);
skb_reset_transport_header(skb);
@@ -1641,16 +1722,16 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
if (err) {
kfree_skb(skb);
- return err;
+ goto out;
}
err = irlmp_connless_data_request((bound ? self->lsap : NULL),
skb, pid);
- if (err) {
+ if (err)
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
- return err;
- }
- return len;
+out:
+ unlock_kernel();
+ return err ? : len;
}
#endif /* CONFIG_IRDA_ULTRA */
@@ -1664,6 +1745,8 @@ static int irda_shutdown(struct socket *sock, int how)
IRDA_DEBUG(1, "%s(%p)\n", __func__, self);
+ lock_kernel();
+
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
sk->sk_state_change(sk);
@@ -1684,6 +1767,8 @@ static int irda_shutdown(struct socket *sock, int how)
self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */
self->saddr = 0x0; /* so IrLMP assign us any link */
+ unlock_kernel();
+
return 0;
}
@@ -1699,6 +1784,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
IRDA_DEBUG(4, "%s()\n", __func__);
+ lock_kernel();
poll_wait(file, sk->sk_sleep, wait);
mask = 0;
@@ -1746,18 +1832,34 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
default:
break;
}
+ unlock_kernel();
return mask;
}
+static unsigned int irda_datagram_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+{
+ int err;
+
+ lock_kernel();
+ err = datagram_poll(file, sock, wait);
+ unlock_kernel();
+
+ return err;
+}
+
/*
* Function irda_ioctl (sock, cmd, arg)
*/
static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
+ int err;
IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd);
+ lock_kernel();
+ err = -EINVAL;
switch (cmd) {
case TIOCOUTQ: {
long amount;
@@ -1765,9 +1867,8 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
if (amount < 0)
amount = 0;
- if (put_user(amount, (unsigned int __user *)arg))
- return -EFAULT;
- return 0;
+ err = put_user(amount, (unsigned int __user *)arg);
+ break;
}
case TIOCINQ: {
@@ -1776,15 +1877,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
amount = skb->len;
- if (put_user(amount, (unsigned int __user *)arg))
- return -EFAULT;
- return 0;
+ err = put_user(amount, (unsigned int __user *)arg);
+ break;
}
case SIOCGSTAMP:
if (sk != NULL)
- return sock_get_timestamp(sk, (struct timeval __user *)arg);
- return -EINVAL;
+ err = sock_get_timestamp(sk, (struct timeval __user *)arg);
+ break;
case SIOCGIFADDR:
case SIOCSIFADDR:
@@ -1796,14 +1896,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFNETMASK:
case SIOCGIFMETRIC:
case SIOCSIFMETRIC:
- return -EINVAL;
+ break;
default:
IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__);
- return -ENOIOCTLCMD;
+ err = -ENOIOCTLCMD;
}
+ unlock_kernel();
- /*NOTREACHED*/
- return 0;
+ return err;
}
#ifdef CONFIG_COMPAT
@@ -1825,7 +1925,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
* Set some options for the socket
*
*/
-static int irda_setsockopt(struct socket *sock, int level, int optname,
+static int __irda_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
@@ -2083,6 +2183,18 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
return 0;
}
+static int irda_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, unsigned int optlen)
+{
+ int err;
+
+ lock_kernel();
+ err = __irda_setsockopt(sock, level, optname, optval, optlen);
+ unlock_kernel();
+
+ return err;
+}
+
/*
* Function irda_extract_ias_value(ias_opt, ias_value)
*
@@ -2135,7 +2247,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt,
/*
* Function irda_getsockopt (sock, level, optname, optval, optlen)
*/
-static int irda_getsockopt(struct socket *sock, int level, int optname,
+static int __irda_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
@@ -2463,13 +2575,25 @@ bed:
return 0;
}
+static int irda_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ int err;
+
+ lock_kernel();
+ err = __irda_getsockopt(sock, level, optname, optval, optlen);
+ unlock_kernel();
+
+ return err;
+}
+
static struct net_proto_family irda_family_ops = {
.family = PF_IRDA,
.create = irda_create,
.owner = THIS_MODULE,
};
-static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
+static const struct proto_ops irda_stream_ops = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2493,7 +2617,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.sendpage = sock_no_sendpage,
};
-static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
+static const struct proto_ops irda_seqpacket_ops = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2502,7 +2626,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.socketpair = sock_no_socketpair,
.accept = irda_accept,
.getname = irda_getname,
- .poll = datagram_poll,
+ .poll = irda_datagram_poll,
.ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
@@ -2517,7 +2641,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.sendpage = sock_no_sendpage,
};
-static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
+static const struct proto_ops irda_dgram_ops = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2526,7 +2650,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.socketpair = sock_no_socketpair,
.accept = irda_accept,
.getname = irda_getname,
- .poll = datagram_poll,
+ .poll = irda_datagram_poll,
.ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
@@ -2542,7 +2666,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
};
#ifdef CONFIG_IRDA_ULTRA
-static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
+static const struct proto_ops irda_ultra_ops = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2551,7 +2675,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = irda_getname,
- .poll = datagram_poll,
+ .poll = irda_datagram_poll,
.ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
@@ -2567,13 +2691,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
};
#endif /* CONFIG_IRDA_ULTRA */
-SOCKOPS_WRAP(irda_stream, PF_IRDA);
-SOCKOPS_WRAP(irda_seqpacket, PF_IRDA);
-SOCKOPS_WRAP(irda_dgram, PF_IRDA);
-#ifdef CONFIG_IRDA_ULTRA
-SOCKOPS_WRAP(irda_ultra, PF_IRDA);
-#endif /* CONFIG_IRDA_ULTRA */
-
/*
* Function irsock_init (pro)
*
--
1.6.3.3
^ permalink raw reply related
* [PATCH 5/5] net: kill proto_ops wrapper
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
To: linux-kernel
Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
Arnd Bergmann, netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>
All users of wrapped proto_ops are now gone, so we can safely remove
the wrappers as well.
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
include/linux/net.h | 83 ---------------------------------------------------
1 files changed, 0 insertions(+), 83 deletions(-)
diff --git a/include/linux/net.h b/include/linux/net.h
index 529a093..041a8e4 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -263,89 +263,6 @@ extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
extern int kernel_sock_shutdown(struct socket *sock,
enum sock_shutdown_cmd how);
-#ifndef CONFIG_SMP
-#define SOCKOPS_WRAPPED(name) name
-#define SOCKOPS_WRAP(name, fam)
-#else
-
-#define SOCKOPS_WRAPPED(name) __unlocked_##name
-
-#define SOCKCALL_WRAP(name, call, parms, args) \
-static int __lock_##name##_##call parms \
-{ \
- int ret; \
- lock_kernel(); \
- ret = __unlocked_##name##_ops.call args ;\
- unlock_kernel(); \
- return ret; \
-}
-
-#define SOCKCALL_UWRAP(name, call, parms, args) \
-static unsigned int __lock_##name##_##call parms \
-{ \
- int ret; \
- lock_kernel(); \
- ret = __unlocked_##name##_ops.call args ;\
- unlock_kernel(); \
- return ret; \
-}
-
-
-#define SOCKOPS_WRAP(name, fam) \
-SOCKCALL_WRAP(name, release, (struct socket *sock), (sock)) \
-SOCKCALL_WRAP(name, bind, (struct socket *sock, struct sockaddr *uaddr, int addr_len), \
- (sock, uaddr, addr_len)) \
-SOCKCALL_WRAP(name, connect, (struct socket *sock, struct sockaddr * uaddr, \
- int addr_len, int flags), \
- (sock, uaddr, addr_len, flags)) \
-SOCKCALL_WRAP(name, socketpair, (struct socket *sock1, struct socket *sock2), \
- (sock1, sock2)) \
-SOCKCALL_WRAP(name, accept, (struct socket *sock, struct socket *newsock, \
- int flags), (sock, newsock, flags)) \
-SOCKCALL_WRAP(name, getname, (struct socket *sock, struct sockaddr *uaddr, \
- int *addr_len, int peer), (sock, uaddr, addr_len, peer)) \
-SOCKCALL_UWRAP(name, poll, (struct file *file, struct socket *sock, struct poll_table_struct *wait), \
- (file, sock, wait)) \
-SOCKCALL_WRAP(name, ioctl, (struct socket *sock, unsigned int cmd, \
- unsigned long arg), (sock, cmd, arg)) \
-SOCKCALL_WRAP(name, compat_ioctl, (struct socket *sock, unsigned int cmd, \
- unsigned long arg), (sock, cmd, arg)) \
-SOCKCALL_WRAP(name, listen, (struct socket *sock, int len), (sock, len)) \
-SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \
-SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \
- char __user *optval, unsigned int optlen), (sock, level, optname, optval, optlen)) \
-SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \
- char __user *optval, int __user *optlen), (sock, level, optname, optval, optlen)) \
-SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len), \
- (iocb, sock, m, len)) \
-SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len, int flags), \
- (iocb, sock, m, len, flags)) \
-SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \
- (file, sock, vma)) \
- \
-static const struct proto_ops name##_ops = { \
- .family = fam, \
- .owner = THIS_MODULE, \
- .release = __lock_##name##_release, \
- .bind = __lock_##name##_bind, \
- .connect = __lock_##name##_connect, \
- .socketpair = __lock_##name##_socketpair, \
- .accept = __lock_##name##_accept, \
- .getname = __lock_##name##_getname, \
- .poll = __lock_##name##_poll, \
- .ioctl = __lock_##name##_ioctl, \
- .compat_ioctl = __lock_##name##_compat_ioctl, \
- .listen = __lock_##name##_listen, \
- .shutdown = __lock_##name##_shutdown, \
- .setsockopt = __lock_##name##_setsockopt, \
- .getsockopt = __lock_##name##_getsockopt, \
- .sendmsg = __lock_##name##_sendmsg, \
- .recvmsg = __lock_##name##_recvmsg, \
- .mmap = __lock_##name##_mmap, \
-};
-
-#endif
-
#define MODULE_ALIAS_NETPROTO(proto) \
MODULE_ALIAS("net-pf-" __stringify(proto))
--
1.6.3.3
^ permalink raw reply related
* [PATCH 4/5] net/x25: push BKL usage into x25_proto
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
To: linux-kernel
Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
Arnd Bergmann, Henner Eisen, linux-x25, netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>
The x25 driver uses lock_kernel() implicitly through
its proto_ops wrapper. The makes the usage explicit
in order to get rid of that wrapper and to better document
the usage of the BKL.
The next step should be to get rid of the usage of the BKL
in x25 entirely, which requires understanding what data
structures need serialized accesses.
Cc: Henner Eisen <eis@baty.hanse.de>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-x25@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
net/x25/af_x25.c | 71 +++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 7fa9c7a..a7a4bc2 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -415,6 +415,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
int rc = -ENOPROTOOPT;
+ lock_kernel();
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;
@@ -429,6 +430,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
x25_sk(sk)->qbitincl = !!opt;
rc = 0;
out:
+ unlock_kernel();
return rc;
}
@@ -438,6 +440,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
int val, len, rc = -ENOPROTOOPT;
+ lock_kernel();
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;
@@ -458,6 +461,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
val = x25_sk(sk)->qbitincl;
rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
out:
+ unlock_kernel();
return rc;
}
@@ -466,12 +470,14 @@ static int x25_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
int rc = -EOPNOTSUPP;
+ lock_kernel();
if (sk->sk_state != TCP_LISTEN) {
memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
rc = 0;
}
+ unlock_kernel();
return rc;
}
@@ -597,6 +603,7 @@ static int x25_release(struct socket *sock)
struct sock *sk = sock->sk;
struct x25_sock *x25;
+ lock_kernel();
if (!sk)
goto out;
@@ -627,6 +634,7 @@ static int x25_release(struct socket *sock)
sock_orphan(sk);
out:
+ unlock_kernel();
return 0;
}
@@ -634,18 +642,23 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
+ int rc = 0;
+ lock_kernel();
if (!sock_flag(sk, SOCK_ZAPPED) ||
addr_len != sizeof(struct sockaddr_x25) ||
- addr->sx25_family != AF_X25)
- return -EINVAL;
+ addr->sx25_family != AF_X25) {
+ rc = -EINVAL;
+ goto out;
+ }
x25_sk(sk)->source_addr = addr->sx25_addr;
x25_insert_socket(sk);
sock_reset_flag(sk, SOCK_ZAPPED);
SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
-
- return 0;
+out:
+ unlock_kernel();
+ return rc;
}
static int x25_wait_for_connection_establishment(struct sock *sk)
@@ -686,6 +699,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
struct x25_route *rt;
int rc = 0;
+ lock_kernel();
lock_sock(sk);
if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED;
@@ -763,6 +777,7 @@ out_put_route:
x25_route_put(rt);
out:
release_sock(sk);
+ unlock_kernel();
return rc;
}
@@ -802,6 +817,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
struct sk_buff *skb;
int rc = -EINVAL;
+ lock_kernel();
if (!sk || sk->sk_state != TCP_LISTEN)
goto out;
@@ -829,6 +845,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
out2:
release_sock(sk);
out:
+ unlock_kernel();
return rc;
}
@@ -838,10 +855,14 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
struct sock *sk = sock->sk;
struct x25_sock *x25 = x25_sk(sk);
+ int rc = 0;
+ lock_kernel();
if (peer) {
- if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ rc = -ENOTCONN;
+ goto out;
+ }
sx25->sx25_addr = x25->dest_addr;
} else
sx25->sx25_addr = x25->source_addr;
@@ -849,7 +870,21 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
sx25->sx25_family = AF_X25;
*uaddr_len = sizeof(*sx25);
- return 0;
+out:
+ unlock_kernel();
+ return rc;
+}
+
+static unsigned int x25_datagram_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+{
+ int rc;
+
+ lock_kernel();
+ rc = datagram_poll(file, sock, wait);
+ unlock_kernel();
+
+ return rc;
}
int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
@@ -1002,6 +1037,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
size_t size;
int qbit = 0, rc = -EINVAL;
+ lock_kernel();
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
goto out;
@@ -1166,6 +1202,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
release_sock(sk);
rc = len;
out:
+ unlock_kernel();
return rc;
out_kfree_skb:
kfree_skb(skb);
@@ -1186,6 +1223,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
unsigned char *asmptr;
int rc = -ENOTCONN;
+ lock_kernel();
/*
* This works for seqpacket too. The receiver has ordered the queue for
* us! We do one quick check first though
@@ -1259,6 +1297,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free_dgram:
skb_free_datagram(sk, skb);
out:
+ unlock_kernel();
return rc;
}
@@ -1270,6 +1309,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int rc;
+ lock_kernel();
switch (cmd) {
case TIOCOUTQ: {
int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
@@ -1472,6 +1512,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
+ unlock_kernel();
return rc;
}
@@ -1542,15 +1583,19 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
break;
case SIOCGSTAMP:
rc = -EINVAL;
+ lock_kernel();
if (sk)
rc = compat_sock_get_timestamp(sk,
(struct timeval __user*)argp);
+ unlock_kernel();
break;
case SIOCGSTAMPNS:
rc = -EINVAL;
+ lock_kernel();
if (sk)
rc = compat_sock_get_timestampns(sk,
(struct timespec __user*)argp);
+ unlock_kernel();
break;
case SIOCGIFADDR:
case SIOCSIFADDR:
@@ -1569,16 +1614,22 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
+ lock_kernel();
rc = x25_route_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25GSUBSCRIP:
+ lock_kernel();
rc = compat_x25_subscr_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25SSUBSCRIP:
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
+ lock_kernel();
rc = compat_x25_subscr_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25GFACILITIES:
case SIOCX25SFACILITIES:
@@ -1600,7 +1651,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
}
#endif
-static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
+static const struct proto_ops x25_proto_ops = {
.family = AF_X25,
.owner = THIS_MODULE,
.release = x25_release,
@@ -1609,7 +1660,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.socketpair = sock_no_socketpair,
.accept = x25_accept,
.getname = x25_getname,
- .poll = datagram_poll,
+ .poll = x25_datagram_poll,
.ioctl = x25_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_x25_ioctl,
@@ -1624,8 +1675,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.sendpage = sock_no_sendpage,
};
-SOCKOPS_WRAP(x25_proto, AF_X25);
-
static struct packet_type x25_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_X25),
.func = x25_lapb_receive_frame,
--
1.6.3.3
^ permalink raw reply related
* [PATCH 2/5] net/ipx: push down BKL into a ipx_dgram_ops
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
To: linux-kernel
Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
Arnd Bergmann, Arnaldo Carvalho de Melo, Stephen Hemminger,
netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>
Making the BKL usage explicit in ipx makes it more
obvious where it is used, reduces code size and helps
getting rid of the BKL in common code.
I did not analyse how to kill lock_kernel from ipx
entirely, this will involve either proving that it's not
needed, or replacing with a proper mutex or spinlock,
after finding out which data structures are protected
by the lock.
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: David S. Miller <davem@davemloft.net>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
net/ipx/af_ipx.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 46 insertions(+), 8 deletions(-)
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 66c7a20..f542c5b 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1298,6 +1298,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname,
int opt;
int rc = -EINVAL;
+ lock_kernel();
if (optlen != sizeof(int))
goto out;
@@ -1312,6 +1313,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname,
ipx_sk(sk)->type = opt;
rc = 0;
out:
+ unlock_kernel();
return rc;
}
@@ -1323,6 +1325,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
int len;
int rc = -ENOPROTOOPT;
+ lock_kernel();
if (!(level == SOL_IPX && optname == IPX_TYPE))
goto out;
@@ -1343,6 +1346,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
rc = 0;
out:
+ unlock_kernel();
return rc;
}
@@ -1390,6 +1394,7 @@ static int ipx_release(struct socket *sock)
if (!sk)
goto out;
+ lock_kernel();
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk);
@@ -1397,6 +1402,7 @@ static int ipx_release(struct socket *sock)
sock->sk = NULL;
sk_refcnt_debug_release(sk);
ipx_destroy_socket(sk);
+ unlock_kernel();
out:
return 0;
}
@@ -1424,7 +1430,8 @@ static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc)
return htons(socketNum);
}
-static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int __ipx_bind(struct socket *sock,
+ struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
struct ipx_sock *ipxs = ipx_sk(sk);
@@ -1519,6 +1526,17 @@ out:
return rc;
}
+static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+ int rc;
+
+ lock_kernel();
+ rc = __ipx_bind(sock, uaddr, addr_len);
+ unlock_kernel();
+
+ return rc;
+}
+
static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags)
{
@@ -1531,6 +1549,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
+ lock_kernel();
if (addr_len != sizeof(*addr))
goto out;
addr = (struct sockaddr_ipx *)uaddr;
@@ -1550,7 +1569,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
IPX_NODE_LEN);
#endif /* CONFIG_IPX_INTERN */
- rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+ rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
sizeof(struct sockaddr_ipx));
if (rc)
goto out;
@@ -1577,6 +1596,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
ipxrtr_put(rt);
rc = 0;
out:
+ unlock_kernel();
return rc;
}
@@ -1592,6 +1612,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
*uaddr_len = sizeof(struct sockaddr_ipx);
+ lock_kernel();
if (peer) {
rc = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
@@ -1626,6 +1647,19 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
rc = 0;
out:
+ unlock_kernel();
+ return rc;
+}
+
+static unsigned int ipx_datagram_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+{
+ int rc;
+
+ lock_kernel();
+ rc = datagram_poll(file, sock, wait);
+ unlock_kernel();
+
return rc;
}
@@ -1700,6 +1734,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
int rc = -EINVAL;
int flags = msg->msg_flags;
+ lock_kernel();
/* Socket gets bound below anyway */
/* if (sk->sk_zapped)
return -EIO; */ /* Socket not bound */
@@ -1723,7 +1758,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
memcpy(uaddr.sipx_node, ipxs->intrfc->if_node,
IPX_NODE_LEN);
#endif
- rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+ rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
sizeof(struct sockaddr_ipx));
if (rc)
goto out;
@@ -1751,6 +1786,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
if (rc >= 0)
rc = len;
out:
+ unlock_kernel();
return rc;
}
@@ -1765,6 +1801,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
struct sk_buff *skb;
int copied, rc;
+ lock_kernel();
/* put the autobinding in */
if (!ipxs->port) {
struct sockaddr_ipx uaddr;
@@ -1779,7 +1816,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN);
#endif /* CONFIG_IPX_INTERN */
- rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+ rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
sizeof(struct sockaddr_ipx));
if (rc)
goto out;
@@ -1823,6 +1860,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free:
skb_free_datagram(sk, skb);
out:
+ unlock_kernel();
return rc;
}
@@ -1834,6 +1872,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
struct sock *sk = sock->sk;
void __user *argp = (void __user *)arg;
+ lock_kernel();
switch (cmd) {
case TIOCOUTQ:
amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
@@ -1896,6 +1935,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
+ unlock_kernel();
return rc;
}
@@ -1933,7 +1973,7 @@ static struct net_proto_family ipx_family_ops = {
.owner = THIS_MODULE,
};
-static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
+static const struct proto_ops ipx_dgram_ops = {
.family = PF_IPX,
.owner = THIS_MODULE,
.release = ipx_release,
@@ -1942,7 +1982,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = ipx_getname,
- .poll = datagram_poll,
+ .poll = ipx_datagram_poll,
.ioctl = ipx_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ipx_compat_ioctl,
@@ -1957,8 +1997,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.sendpage = sock_no_sendpage,
};
-SOCKOPS_WRAP(ipx_dgram, PF_IPX);
-
static struct packet_type ipx_8023_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_802_3),
.func = ipx_rcv,
--
1.6.3.3
^ permalink raw reply related
* [PATCH 1/5] net/appletalk: push down BKL into a atalk_dgram_ops
From: Arnd Bergmann @ 2009-11-05 14:37 UTC (permalink / raw)
To: linux-kernel
Cc: David Miller, John Kacur, Thomas Gleixner, Frederic Weisbecker,
Arnd Bergmann, Arnaldo Carvalho de Melo, Stephen Hemminger,
netdev
In-Reply-To: <1257431850-20874-1-git-send-email-arnd@arndb.de>
Making the BKL usage explicit in appletalk makes it more
obvious where it is used, reduces code size and helps
getting rid of the BKL in common code.
I did not analyse how to kill lock_kernel from appletalk
entirely, this will involve either proving that it's not
needed, or replacing with a proper mutex or spinlock,
after finding out which data structures are protected
by the lock.
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: David S. Miller <davem@davemloft.net>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
net/appletalk/ddp.c | 105 +++++++++++++++++++++++++++++++++++++-------------
1 files changed, 77 insertions(+), 28 deletions(-)
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index b1a4290..3b831c0 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1054,11 +1054,13 @@ static int atalk_release(struct socket *sock)
{
struct sock *sk = sock->sk;
+ lock_kernel();
if (sk) {
sock_orphan(sk);
sock->sk = NULL;
atalk_destroy_socket(sk);
}
+ unlock_kernel();
return 0;
}
@@ -1134,6 +1136,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sockaddr_at *addr = (struct sockaddr_at *)uaddr;
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
+ int err;
if (!sock_flag(sk, SOCK_ZAPPED) ||
addr_len != sizeof(struct sockaddr_at))
@@ -1142,37 +1145,44 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (addr->sat_family != AF_APPLETALK)
return -EAFNOSUPPORT;
+ lock_kernel();
if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) {
struct atalk_addr *ap = atalk_find_primary();
+ err = -EADDRNOTAVAIL;
if (!ap)
- return -EADDRNOTAVAIL;
+ goto out;
at->src_net = addr->sat_addr.s_net = ap->s_net;
at->src_node = addr->sat_addr.s_node= ap->s_node;
} else {
+ err = -EADDRNOTAVAIL;
if (!atalk_find_interface(addr->sat_addr.s_net,
addr->sat_addr.s_node))
- return -EADDRNOTAVAIL;
+ goto out;
at->src_net = addr->sat_addr.s_net;
at->src_node = addr->sat_addr.s_node;
}
if (addr->sat_port == ATADDR_ANYPORT) {
- int n = atalk_pick_and_bind_port(sk, addr);
+ err = atalk_pick_and_bind_port(sk, addr);
- if (n < 0)
- return n;
+ if (err < 0)
+ goto out;
} else {
at->src_port = addr->sat_port;
+ err = -EADDRINUSE;
if (atalk_find_or_insert_socket(sk, addr))
- return -EADDRINUSE;
+ goto out;
}
sock_reset_flag(sk, SOCK_ZAPPED);
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
/* Set the address we talk to */
@@ -1182,6 +1192,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
struct sockaddr_at *addr;
+ int err;
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
@@ -1206,12 +1217,15 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
#endif
}
+ lock_kernel();
+ err = -EBUSY;
if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
- return -EBUSY;
+ goto out;
+ err = -ENETUNREACH;
if (!atrtr_get_dev(&addr->sat_addr))
- return -ENETUNREACH;
+ goto out;
at->dest_port = addr->sat_port;
at->dest_net = addr->sat_addr.s_net;
@@ -1219,7 +1233,10 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
sock->state = SS_CONNECTED;
sk->sk_state = TCP_ESTABLISHED;
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}
/*
@@ -1232,17 +1249,21 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_at sat;
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
+ int err;
+ lock_kernel();
+ err = -ENOBUFS;
if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
- return -ENOBUFS;
+ goto out;
*uaddr_len = sizeof(struct sockaddr_at);
memset(&sat.sat_zero, 0, sizeof(sat.sat_zero));
if (peer) {
+ err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ goto out;
sat.sat_addr.s_net = at->dest_net;
sat.sat_addr.s_node = at->dest_node;
@@ -1253,9 +1274,23 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
sat.sat_port = at->src_port;
}
+ err = 0;
sat.sat_family = AF_APPLETALK;
memcpy(uaddr, &sat, sizeof(sat));
- return 0;
+
+out:
+ unlock_kernel();
+ return err;
+}
+
+static unsigned int atalk_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+{
+ int err;
+ lock_kernel();
+ err = datagram_poll(file, sock, wait);
+ unlock_kernel();
+ return err;
}
#if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE)
@@ -1563,23 +1598,28 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
if (len > DDP_MAXSZ)
return -EMSGSIZE;
+ lock_kernel();
if (usat) {
+ err = -EBUSY;
if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
- return -EBUSY;
+ goto out;
+ err = -EINVAL;
if (msg->msg_namelen < sizeof(*usat) ||
usat->sat_family != AF_APPLETALK)
- return -EINVAL;
+ goto out;
+ err = -EPERM;
/* netatalk didn't implement this check */
if (usat->sat_addr.s_node == ATADDR_BCAST &&
!sock_flag(sk, SOCK_BROADCAST)) {
- return -EPERM;
+ goto out;
}
} else {
+ err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ goto out;
usat = &local_satalk;
usat->sat_family = AF_APPLETALK;
usat->sat_port = at->dest_port;
@@ -1603,8 +1643,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
rt = atrtr_find(&at_hint);
}
+ err = ENETUNREACH;
if (!rt)
- return -ENETUNREACH;
+ goto out;
dev = rt->dev;
@@ -1614,7 +1655,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
size += dev->hard_header_len;
skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err);
if (!skb)
- return err;
+ goto out;
skb->sk = sk;
skb_reserve(skb, ddp_dl->header_length);
@@ -1637,7 +1678,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
if (err) {
kfree_skb(skb);
- return -EFAULT;
+ err = -EFAULT;
+ goto out;
}
if (sk->sk_no_check == 1)
@@ -1676,7 +1718,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
rt = atrtr_find(&at_lo);
if (!rt) {
kfree_skb(skb);
- return -ENETUNREACH;
+ err = -ENETUNREACH;
+ goto out;
}
dev = rt->dev;
skb->dev = dev;
@@ -1696,7 +1739,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
}
SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len);
- return len;
+out:
+ unlock_kernel();
+ return err ? : len;
}
static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
@@ -1708,10 +1753,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
int copied = 0;
int offset = 0;
int err = 0;
- struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+ struct sk_buff *skb;
+
+ lock_kernel();
+ skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err);
if (!skb)
- return err;
+ goto out;
/* FIXME: use skb->cb to be able to use shared skbs */
ddp = ddp_hdr(skb);
@@ -1739,6 +1787,9 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
}
skb_free_datagram(sk, skb); /* Free the datagram. */
+
+out:
+ unlock_kernel();
return err ? : copied;
}
@@ -1827,7 +1878,7 @@ static struct net_proto_family atalk_family_ops = {
.owner = THIS_MODULE,
};
-static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
+static const struct proto_ops atalk_dgram_ops = {
.family = PF_APPLETALK,
.owner = THIS_MODULE,
.release = atalk_release,
@@ -1836,7 +1887,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = atalk_getname,
- .poll = datagram_poll,
+ .poll = atalk_poll,
.ioctl = atalk_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = atalk_compat_ioctl,
@@ -1851,8 +1902,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.sendpage = sock_no_sendpage,
};
-SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK);
-
static struct notifier_block ddp_notifier = {
.notifier_call = ddp_device_event,
};
--
1.6.3.3
^ permalink raw reply related
* Re: [PATCH] tcp: set SPLICE_F_NONBLOCK after first buffer has been spliced
From: Max Kellermann @ 2009-11-05 14:33 UTC (permalink / raw)
To: Eric Dumazet; +Cc: linux-kernel, jens.axboe, Linux Netdev List
In-Reply-To: <4AF2DD21.8060604@gmail.com>
On 2009/11/05 15:11, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> It cannot, therefore an application uses O_NDELAY to avoid blocking.
>
> Try following program if you are not convinced
Indeed, I'm surprised by the result rendered by the Linux kernel.
That however still contradicts with the poll() documentation.
So this boils down to the question: kernel bug or documentation bug?
http://www.opengroup.org/onlinepubs/9699919799/functions/pselect.html
"A descriptor shall be considered ready for writing when a call to an
output function with O_NONBLOCK clear would not block, whether or not
the function would transfer data successfully."
There is no size limit mentioned here. Your program reveals that the
kernel violates this definition.
> Your patch basically makes SPLICE_F_NONBLOCK option always set
> (choice 1) above)
[...]
> Why in the first place have an option if it is always set ?
It is not, you misunderstood my patch. If there's no room in the pipe
buffer, then the first iteration of the "while" loop will block (as
usual). *After* the first iteration has finished (and at least one
buffer has been moved already), the flag is set, and further
iterations will not block.
^ permalink raw reply
* Re: [PATCH RFC] gianfar: Make polling safe with IRQs disabled
From: Anton Vorontsov @ 2009-11-05 14:20 UTC (permalink / raw)
To: Jon Loeliger
Cc: David Miller, linuxppc-dev, netdev, Andy Fleming, Jason Wessel
In-Reply-To: <E1N62ti-0003iS-K2@jdl.com>
On Thu, Nov 05, 2009 at 08:01:10AM -0600, Jon Loeliger wrote:
> > When using KGDBoE, gianfar driver spits 'Interrupt problem' messages,
> > which appears to be a legitimate warning, i.e. we may end up calling
> > netif_receive_skb() or vlan_hwaccel_receive_skb() with IRQs disabled.
> >
> > This patch reworks the RX path so that if netpoll is enabled (the
> > only case when the driver don't know from what context the polling
> > may be called), we check whether IRQs are disabled, and if so we
> > fall back to safe variants of skb receiving functions.
> >
> > Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> > ---
> >
> > I'm not sure if this is suitable for mainline since it doesn't
> > have KGDBoE support. Jason, if the patch is OK, would you like
> > to merge it into KGDB tree?
>
> It's a legitimate problem with or without KGDBoE. I see it
> occasionally when conn_track is enabled as well, for example.
Hm, then I'd better remove the #ifdef CONFIG_NETPOLL.
Interestingly though, why conn_track does the polling with irqs
disabled, could be a bug in the conn_track? Because pretty much
drivers assume that polling is called with IRQs enabled.
If it's easily reproducible, could you replace the printk() with
WARN_ON(1) and post the backtrace? Or I can try to reproduce the
issue if you tell me how.
Thanks!
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH] tcp: set SPLICE_F_NONBLOCK after first buffer has been spliced
From: Eric Dumazet @ 2009-11-05 14:11 UTC (permalink / raw)
To: Max Kellermann; +Cc: linux-kernel, jens.axboe, Linux Netdev List
In-Reply-To: <20091105132352.GA14453@rabbit.intern.cm-ag>
Max Kellermann a écrit :
> On 2009/11/05 12:21, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> Max Kellermann a écrit :
>>> Do you think that a splice() should block if the socket is readable
>>> and the pipe is writable according to select()?
>>>
>> Yes, this is perfectly legal
>>
>> select() can return "OK to write on fd",
>> and still, write(fd, buffer, 10000000) is supposer/allowed to block if fd is not O_NDELAY
>
>>From the select() manpage: "those in writefds will be watched to see
> if a write will not block"
>
>>From the poll() manpage: "Writing now will not block."
>
> This looks unambiguous to me, and contradicts with your thesis. Can
> you provide sources?
>
> What is your interpretation of the guarantees provided by select() and
> poll()? Which byte count is "ok" to write after POLLOUT, and how much
> is "too much"? How does the application know?
It cannot, therefore an application uses O_NDELAY to avoid blocking.
Try following program if you are not convinced
#include <unistd.h>
#include <sys/poll.h>
#include <stdio.h>
char buffer[1000000];
int main(int argc, char *argv[])
{
int fds[2];
struct pollfd pfd;
int res;
pipe(fds);
pfd.fd = fds[1];
pfd.events = POLLOUT;
res = poll(&pfd, 1, -1);
if (res > 0 && pfd.revents & POLLOUT)
printf("OK to write on pipe\n");
write(fds[1], buffer, sizeof(buffer)); // why it blocks, did poll() lied ???
return 0;
}
> I understand your patch, but I don't understand the conflict with my
> patch. Can you describe a breakage caused by my patch?
I only pointed out that using splice(tcp -> pipe) and blocking on pipe
_can_ block, even on _first_ frame received from tcp, as you discovered.
Your only choices to avoid a deadlock are :
1) to use SPLICE_F_NONBLOCK.
2) Using a second thread to read the pipe and empty it. First thread will
happily transfert 1000000 bytes in one syscall...
3) or limit your splice(... len, flags) length to 16 (16 buffers of one byte
in pathological cases)
Your patch basically makes SPLICE_F_NONBLOCK option always set (choice 1) above)
So users wanting option 3) are stuck. You force them to use a poll()/select()
thing while they dont want to poll : They have a producer thread(s), and a consumer
thread(s).
producer()
{
while (1)
splice(tcp, &offset, pfds[1], NULL, 10000000,
SPLICE_F_MORE | SPLICE_F_MOVE);
}
Why in the first place have an option if it is always set ?
^ permalink raw reply
* Re: Shared i2c adapter locking
From: Jean Delvare @ 2009-11-05 14:07 UTC (permalink / raw)
To: Ben Hutchings
Cc: Stephen Rothwell, David Miller, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-next-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mika Kuoppala, Linux I2C
In-Reply-To: <1257429444.2793.2.camel-xQnnTUlwzDrdvaEqJLTMTA9jg9n5Vt1AMm0uRHvK7Nw@public.gmane.org>
On Thu, 05 Nov 2009 13:57:24 +0000, Ben Hutchings wrote:
> On Thu, 2009-11-05 at 14:11 +0100, Jean Delvare wrote:
> [...]
> > What about the following patch?
> >
> > From: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
> > Subject: i2c: Add an interface to lock/unlock I2C bus segment
> >
> > Some drivers need to be able to prevent access to an I2C bus segment
> > for a specific period of time. Add an interface for them to do so
> > without twiddling with i2c-core internals.
> >
> > Signed-off-by: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
> > Cc: Ben Hutchings <bhutchings-s/n/eUQHGBpZroRs9YW3xA@public.gmane.org>
> Acked-by: Ben Hutchings <bhutchings-s/n/eUQHGBpZroRs9YW3xA@public.gmane.org>
>
> Presumably this is meant for net-next-2.6, and you'll implement
Actually I meant to push this to Linus immediately, through my i2c
tree. This is essentially a no-op: the binary code will be the same as
before the patch, so guaranteed to be safe, and this will solve
conflicts in linux-next.
> i2c_{lock,unlock}_adapter() using rt_mutex in your i2c tree?
Correct.
--
Jean Delvare
^ permalink raw reply
* Re: Shared i2c adapter locking
From: Ben Hutchings @ 2009-11-05 13:57 UTC (permalink / raw)
To: Jean Delvare
Cc: Stephen Rothwell, David Miller, netdev, linux-next, linux-kernel,
Mika Kuoppala, Linux I2C
In-Reply-To: <20091105141122.56b6b4f8@hyperion.delvare>
On Thu, 2009-11-05 at 14:11 +0100, Jean Delvare wrote:
[...]
> What about the following patch?
>
> From: Jean Delvare <khali@linux-fr.org>
> Subject: i2c: Add an interface to lock/unlock I2C bus segment
>
> Some drivers need to be able to prevent access to an I2C bus segment
> for a specific period of time. Add an interface for them to do so
> without twiddling with i2c-core internals.
>
> Signed-off-by: Jean Delvare <khali@linux-fr.org>
> Cc: Ben Hutchings <bhutchings@solarflare.com>
Acked-by: Ben Hutchings <bhutchings@solarflare.com>
Presumably this is meant for net-next-2.6, and you'll implement
i2c_{lock,unlock}_adapter() using rt_mutex in your i2c tree?
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 1/3] net: TCP thin-stream detection
From: Ilpo Järvinen @ 2009-11-05 13:45 UTC (permalink / raw)
To: Andreas Petlund
Cc: Arnd Hannemann, William Allen Simpson, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, shemminger@vyatta.com,
davem@davemloft.net
In-Reply-To: <4AF2D47F.4030701@simula.no>
On Thu, 5 Nov 2009, Andreas Petlund wrote:
> Arnd Hannemann wrote:
> >
> > One example: Consider standard NewReno non-SACK enabled flow:
> > For some reasons two data packets get reordered.
> > The TCP sender will produce a dupACK and an ACK.
> > The dupACK will trigger (because of your logic) a spurious retransmit.
> > The spurious retransmit will trigger a dupACK.
> > This dupACK will again trigger a spurious retransmit.
> > And this game will continue, unless a packet is dropped by coincidence.
>
> Such an effect will be extremely rare. It will depend on the application
> producing an extremely even flow of packets with just the right
> interarrival time, and also on reordering of data (which also will
> happen very seldom when the number of packets in flight are so low).
> Even though it can happen, the data flow will progress (with spurious
> retransmissions). The effect will stop as soon as the application sends
> more than 4 segments in an RTT (which will disable the thin-stream
> modifications) or less than 1 (which will cause all segments to be
> successfully ACKed), or if, as you say, a packet is dropped.
I'd simply workaround this problem by requiring SACK to be enabled for
such a connection. This is reinforced by the fact that small windowed
transfers want it certainly to be on anyway to get the best out of ACK
flow even if there were some ACK losses.
--
i.
^ permalink raw reply
* RE: [PATCH 19/25] mlx4: Randomizing mac addresses for slaves
From: Liran Liss @ 2009-11-05 13:38 UTC (permalink / raw)
To: Or Gerlitz, Roland Dreier
Cc: Yevgeny Petrilin, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Tziporet Koren
In-Reply-To: <15ddcffd0911041333l165ee274mfae3508a3db755e7-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
This approach seems to be common practice now (e.g., drivers/net/igb/igb_main.c:1332).
In any case, the user can change the randomized mac.
--Liran
-----Original Message-----
From: Or Gerlitz [mailto:or.gerlitz-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org]
Sent: Wednesday, November 04, 2009 11:33 PM
To: Roland Dreier
Cc: Yevgeny Petrilin; linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; netdev-u79uwXL29TaqPxH82wqD4g@public.gmane.orgg; Liran Liss; Tziporet Koren
Subject: Re: [PATCH 19/25] mlx4: Randomizing mac addresses for slaves
On Wed, Nov 4, 2009 at 10:04 PM, Roland Dreier <rdreier-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org> wrote:
>> +#define MLX4_MAC_HEAD 0x2c9000000ULL
> Is this a good idea? You're basically choosing 24 random bits within your OUI...
> seems the chance of collision with another MAC used on the same
> network is high enough that it could easily happen in practice on a moderately big network.
yes, this has been brought by Stephen and others on this last back on September 11th, this year @
http://marc.info/?l=linux-netdev&m=125263488409128
> Can you pick a reserved range or something?
Using different OUI for the VF device wouldn't help either I think, since the #VF becomes fairly big even on a modest side cluster with
(say) a VM consuming VF per 1-2 cores.
Or.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox