>From Kirill Kapranov <k...@nita.ru>,<kapran...@inbox.ru> NET/PHY: Eliminate the forced speed reduction algorithm. In case of fixed speed set up for a NIC (e.g. ethtool -s eth0 autoneg off speed 100 duplex full) with an ethernet cable plugged off, the mentioned algorithm slows down a NIC speed, so further hooking up a cable does not lead to "link" state. Signed-off-by: Kirill Kapranov <k...@nita.ru>,<kapran...@inbox.ru> --- The purpose of the introduced patch is deletion of the forced speed reduction algorithm realization from the driver module "phy". The above mentioned algorithm works in the following way: if the PHY detected unlink line state (connector plugged off), NIC speed is decreased step-by-step in the sequence: 100 full duplex 100 half duplex 10 full duplex 10 half duplex with the latency circa 10 s per step, and stops at 10-HD value. I have looked up RFC-802.3, and found, that the mentioned algorithm is neither quoted nor described. AFAIK, no one RFC describe the mentioned algorithm, so it may be a witty invention of the developer(s).
In the case of the fixed speed and duplex set, with the autonegotiation off, for a NIC (e.g. # ethtool -s eth0 autoneg off speed 100 duplex full) with ethernet cable plugged off, mentioned algorithm slows down NIC speed, so when ethernet connector is plugged in, connection will be inoperative: an ethernet switch will try to connect with 100/full (e.g.), a NIC will stay at 10/half. Thus, this algorithm is destructive for the fixed speed/duplex mode (with autonegotiation off). In the AUTO mode, the mentioned algorithm is inessential. The autonegotiation procedure works fine regardless an speed/duplex settings at the moment of connector hooking up. Thus, there is no point in using of this algorithm in driver. Tested at 2.6.38.7, applicable up to for 3.0.4. --- linux/drivers/net/phy/phy.c.orig 2011-05-22 02:13:59.000000000 +0400 +++ linux/drivers/net/phy/phy.c 2012-04-28 12:49:37.000000000 +0400 @@ -457,34 +457,6 @@ void phy_stop_machine(struct phy_device } /** - * phy_force_reduction - reduce PHY speed/duplex settings by one step - * @phydev: target phy_device struct - * - * Description: Reduces the speed/duplex settings by one notch, - * in this order-- - * 1000/FULL, 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF. - * The function bottoms out at 10/HALF. - */ -static void phy_force_reduction(struct phy_device *phydev) -{ - int idx; - - idx = phy_find_setting(phydev->speed, phydev->duplex); - - idx++; - - idx = phy_find_valid(idx, phydev->supported); - - phydev->speed = settings[idx].speed; - phydev->duplex = settings[idx].duplex; - - pr_info("Trying %d/%s\n", phydev->speed, - DUPLEX_FULL == phydev->duplex ? - "FULL" : "HALF"); -} - - -/** * phy_error - enter HALTED state for this PHY device * @phydev: target phy_device struct * @@ -814,30 +786,12 @@ void phy_state_machine(struct work_struc phydev->adjust_link(phydev->attached_dev); } else if (0 == phydev->link_timeout--) { - int idx; needs_aneg = 1; /* If we have the magic_aneg bit, * we try again */ if (phydev->drv->flags & PHY_HAS_MAGICANEG) break; - - /* The timer expired, and we still - * don't have a setting, so we try - * forcing it until we find one that - * works, starting from the fastest speed, - * and working our way down */ - idx = phy_find_valid(0, phydev->supported); - - phydev->speed = settings[idx].speed; - phydev->duplex = settings[idx].duplex; - - phydev->autoneg = AUTONEG_DISABLE; - - pr_info("Trying %d/%s\n", phydev->speed, - DUPLEX_FULL == - phydev->duplex ? - "FULL" : "HALF"); } break; case PHY_NOLINK: @@ -863,7 +817,6 @@ void phy_state_machine(struct work_struc netif_carrier_on(phydev->attached_dev); } else { if (0 == phydev->link_timeout--) { - phy_force_reduction(phydev); needs_aneg = 1; } } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/