Netdev List
 help / color / mirror / Atom feed
* [PATCH net,1/1] hyperv: Add support for setting MAC from within guests
From: Haiyang Zhang @ 2012-07-06 21:25 UTC (permalink / raw)
  To: davem, netdev; +Cc: haiyangz, kys, olaf, linux-kernel, devel

This adds support for setting synthetic NIC MAC address from within Linux
guests. Before using this feature, the option "spoofing of MAC address"
should be enabled at the Hyper-V manager / Settings of the synthetic
NIC.

Thanks to Kin Cho <kcho@infoblox.com> for the initial implementation and
tests. And, thanks to Long Li <longli@microsoft.com> for the debugging
works.

Reported-and-tested-by: Kin Cho <kcho@infoblox.com>
Reported-by: Long Li <longli@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/net/hyperv/hyperv_net.h   |    1 +
 drivers/net/hyperv/netvsc_drv.c   |   30 +++++++++++++-
 drivers/net/hyperv/rndis_filter.c |   79 +++++++++++++++++++++++++++++++++++++
 3 files changed, 109 insertions(+), 1 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 2857ab0..95ceb35 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -131,6 +131,7 @@ int rndis_filter_send(struct hv_device *dev,
 			struct hv_netvsc_packet *pkt);
 
 int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
+int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);
 
 
 #define NVSP_INVALID_PROTOCOL_VERSION	((u32)0xFFFFFFFF)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 8f8ed33..8e23c08 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -341,6 +341,34 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
 	return 0;
 }
 
+
+static int netvsc_set_mac_addr(struct net_device *ndev, void *p)
+{
+	struct net_device_context *ndevctx = netdev_priv(ndev);
+	struct hv_device *hdev =  ndevctx->device_ctx;
+	struct sockaddr *addr = p;
+	char save_adr[14];
+	unsigned char save_aatype;
+	int err;
+
+	memcpy(save_adr, ndev->dev_addr, ETH_ALEN);
+	save_aatype = ndev->addr_assign_type;
+
+	err = eth_mac_addr(ndev, p);
+	if (err != 0)
+		return err;
+
+	err = rndis_filter_set_device_mac(hdev, addr->sa_data);
+	if (err != 0) {
+		/* roll back to saved MAC */
+		memcpy(ndev->dev_addr, save_adr, ETH_ALEN);
+		ndev->addr_assign_type = save_aatype;
+	}
+
+	return err;
+}
+
+
 static const struct ethtool_ops ethtool_ops = {
 	.get_drvinfo	= netvsc_get_drvinfo,
 	.get_link	= ethtool_op_get_link,
@@ -353,7 +381,7 @@ static const struct net_device_ops device_ops = {
 	.ndo_set_rx_mode =		netvsc_set_multicast_list,
 	.ndo_change_mtu =		netvsc_change_mtu,
 	.ndo_validate_addr =		eth_validate_addr,
-	.ndo_set_mac_address =		eth_mac_addr,
+	.ndo_set_mac_address =		netvsc_set_mac_addr,
 };
 
 /*
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 981ebb1..fbf5394 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -27,6 +27,7 @@
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/nls.h>
 
 #include "hyperv_net.h"
 
@@ -47,6 +48,7 @@ struct rndis_request {
 	struct hv_page_buffer buf;
 	/* FIXME: We assumed a fixed size request here. */
 	struct rndis_message request_msg;
+	u8 ext[100];
 };
 
 static void rndis_filter_send_completion(void *ctx);
@@ -511,6 +513,83 @@ static int rndis_filter_query_device_mac(struct rndis_device *dev)
 				      dev->hw_mac_adr, &size);
 }
 
+#define NWADR_STR "NetworkAddress"
+#define NWADR_STRLEN 14
+
+int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac)
+{
+	struct netvsc_device *nvdev = hv_get_drvdata(hdev);
+	struct rndis_device *rdev = nvdev->extension;
+	struct net_device *ndev = nvdev->ndev;
+	struct rndis_request *request;
+	struct rndis_set_request *set;
+	struct rndis_config_parameter_info *cpi;
+	wchar_t *cfg_nwadr, *cfg_mac;
+	struct rndis_set_complete *set_complete;
+	char macstr[2*ETH_ALEN+1];
+	u32 extlen = sizeof(struct rndis_config_parameter_info) +
+		2*NWADR_STRLEN + 4*ETH_ALEN;
+	int ret, t;
+
+	request = get_rndis_request(rdev, RNDIS_MSG_SET,
+		RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
+	if (!request)
+		return -ENOMEM;
+
+	set = &request->request_msg.msg.set_req;
+	set->oid = RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER;
+	set->info_buflen = extlen;
+	set->info_buf_offset = sizeof(struct rndis_set_request);
+	set->dev_vc_handle = 0;
+
+	cpi = (struct rndis_config_parameter_info *)((ulong)set +
+		set->info_buf_offset);
+	cpi->parameter_name_offset =
+		sizeof(struct rndis_config_parameter_info);
+	/* Multiply by 2 because host needs 2 bytes (utf16) for each char */
+	cpi->parameter_name_length = 2*NWADR_STRLEN;
+	cpi->parameter_type = RNDIS_CONFIG_PARAM_TYPE_STRING;
+	cpi->parameter_value_offset =
+		cpi->parameter_name_offset + cpi->parameter_name_length;
+	/* Multiply by 4 because each MAC byte displayed as 2 utf16 chars */
+	cpi->parameter_value_length = 4*ETH_ALEN;
+
+	cfg_nwadr = (wchar_t *)((ulong)cpi + cpi->parameter_name_offset);
+	cfg_mac = (wchar_t *)((ulong)cpi + cpi->parameter_value_offset);
+	ret = utf8s_to_utf16s(NWADR_STR, NWADR_STRLEN, UTF16_HOST_ENDIAN,
+			      cfg_nwadr, NWADR_STRLEN);
+	if (ret < 0)
+		goto cleanup;
+	snprintf(macstr, 2*ETH_ALEN+1, "%pm", mac);
+	ret = utf8s_to_utf16s(macstr, 2*ETH_ALEN, UTF16_HOST_ENDIAN,
+			      cfg_mac, 2*ETH_ALEN);
+	if (ret < 0)
+		goto cleanup;
+
+	ret = rndis_filter_send_request(rdev, request);
+	if (ret != 0)
+		goto cleanup;
+
+	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+	if (t == 0) {
+		netdev_err(ndev, "timeout before we got a set response...\n");
+		/*
+		 * can't put_rndis_request, since we may still receive a
+		 * send-completion.
+		 */
+		return -EBUSY;
+	} else {
+		set_complete = &request->response_msg.msg.set_complete;
+		if (set_complete->status != RNDIS_STATUS_SUCCESS)
+			ret = -EINVAL;
+	}
+
+cleanup:
+	put_rndis_request(rdev, request);
+	return ret;
+}
+
+
 static int rndis_filter_query_device_link_status(struct rndis_device *dev)
 {
 	u32 size = sizeof(u32);
-- 
1.7.4.1

^ permalink raw reply related

* Re: [PATCH 4/4] asix: Add a new driver for the AX88172A
From: Grant Grundler @ 2012-07-06 21:20 UTC (permalink / raw)
  To: Christian Riesch
  Cc: netdev, Oliver Neukum, Eric Dumazet, Allan Chou, Mark Lord,
	Ming Lei, Michael Riesch
In-Reply-To: <1341574388-7464-5-git-send-email-christian.riesch@omicron.at>

On Fri, Jul 6, 2012 at 4:33 AM, Christian Riesch
<christian.riesch@omicron.at> wrote:
> The Asix AX88172A is a USB 2.0 Ethernet interface that supports both an
> internal PHY as well as an external PHY (connected via MII).
>
> This patch adds a driver for the AX88172A and provides support for
> both modes and supports phylib.

Christian,
In general this looks fine to me...but I wouldn't know about "bus
identifier life times" (Ben Hutchings comment).

My nit pick is the declaration and of use_embdphy. An alternative
coding _suggestion_ below.  I'm not substantially altering the
functionality.

thanks,
grant

>
> Signed-off-by: Christian Riesch <christian.riesch@omicron.at>
> ---
>  drivers/net/usb/Makefile       |    2 +-
>  drivers/net/usb/asix_devices.c |    6 +
>  drivers/net/usb/ax88172a.c     |  407 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 414 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/net/usb/ax88172a.c
>
> diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
> index a9490d9..bf06300 100644
> --- a/drivers/net/usb/Makefile
> +++ b/drivers/net/usb/Makefile
> @@ -8,7 +8,7 @@ obj-$(CONFIG_USB_PEGASUS)       += pegasus.o
>  obj-$(CONFIG_USB_RTL8150)      += rtl8150.o
>  obj-$(CONFIG_USB_HSO)          += hso.o
>  obj-$(CONFIG_USB_NET_AX8817X)  += asix.o
> -asix-y := asix_devices.o asix_common.o
> +asix-y := asix_devices.o asix_common.o ax88172a.o
>  obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
>  obj-$(CONFIG_USB_NET_CDC_EEM)  += cdc_eem.o
>  obj-$(CONFIG_USB_NET_DM9601)   += dm9601.o
> diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
> index c8682a5..02b8c21 100644
> --- a/drivers/net/usb/asix_devices.c
> +++ b/drivers/net/usb/asix_devices.c
> @@ -877,6 +877,8 @@ static const struct driver_info ax88178_info = {
>         .tx_fixup = asix_tx_fixup,
>  };
>
> +extern const struct driver_info ax88172a_info;
> +
>  static const struct usb_device_id      products[] = {
>  {
>         /* Linksys USB200M */
> @@ -1002,6 +1004,10 @@ static const struct usb_device_id        products[] = {
>         /* Asus USB Ethernet Adapter */
>         USB_DEVICE(0x0b95, 0x7e2b),
>         .driver_info = (unsigned long) &ax88772_info,
> +}, {
> +       /* ASIX 88172a demo board */
> +       USB_DEVICE(0x0b95, 0x172a),
> +       .driver_info = (unsigned long) &ax88172a_info,
>  },
>         { },            /* END */
>  };
> diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c
> new file mode 100644
> index 0000000..9f2d1fd
> --- /dev/null
> +++ b/drivers/net/usb/ax88172a.c
> @@ -0,0 +1,407 @@
> +/*
> + * ASIX AX88172A based USB 2.0 Ethernet Devices
> + * Copyright (C) 2012 OMICRON electronics GmbH
> + *
> + * Supports external PHYs via phylib. Based on the driver for the
> + * AX88772. Original copyrights follow:
> + *
> + * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
> + * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
> + * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
> + * Copyright (c) 2002-2003 TiVo Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#include "asix.h"
> +#include <linux/phy.h>
> +
> +struct ax88172a_private {
> +       int use_embdphy;

Can you move the "int" to the end of the struct?
It's cleaner to have fields "natively align". ie pointers should start
at 8 byte alignments when compiled for 64-bit.

> +       struct mii_bus *mdio;
> +       struct phy_device *phydev;
> +       char phy_name[20];
> +       u16 phy_addr;
> +       u16 oldmode;
> +};
> +
> +static inline int asix_read_phy_addr(struct usbnet *dev, int internal)
> +{
> +       int offset = (internal ? 1 : 0);

One could use "internal" parameter directly for indexing if
use_embdphy were renamed to use_extphy and the logic inverted..

> +       u8 buf[2];
> +       int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
> +
> +       netdev_dbg(dev->net, "asix_get_phy_addr()\n");
> +
> +       if (ret < 0) {
> +               netdev_err(dev->net, "Error reading PHYID register: %02x\n",
> +                          ret);
> +               goto out;
> +       }
> +       netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n",
> +                  *((__le16 *)buf));
> +       ret = buf[offset];
> +
> +out:
> +       return ret;
> +}
> +
> +static int ax88172a_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
> +{
> +       return phy_mii_ioctl(net->phydev, rq, cmd);
> +}
> +
> +/* MDIO read and write wrappers for phylib */
> +static int asix_mdio_bus_read(struct mii_bus *bus, int phy_id, int regnum)
> +{
> +       return asix_mdio_read(((struct usbnet *)bus->priv)->net, phy_id,
> +                             regnum);
> +}
> +
> +static int asix_mdio_bus_write(struct mii_bus *bus, int phy_id, int regnum,
> +                              u16 val)
> +{
> +       asix_mdio_write(((struct usbnet *)bus->priv)->net, phy_id, regnum,
> +                       val);
> +       return 0;
> +}
> +
> +/* set MAC link settings according to information from phylib */
> +static void asix_adjust_link(struct net_device *netdev)
> +{
> +       struct phy_device *phydev = netdev->phydev;
> +       struct usbnet *dev = netdev_priv(netdev);
> +       struct ax88172a_private *priv =
> +               (struct ax88172a_private *)dev->driver_priv;
> +       u16 mode = 0;
> +
> +       dbg("asix_adjust_link called\n");
> +
> +       if (phydev->link) {
> +               mode = AX88772_MEDIUM_DEFAULT;
> +
> +               if (phydev->duplex == DUPLEX_HALF)
> +                       mode &= ~AX_MEDIUM_FD;
> +
> +               if (phydev->speed != SPEED_100)
> +                       mode &= ~AX_MEDIUM_PS;
> +       }
> +
> +       if (mode != priv->oldmode) {
> +               asix_write_medium_mode(dev, mode);
> +               priv->oldmode = mode;
> +               dbg("asix_adjust_link  speed: %u duplex: %d setting mode to 0x%04x\n",
> +                   phydev->speed, phydev->duplex, mode);
> +               phy_print_status(phydev);
> +       }
> +}
> +
> +static void ax88172a_status(struct usbnet *dev, struct urb *urb)
> +{
> +}
> +
> +/* use phylib infrastructure */
> +static int ax88172a_init_mdio(struct usbnet *dev)
> +{
> +       struct ax88172a_private *priv =
> +               (struct ax88172a_private *)dev->driver_priv;
> +       int ret, i;
> +
> +       priv->mdio = mdiobus_alloc();
> +       if (!priv->mdio) {
> +               dbg("Could not allocate MDIO bus");
> +               return -1;
> +       }
> +
> +       priv->mdio->priv = (void *)dev;
> +       priv->mdio->read = &asix_mdio_bus_read;
> +       priv->mdio->write = &asix_mdio_bus_write;
> +       priv->mdio->name = "Asix MDIO Bus";
> +       snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "asix-%s",
> +                dev_name(dev->net->dev.parent));
> +
> +       priv->mdio->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
> +       if (!priv->mdio->irq) {
> +               dbg("Could not allocate MDIO->IRQ");
> +               ret = -ENOMEM;
> +               goto mfree;
> +       }
> +       for (i = 0; i < PHY_MAX_ADDR; i++)
> +               priv->mdio->irq[i] = PHY_POLL;
> +
> +       ret = mdiobus_register(priv->mdio);
> +       if (ret) {
> +               dbg("Could not register MDIO bus");
> +               goto ifree;
> +       }
> +       snprintf(priv->phy_name, 20, PHY_ID_FMT,
> +                priv->mdio->id, priv->phy_addr);
> +
> +       priv->phydev = phy_connect(dev->net, priv->phy_name, &asix_adjust_link,
> +                                  0, PHY_INTERFACE_MODE_MII);
> +       if (IS_ERR(priv->phydev)) {
> +               dbg("Could not connect to PHY device");
> +               ret = PTR_ERR(priv->phydev);
> +               goto munreg;
> +       }
> +       dbg("dev->net->phydev (%s) is now 0x%p", priv->phy_name,
> +           dev->net->phydev);
> +
> +       /* During power-up, the AX88172A set the power down (BMCR_PDOWN)
> +        *   bit of the PHY. Bring the PHY up again.
> +        */
> +       genphy_resume(priv->phydev);
> +
> +       phy_start(priv->phydev);
> +
> +       return 0;
> +munreg:
> +       mdiobus_unregister(priv->mdio);
> +ifree:
> +       kfree(priv->mdio->irq);
> +mfree:
> +       mdiobus_free(priv->mdio);
> +       return ret;
> +}
> +
> +static void ax88172a_remove_mdio(struct usbnet *dev)
> +{
> +       struct ax88172a_private *priv =
> +               (struct ax88172a_private *)dev->driver_priv;
> +
> +       phy_stop(priv->phydev);
> +       phy_disconnect(priv->phydev);
> +       mdiobus_unregister(priv->mdio);
> +       kfree(priv->mdio->irq);
> +       mdiobus_free(priv->mdio);
> +}
> +
> +static const struct net_device_ops ax88172a_netdev_ops = {
> +       .ndo_open               = usbnet_open,
> +       .ndo_stop               = usbnet_stop,
> +       .ndo_start_xmit         = usbnet_start_xmit,
> +       .ndo_tx_timeout         = usbnet_tx_timeout,
> +       .ndo_change_mtu         = usbnet_change_mtu,
> +       .ndo_set_mac_address    = asix_set_mac_address,
> +       .ndo_validate_addr      = eth_validate_addr,
> +       .ndo_do_ioctl           = ax88172a_ioctl,
> +       .ndo_set_rx_mode        = asix_set_multicast,
> +};
> +
> +int ax88172a_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
> +{
> +       return phy_ethtool_gset(net->phydev, cmd);
> +}
> +
> +int ax88172a_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
> +{
> +       return phy_ethtool_sset(net->phydev, cmd);
> +}
> +
> +int ax88172a_nway_reset(struct net_device *net)
> +{
> +       return phy_start_aneg(net->phydev);
> +}
> +
> +static const struct ethtool_ops ax88172a_ethtool_ops = {
> +       .get_drvinfo            = asix_get_drvinfo,
> +       .get_link               = usbnet_get_link,
> +       .get_msglevel           = usbnet_get_msglevel,
> +       .set_msglevel           = usbnet_set_msglevel,
> +       .get_wol                = asix_get_wol,
> +       .set_wol                = asix_set_wol,
> +       .get_eeprom_len         = asix_get_eeprom_len,
> +       .get_eeprom             = asix_get_eeprom,
> +       .get_settings           = ax88172a_get_settings,
> +       .set_settings           = ax88172a_set_settings,
> +       .nway_reset             = ax88172a_nway_reset,
> +};
> +
> +static int ax88172a_reset_phy(struct usbnet *dev, int embd_phy)
> +{
> +       int ret;
> +
> +       ret = asix_sw_reset(dev, AX_SWRESET_IPPD);
> +       if (ret < 0)
> +               goto err;
> +
> +       msleep(150);
> +       ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
> +       if (ret < 0)
> +               goto err;
> +
> +       msleep(150);
> +
> +       ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_IPPD);

(would have to swap things here if adopting my suggestions.)

> +       if (ret < 0)
> +               goto err;
> +
> +       return 0;
> +
> +err:
> +       return ret;
> +}
> +
> +
> +static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf)
> +{
> +       int ret;
> +       struct asix_data *data = (struct asix_data *)&dev->data;
> +       u8 buf[ETH_ALEN];
> +       struct ax88172a_private *priv;
> +
> +       data->eeprom_len = AX88772_EEPROM_LEN;
> +
> +       usbnet_get_endpoints(dev, intf);
> +
> +       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +       if (!priv) {
> +               dbg("Could not allocate memory for private data");
> +               return -ENOMEM;
> +       }
> +       dev->driver_priv = priv;
> +
> +       /* Get the MAC address */
> +       ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf);
> +       if (ret < 0) {
> +               dbg("Failed to read MAC address: %d", ret);
> +               goto free;
> +       }
> +       memcpy(dev->net->dev_addr, buf, ETH_ALEN);
> +
> +       dev->net->netdev_ops = &ax88172a_netdev_ops;
> +       dev->net->ethtool_ops = &ax88172a_ethtool_ops;
> +
> +       /* are we using the internal or the external phy? */
> +       ret = asix_read_cmd(dev, AX_CMD_SW_PHY_STATUS, 0, 0, 1, buf);
> +       if (ret < 0) {
> +               dbg("Failed to read software interface selection register: %d",
> +                   ret);
> +               goto free;
> +       }
> +       dbg("AX_CMD_SW_PHY_STATUS = 0x%02x\n", buf[0]);
> +       switch ((buf[0] & 0x0c) >> 2) {
> +       case 0:
> +               dbg("use internal phy\n");
> +               priv->use_embdphy = 1;
> +               break;
> +       case 1:
> +               dbg("use external phy\n");
> +               priv->use_embdphy = 0;
> +               break;
> +       default:
> +               dbg("Interface mode not supported by driver\n");
> +               goto free;
> +       }

This switch statement inverts the existing logic. Much simpler code would be:
    /* buf[0] & 0xc describes phy interface mode */
    if (buf[0] &  8) {
         dbg("Interface mode not supported by driver\n");
         goto free;
    }
    priv->use_extphy = (buf[0] & 4) >> 2;

> +
> +       priv->phy_addr = asix_read_phy_addr(dev, priv->use_embdphy);
> +       ax88172a_reset_phy(dev, priv->use_embdphy);
> +
> +       /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
> +       if (dev->driver_info->flags & FLAG_FRAMING_AX) {
> +               /* hard_mtu  is still the default - the device does not support
> +                  jumbo eth frames */
> +               dev->rx_urb_size = 2048;
> +       }
> +
> +       /* init MDIO bus */
> +       ret = ax88172a_init_mdio(dev);
> +       if (ret)
> +               goto free;
> +
> +       return 0;
> +
> +free:
> +       kfree(priv);
> +       return ret;
> +}
> +
> +static void ax88172a_unbind(struct usbnet *dev, struct usb_interface *intf)
> +{
> +       struct ax88172a_private *priv =
> +               (struct ax88172a_private *)dev->driver_priv;
> +
> +       ax88172a_remove_mdio(dev);
> +       kfree(priv);
> +}
> +
> +static int ax88172a_reset(struct usbnet *dev)
> +{
> +       struct asix_data *data = (struct asix_data *)&dev->data;
> +       struct ax88172a_private *priv =
> +               (struct ax88172a_private *)dev->driver_priv;
> +       int ret;
> +       u16 rx_ctl;
> +
> +       ax88172a_reset_phy(dev, priv->use_embdphy);
> +
> +       msleep(150);
> +       rx_ctl = asix_read_rx_ctl(dev);
> +       dbg("RX_CTL is 0x%04x after software reset", rx_ctl);
> +       ret = asix_write_rx_ctl(dev, 0x0000);
> +       if (ret < 0)
> +               goto out;
> +
> +       rx_ctl = asix_read_rx_ctl(dev);
> +       dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
> +
> +       msleep(150);
> +
> +       ax88172a_nway_reset(dev->net);
> +
> +       ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
> +                               AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
> +                               AX88772_IPG2_DEFAULT, 0, NULL);
> +       if (ret < 0) {
> +               dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
> +               goto out;
> +       }
> +
> +       /* Rewrite MAC address */
> +       memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN);
> +       ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN,
> +                                                       data->mac_addr);
> +       if (ret < 0)
> +               goto out;
> +
> +       /* Set RX_CTL to default values with 2k buffer, and enable cactus */
> +       ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL);
> +       if (ret < 0)
> +               goto out;
> +
> +       rx_ctl = asix_read_rx_ctl(dev);
> +       dbg("RX_CTL is 0x%04x after all initializations", rx_ctl);
> +
> +       rx_ctl = asix_read_medium_status(dev);
> +       dbg("Medium Status is 0x%04x after all initializations", rx_ctl);
> +
> +       return 0;
> +
> +out:
> +       return ret;
> +
> +}
> +
> +const struct driver_info ax88172a_info = {
> +       .description = "ASIX AX88172A USB 2.0 Ethernet",
> +       .bind = ax88172a_bind,
> +       .unbind = ax88172a_unbind,
> +       .status = ax88172a_status,
> +       .reset = ax88172a_reset,
> +       .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
> +                FLAG_MULTI_PACKET,
> +       .rx_fixup = asix_rx_fixup,
> +       .tx_fixup = asix_tx_fixup,
> +};
> --
> 1.7.0.4
>

^ permalink raw reply

* Re: [RFC PATCH] bridge: netfilter: fix skb->nf_bridge NULL panic in br_nf_forward_finish
From: Julian Anastasov @ 2012-07-06 20:34 UTC (permalink / raw)
  To: Lin Ming
  Cc: Massimo Cetra, Eric Dumazet, netdev, Stephen Hemminger,
	David S. Miller
In-Reply-To: <1341584394.4789.34.camel@chief-river-32>


	Hello,

On Fri, 6 Jul 2012, Lin Ming wrote:

> I can reproduce similiar panic with 3.5-rc5 kernel as Massimo reported at:
> http://marc.info/?l=linux-netdev&m=134089242113979&w=2
> 
> The steps to reproduce as follow,
> 
> 1. On Host1, setup brige br0(192.168.1.106)
> 2. Boot a kvm guest(192.168.1.105) on Host1 and start httpd
> 3. Start IPVS service on Host1
>    ipvsadm -A -t 192.168.1.106:80 -s rr
>    ipvsadm -a -t 192.168.1.106:80 -r 192.168.1.105:80 -m
> 4. Run apache benchmark on Host2(192.168.1.101)
>    ab -n 1000 http://192.168.1.106/
> 
> The panic happened in br_nf_forward_finish because skb->nf_bridge is NULL.
> skb->nf_bridge is set to NULL in ip_vs_reply4 hook.
> 
> br_nf_forward_ip():
>   NF_HOOK(pf, NF_INET_FORWARD, skb, brnf_get_logical_dev(skb, in), parent,
>                 br_nf_forward_finish);
> 
> This calls IPVS hook ip_vs_reply4.
> 
> ip_vs_reply4
>   ip_vs_out
>     handle_response
>       ip_vs_notrack
>         nf_reset()
>         {
>           skb->nf_bridge = NULL;
>         }

	Actually, IPVS wants in this case just to replace nfct
with untracked version. May be it is better to replace
the nf_reset(skb) call in ip_vs_notrack() with a
nf_conntrack_put(skb->nfct) call. Can you test and post
such patch?

> This patch added skb->nf_bridge check in br_nf_forward_finish and the panic gone.
> But I am really not sure if this is the right fix.
> Please help to review.
> 
> The panic log attached.
> 
> [  579.781508] BUG: unable to handle kernel NULL pointer dereference at 0000000000000004
> [  579.781669] IP: [<ffffffff817b1ca5>] br_nf_forward_finish+0x58/0x112
> [  579.781792] PGD 218f9067 PUD 0 
> [  579.781865] Oops: 0000 [#1] SMP 
> [  579.781945] CPU 0 
> [  579.781983] Modules linked in:
> [  579.782047] 
> [  579.782080] 
> [  579.782114] Pid: 4644, comm: qemu Tainted: G        W    3.5.0-rc5-00006-g95e69f9 #282 Hewlett-Packard  /30E8
> [  579.782300] RIP: 0010:[<ffffffff817b1ca5>]  [<ffffffff817b1ca5>] br_nf_forward_finish+0x58/0x112
> [  579.782455] RSP: 0018:ffff88007b003a98  EFLAGS: 00010287
> [  579.782541] RAX: 0000000000000008 RBX: ffff8800762ead00 RCX: 000000000001670a
> [  579.782653] RDX: 0000000000000000 RSI: 000000000000000a RDI: ffff8800762ead00
> [  579.782845] RBP: ffff88007b003ac8 R08: 0000000000016630 R09: ffff88007b003a90
> [  579.782957] R10: ffff88007b0038e8 R11: ffff88002da37540 R12: ffff88002da01a02
> [  579.783066] R13: ffff88002da01a80 R14: ffff88002d83c000 R15: ffff88002d82a000
> [  579.783177] FS:  0000000000000000(0000) GS:ffff88007b000000(0063) knlGS:00000000f62d1b70
> [  579.783306] CS:  0010 DS: 002b ES: 002b CR0: 000000008005003b
> [  579.783395] CR2: 0000000000000004 CR3: 00000000218fe000 CR4: 00000000000027f0
> [  579.783505] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [  579.783684] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> [  579.783795] Process qemu (pid: 4644, threadinfo ffff880021b20000, task ffff880021aba760)
> [  579.783919] Stack:
> [  579.783959]  ffff88007693cedc ffff8800762ead00 ffff88002da01a02 ffff8800762ead00
> [  579.784110]  ffff88002da01a02 ffff88002da01a80 ffff88007b003b18 ffffffff817b26c7
> [  579.784260]  ffff880080000000 ffffffff81ef59f0 ffff8800762ead00 ffffffff81ef58b0
> [  579.784477] Call Trace:
> [  579.784523]  <IRQ> 
> [  579.784562] 
> [  579.784603]  [<ffffffff817b26c7>] br_nf_forward_ip+0x275/0x2c8
> [  579.784707]  [<ffffffff81704b58>] nf_iterate+0x47/0x7d
> [  579.784797]  [<ffffffff817ac32e>] ? br_dev_queue_push_xmit+0xae/0xae
> [  579.784906]  [<ffffffff81704bfb>] nf_hook_slow+0x6d/0x102
> [  579.784995]  [<ffffffff817ac32e>] ? br_dev_queue_push_xmit+0xae/0xae
> [  579.785175]  [<ffffffff8187fa95>] ? _raw_write_unlock_bh+0x19/0x1b
> [  579.785179]  [<ffffffff817ac417>] __br_forward+0x97/0xa2
> [  579.785179]  [<ffffffff817ad366>] br_handle_frame_finish+0x1a6/0x257
> [  579.785179]  [<ffffffff817b2386>] br_nf_pre_routing_finish+0x26d/0x2cb
> [  579.785179]  [<ffffffff817b2cf0>] br_nf_pre_routing+0x55d/0x5c1
> [  579.785179]  [<ffffffff81704b58>] nf_iterate+0x47/0x7d
> [  579.785179]  [<ffffffff817ad1c0>] ? br_handle_local_finish+0x44/0x44
> [  579.785179]  [<ffffffff81704bfb>] nf_hook_slow+0x6d/0x102
> [  579.785179]  [<ffffffff817ad1c0>] ? br_handle_local_finish+0x44/0x44
> [  579.785179]  [<ffffffff81551525>] ? sky2_poll+0xb35/0xb54
> [  579.785179]  [<ffffffff817ad62a>] br_handle_frame+0x213/0x229
> [  579.785179]  [<ffffffff817ad417>] ? br_handle_frame_finish+0x257/0x257
> [  579.785179]  [<ffffffff816e3b47>] __netif_receive_skb+0x2b4/0x3f1
> [  579.785179]  [<ffffffff816e69fc>] process_backlog+0x99/0x1e2
> [  579.785179]  [<ffffffff816e6800>] net_rx_action+0xdf/0x242
> [  579.785179]  [<ffffffff8107e8a8>] __do_softirq+0xc1/0x1e0
> [  579.785179]  [<ffffffff8135a5ba>] ? trace_hardirqs_off_thunk+0x3a/0x6c
> [  579.785179]  [<ffffffff8188812c>] call_softirq+0x1c/0x30
> 
> Signed-off-by: Lin Ming <mlin@ss.pku.edu.cn>
> ---
>  net/bridge/br_netfilter.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
> index e41456b..10da415 100644
> --- a/net/bridge/br_netfilter.c
> +++ b/net/bridge/br_netfilter.c
> @@ -719,7 +719,7 @@ static int br_nf_forward_finish(struct sk_buff *skb)
>  	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
>  	struct net_device *in;
>  
> -	if (!IS_ARP(skb) && !IS_VLAN_ARP(skb)) {
> +	if (!IS_ARP(skb) && !IS_VLAN_ARP(skb) && nf_bridge) {
>  		in = nf_bridge->physindev;
>  		if (nf_bridge->mask & BRNF_PKT_TYPE) {
>  			skb->pkt_type = PACKET_OTHERHOST;
> -- 
> 1.7.2.5

Regards

--
Julian Anastasov <ja@ssi.bg>

^ permalink raw reply

* Re: [PATCH] smsc95xx: support ethtool get_regs
From: Francois Romieu @ 2012-07-06 20:01 UTC (permalink / raw)
  To: Émeric Vigier
  Cc: Steve Glendinning, steve glendinning, netdev, Nancy Lin
In-Reply-To: <1847398984.224080.1341598531284.JavaMail.root@mail.savoirfairelinux.com>

Émeric Vigier <emeric.vigier@savoirfairelinux.com> :
[...]
> +static int smsc95xx_ethtool_getregslen(struct net_device *dev)
> +{
> +	/* all smsc95xx registers plus all phy registers */
> +	return COE_CR - ID_REV + 1 + 32 * sizeof(u32);

I do not see where ID_REV is accounted for in the loops below.

s/32 */PHY_SPECIAL */ or s/PHY_SPECIAL/32/ below.

I thought PHY registers were 16 bits wide. Moreover they are already
available through smsc95xx_ioctl().

> +}
> +
> +static void
> +smsc95xx_ethtool_getregs(struct net_device *netdev, struct ethtool_regs *regs,
> +			 void *buf)
> +{
> +	struct usbnet *dev = netdev_priv(netdev);
> +	unsigned int i, j = 0, retval;

	unsigned int i, j, retval;

> +	u32 *data = buf;
> +
> +	netif_dbg(dev, hw, dev->net, "ethtool_getregs\n");

The tracing framework does provide almost the same information.

> +
> +	retval = smsc95xx_read_reg(dev, ID_REV, &regs->version);
> +	if (retval < 0) {
> +		netdev_warn(dev->net, "REGS: cannot read ID_REV\n");

s/dev->net/netdev/ ?


> +		return;
> +	}
> +
> +	for (i = 0; i <= COE_CR; i += (sizeof(u32))) {
> +		retval = smsc95xx_read_reg(dev, i, &data[j++]);

	for (i = 0, j = 0; i <= COE_CR; i += sizeof(u32), j++) {
		retval = smsc95xx_read_reg(dev, i, data + j);

-- 
Ueimor

^ permalink raw reply

* [PATCH 4/4] net: add context callback parameter to phy connect
From: s-paulraj @ 2012-07-06 20:10 UTC (permalink / raw)
  To: netdev, davem, cyril, grant.likely, linux-keystone; +Cc: Sandeep Paulraj

From: Sandeep Paulraj <s-paulraj@ti.com>

This patch introduces a context argument for the adjust link callback in all
drivers that currently use the phy_connect() and it variants.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
---
 drivers/net/ethernet/8390/ax88796.c                |    4 ++--
 drivers/net/ethernet/adi/bfin_mac.c                |    4 ++--
 drivers/net/ethernet/aeroflex/greth.c              |    7 ++++---
 drivers/net/ethernet/amd/au1000_eth.c              |    4 ++--
 drivers/net/ethernet/broadcom/bcm63xx_enet.c       |    4 ++--
 drivers/net/ethernet/broadcom/sb1250-mac.c         |    6 +++---
 drivers/net/ethernet/broadcom/tg3.c                |    4 ++--
 drivers/net/ethernet/cadence/macb.c                |    4 ++--
 drivers/net/ethernet/dnet.c                        |    6 +++---
 drivers/net/ethernet/ethoc.c                       |    4 ++--
 drivers/net/ethernet/faraday/ftgmac100.c           |    4 ++--
 drivers/net/ethernet/freescale/fec.c               |    4 ++--
 drivers/net/ethernet/freescale/fec_mpc52xx.c       |    5 +++--
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |    6 +++---
 drivers/net/ethernet/freescale/gianfar.c           |    8 ++++----
 drivers/net/ethernet/freescale/ucc_geth.c          |    6 +++---
 drivers/net/ethernet/lantiq_etop.c                 |    4 ++--
 drivers/net/ethernet/nxp/lpc_eth.c                 |    5 +++--
 drivers/net/ethernet/octeon/octeon_mgmt.c          |    4 ++--
 drivers/net/ethernet/pasemi/pasemi_mac.c           |    4 ++--
 drivers/net/ethernet/rdc/r6040.c                   |    4 ++--
 drivers/net/ethernet/renesas/sh_eth.c              |    4 ++--
 drivers/net/ethernet/s6gmac.c                      |    4 ++--
 drivers/net/ethernet/smsc/smsc911x.c               |    4 ++--
 drivers/net/ethernet/smsc/smsc9420.c               |    5 +++--
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |    6 ++++--
 drivers/net/ethernet/ti/cpmac.c                    |    4 ++--
 drivers/net/ethernet/ti/cpsw.c                     |    5 +++--
 drivers/net/ethernet/ti/davinci_emac.c             |    4 ++--
 drivers/net/ethernet/toshiba/tc35815.c             |    5 +++--
 drivers/net/ethernet/xilinx/ll_temac_main.c        |    4 ++--
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c  |    3 ++-
 drivers/net/ethernet/xilinx/xilinx_emaclite.c      |    5 +++--
 drivers/net/ethernet/xscale/ixp4xx_eth.c           |    4 ++--
 34 files changed, 84 insertions(+), 74 deletions(-)

diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index 203ff9d..ef02795 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -317,7 +317,7 @@ static void ax_block_output(struct net_device *dev, int count,
 #define AX_MEMR_EEO		BIT(6)
 #define AX_MEMR_EECLK		BIT(7)
 
-static void ax_handle_link_change(struct net_device *dev)
+static void ax_handle_link_change(struct net_device *dev, void *context)
 {
 	struct ax_device  *ax = to_ax_dev(dev);
 	struct phy_device *phy_dev = ax->phy_dev;
@@ -359,7 +359,7 @@ static int ax_mii_probe(struct net_device *dev)
 	}
 
 	ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change, 0,
-				 PHY_INTERFACE_MODE_MII);
+				 PHY_INTERFACE_MODE_MII, NULL);
 	if (ret) {
 		netdev_err(dev, "Could not attach to PHY\n");
 		return ret;
diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index f816426..55d1f99 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -313,7 +313,7 @@ static int bfin_mdiobus_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static void bfin_mac_adjust_link(struct net_device *dev)
+static void bfin_mac_adjust_link(struct net_device *dev, void *context)
 {
 	struct bfin_mac_local *lp = netdev_priv(dev);
 	struct phy_device *phydev = lp->phydev;
@@ -426,7 +426,7 @@ static int mii_probe(struct net_device *dev, int phy_mode)
 	}
 
 	phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
-			0, phy_mode);
+			0, phy_mode, NULL);
 
 	if (IS_ERR(phydev)) {
 		netdev_err(dev, "could not attach PHY\n");
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 3485011..3b803f2 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -1218,7 +1218,7 @@ static int greth_mdio_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static void greth_link_change(struct net_device *dev)
+static void greth_link_change(struct net_device *dev, void *context)
 {
 	struct greth_private *greth = netdev_priv(dev);
 	struct phy_device *phydev = greth->phy;
@@ -1289,7 +1289,8 @@ static int greth_mdio_probe(struct net_device *dev)
 	ret = phy_connect_direct(dev, phy, &greth_link_change,
 			0, greth->gbit_mac ?
 			PHY_INTERFACE_MODE_GMII :
-			PHY_INTERFACE_MODE_MII);
+			PHY_INTERFACE_MODE_MII.
+			NULL);
 	if (ret) {
 		if (netif_msg_ifup(greth))
 			dev_err(&dev->dev, "could not attach to PHY\n");
@@ -1363,7 +1364,7 @@ static int greth_mdio_init(struct greth_private *greth)
 		while (!phy_aneg_done(greth->phy) && time_before(jiffies, timeout)) {
 		}
 		genphy_read_status(greth->phy);
-		greth_link_change(greth->netdev);
+		greth_link_change(greth->netdev, NULL);
 	}
 
 	return 0;
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index 397596b..ed7e60a 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -292,7 +292,7 @@ static void au1000_enable_rx_tx(struct net_device *dev)
 }
 
 static void
-au1000_adjust_link(struct net_device *dev)
+au1000_adjust_link(struct net_device *dev, void *context)
 {
 	struct au1000_private *aup = netdev_priv(dev);
 	struct phy_device *phydev = aup->phy_dev;
@@ -438,7 +438,7 @@ static int au1000_mii_probe(struct net_device *dev)
 	BUG_ON(phydev->attached_dev);
 
 	phydev = phy_connect(dev, dev_name(&phydev->dev), &au1000_adjust_link,
-			0, PHY_INTERFACE_MODE_MII);
+			0, PHY_INTERFACE_MODE_MII, NULL);
 
 	if (IS_ERR(phydev)) {
 		netdev_err(dev, "Could not attach to PHY\n");
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index c7ca7ec..84b7033 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -698,7 +698,7 @@ static void bcm_enet_set_flow(struct bcm_enet_priv *priv, int rx_en, int tx_en)
 /*
  * link changed callback (from phylib)
  */
-static void bcm_enet_adjust_phy_link(struct net_device *dev)
+static void bcm_enet_adjust_phy_link(struct net_device *dev, void *context)
 {
 	struct bcm_enet_priv *priv;
 	struct phy_device *phydev;
@@ -800,7 +800,7 @@ static int bcm_enet_open(struct net_device *dev)
 			 priv->mii_bus->id, priv->phy_id);
 
 		phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0,
-				     PHY_INTERFACE_MODE_MII);
+				     PHY_INTERFACE_MODE_MII, NULL);
 
 		if (IS_ERR(phydev)) {
 			dev_err(kdev, "could not attach to PHY\n");
diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c
index 49e7a25..58155d3 100644
--- a/drivers/net/ethernet/broadcom/sb1250-mac.c
+++ b/drivers/net/ethernet/broadcom/sb1250-mac.c
@@ -316,7 +316,7 @@ static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int sbmac_close(struct net_device *dev);
 static int sbmac_poll(struct napi_struct *napi, int budget);
 
-static void sbmac_mii_poll(struct net_device *dev);
+static void sbmac_mii_poll(struct net_device *dev, void *context);
 static int sbmac_mii_probe(struct net_device *dev);
 
 static void sbmac_mii_sync(void __iomem *sbm_mdio);
@@ -2386,7 +2386,7 @@ static int sbmac_mii_probe(struct net_device *dev)
 	}
 
 	phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 0,
-			      PHY_INTERFACE_MODE_GMII);
+			      PHY_INTERFACE_MODE_GMII, NULL);
 	if (IS_ERR(phy_dev)) {
 		printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
 		return PTR_ERR(phy_dev);
@@ -2415,7 +2415,7 @@ static int sbmac_mii_probe(struct net_device *dev)
 }
 
 
-static void sbmac_mii_poll(struct net_device *dev)
+static void sbmac_mii_poll(struct net_device *dev, void *context)
 {
 	struct sbmac_softc *sc = netdev_priv(dev);
 	struct phy_device *phy_dev = sc->phy_dev;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index e47ff8b..2130a76 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -1756,7 +1756,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
 		tw32_f(MAC_TX_MODE, tp->tx_mode);
 }
 
-static void tg3_adjust_link(struct net_device *dev)
+static void tg3_adjust_link(struct net_device *dev, void *context)
 {
 	u8 oldflowctrl, linkmesg = 0;
 	u32 mac_mode, lcl_adv, rmt_adv;
@@ -1854,7 +1854,7 @@ static int tg3_phy_init(struct tg3 *tp)
 
 	/* Attach the MAC to the PHY. */
 	phydev = phy_connect(tp->dev, dev_name(&phydev->dev), tg3_adjust_link,
-			     phydev->dev_flags, phydev->interface);
+			     phydev->dev_flags, phydev->interface, NULL);
 	if (IS_ERR(phydev)) {
 		dev_err(&tp->pdev->dev, "Could not attach to PHY\n");
 		return PTR_ERR(phydev);
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 1466bc4..943833c 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -135,7 +135,7 @@ static int macb_mdio_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static void macb_handle_link_change(struct net_device *dev)
+static void macb_handle_link_change(struct net_device *dev, void *context)
 {
 	struct macb *bp = netdev_priv(dev);
 	struct phy_device *phydev = bp->phy_dev;
@@ -206,7 +206,7 @@ static int macb_mii_probe(struct net_device *dev)
 
 	/* attach the mac to the phy */
 	ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0,
-				 bp->phy_interface);
+				 bp->phy_interface, NULL);
 	if (ret) {
 		netdev_err(dev, "Could not attach to PHY\n");
 		return ret;
diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c
index 290b26f..68bc305 100644
--- a/drivers/net/ethernet/dnet.c
+++ b/drivers/net/ethernet/dnet.c
@@ -176,7 +176,7 @@ static int dnet_mdio_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static void dnet_handle_link_change(struct net_device *dev)
+static void dnet_handle_link_change(struct net_device *dev, void *context)
 {
 	struct dnet *bp = netdev_priv(dev);
 	struct phy_device *phydev = bp->phy_dev;
@@ -282,11 +282,11 @@ static int dnet_mii_probe(struct net_device *dev)
 	if (bp->capabilities & DNET_HAS_RMII) {
 		phydev = phy_connect(dev, dev_name(&phydev->dev),
 				     &dnet_handle_link_change, 0,
-				     PHY_INTERFACE_MODE_RMII);
+				     PHY_INTERFACE_MODE_RMII, NULL);
 	} else {
 		phydev = phy_connect(dev, dev_name(&phydev->dev),
 				     &dnet_handle_link_change, 0,
-				     PHY_INTERFACE_MODE_MII);
+				     PHY_INTERFACE_MODE_MII, NULL);
 	}
 
 	if (IS_ERR(phydev)) {
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index a381678..dd33a50 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -661,7 +661,7 @@ static int ethoc_mdio_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static void ethoc_mdio_poll(struct net_device *dev)
+static void ethoc_mdio_poll(struct net_device *dev, void *context)
 {
 }
 
@@ -683,7 +683,7 @@ static int __devinit ethoc_mdio_probe(struct net_device *dev)
 	}
 
 	err = phy_connect_direct(dev, phy, ethoc_mdio_poll, 0,
-			PHY_INTERFACE_MODE_GMII);
+			PHY_INTERFACE_MODE_GMII, NULL);
 	if (err) {
 		dev_err(&dev->dev, "could not attach to PHY\n");
 		return err;
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 16b0704..79c5502 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -803,7 +803,7 @@ err:
 /******************************************************************************
  * internal functions (mdio)
  *****************************************************************************/
-static void ftgmac100_adjust_link(struct net_device *netdev)
+static void ftgmac100_adjust_link(struct net_device *netdev, void *context)
 {
 	struct ftgmac100 *priv = netdev_priv(netdev);
 	struct phy_device *phydev = priv->phydev;
@@ -854,7 +854,7 @@ static int ftgmac100_mii_probe(struct ftgmac100 *priv)
 
 	phydev = phy_connect(netdev, dev_name(&phydev->dev),
 			     &ftgmac100_adjust_link, 0,
-			     PHY_INTERFACE_MODE_GMII);
+			     PHY_INTERFACE_MODE_GMII, NULL);
 
 	if (IS_ERR(phydev)) {
 		netdev_err(netdev, "%s: Could not attach to PHY\n", netdev->name);
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index ff7f4c5..b0b5adc 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -856,7 +856,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
 /*
  * Phy section
  */
-static void fec_enet_adjust_link(struct net_device *ndev)
+static void fec_enet_adjust_link(struct net_device *ndev, void *context)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phy_dev = fep->phy_dev;
@@ -994,7 +994,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
 
 	snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);
 	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
-			      fep->phy_interface);
+			      fep->phy_interface, NULL);
 	if (IS_ERR(phy_dev)) {
 		printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
 		return PTR_ERR(phy_dev);
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c
index 2933d08..800b7fb 100644
--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c
+++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c
@@ -172,7 +172,7 @@ static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task
 }
 
 /* based on generic_adjust_link from fs_enet-main.c */
-static void mpc52xx_fec_adjust_link(struct net_device *dev)
+static void mpc52xx_fec_adjust_link(struct net_device *dev, void *context)
 {
 	struct mpc52xx_fec_priv *priv = netdev_priv(dev);
 	struct phy_device *phydev = priv->phydev;
@@ -229,7 +229,8 @@ static int mpc52xx_fec_open(struct net_device *dev)
 
 	if (priv->phy_node) {
 		priv->phydev = of_phy_connect(priv->ndev, priv->phy_node,
-					      mpc52xx_fec_adjust_link, 0, 0);
+					      mpc52xx_fec_adjust_link,
+					      0, 0, NULL);
 		if (!priv->phydev) {
 			dev_err(&dev->dev, "of_phy_connect failed\n");
 			return -ENODEV;
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 2b7633f..82a1dcd 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -771,7 +771,7 @@ static void generic_adjust_link(struct  net_device *dev)
 }
 
 
-static void fs_adjust_link(struct net_device *dev)
+static void fs_adjust_link(struct net_device *dev, void *context)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
 	unsigned long flags;
@@ -800,10 +800,10 @@ static int fs_init_phy(struct net_device *dev)
 		PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII;
 
 	phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0,
-				iface);
+				iface, NULL);
 	if (!phydev) {
 		phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link,
-						   iface);
+						   iface, NULL);
 	}
 	if (!phydev) {
 		dev_err(&dev->dev, "Could not attach to PHY\n");
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index f2db8fc..4d3324a 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -120,7 +120,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu);
 static irqreturn_t gfar_error(int irq, void *dev_id);
 static irqreturn_t gfar_transmit(int irq, void *dev_id);
 static irqreturn_t gfar_interrupt(int irq, void *dev_id);
-static void adjust_link(struct net_device *dev);
+static void adjust_link(struct net_device *dev, void *context);
 static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
 static int gfar_probe(struct platform_device *ofdev);
@@ -1434,10 +1434,10 @@ static int init_phy(struct net_device *dev)
 	interface = gfar_get_interface(dev);
 
 	priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0,
-				      interface);
+				      interface, NULL);
 	if (!priv->phydev)
 		priv->phydev = of_phy_connect_fixed_link(dev, &adjust_link,
-							 interface);
+							 interface, NULL);
 	if (!priv->phydev) {
 		dev_err(&dev->dev, "could not attach to PHY\n");
 		return -ENODEV;
@@ -2939,7 +2939,7 @@ static irqreturn_t gfar_interrupt(int irq, void *grp_id)
  * function converts those variables into the appropriate
  * register values, and can bring down the device if needed.
  */
-static void adjust_link(struct net_device *dev)
+static void adjust_link(struct net_device *dev, void *context)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar __iomem *regs = priv->gfargrp[0].regs;
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index 9ac14f8..7c79cb5 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -1598,7 +1598,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth)
  * register values, and can bring down the device if needed.
  */
 
-static void adjust_link(struct net_device *dev)
+static void adjust_link(struct net_device *dev, void *context)
 {
 	struct ucc_geth_private *ugeth = netdev_priv(dev);
 	struct ucc_geth __iomem *ug_regs;
@@ -1749,10 +1749,10 @@ static int init_phy(struct net_device *dev)
 	priv->oldduplex = -1;
 
 	phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0,
-				priv->phy_interface);
+				priv->phy_interface, NULL);
 	if (!phydev)
 		phydev = of_phy_connect_fixed_link(dev, &adjust_link,
-						   priv->phy_interface);
+						   priv->phy_interface, NULL);
 	if (!phydev) {
 		dev_err(&dev->dev, "Could not attach to PHY\n");
 		return -ENODEV;
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 5dc9cbd..07bca02 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -370,7 +370,7 @@ ltq_etop_mdio_rd(struct mii_bus *bus, int phy_addr, int phy_reg)
 }
 
 static void
-ltq_etop_mdio_link(struct net_device *dev)
+ltq_etop_mdio_link(struct net_device *dev, void *context)
 {
 	/* nothing to do  */
 }
@@ -395,7 +395,7 @@ ltq_etop_mdio_probe(struct net_device *dev)
 	}
 
 	phydev = phy_connect(dev, dev_name(&phydev->dev), &ltq_etop_mdio_link,
-			0, priv->pldata->mii_mode);
+			0, priv->pldata->mii_mode, NULL);
 
 	if (IS_ERR(phydev)) {
 		netdev_err(dev, "Could not attach to PHY\n");
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index 083d671..ed37ead 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -767,7 +767,7 @@ static int lpc_mdio_reset(struct mii_bus *bus)
 	return __lpc_mii_mngt_reset((struct netdata_local *)bus->priv);
 }
 
-static void lpc_handle_link_change(struct net_device *ndev)
+static void lpc_handle_link_change(struct net_device *ndev, void *context)
 {
 	struct netdata_local *pldat = netdev_priv(ndev);
 	struct phy_device *phydev = pldat->phy_dev;
@@ -819,7 +819,8 @@ static int lpc_mii_probe(struct net_device *ndev)
 		netdev_info(ndev, "using RMII interface\n");
 	phydev = phy_connect(ndev, dev_name(&phydev->dev),
 			     &lpc_handle_link_change, 0,
-			     lpc_phy_interface_mode(&pldat->pdev->dev));
+			     lpc_phy_interface_mode(&pldat->pdev->dev),
+			     NULL);
 
 	if (IS_ERR(phydev)) {
 		netdev_err(ndev, "Could not attach to PHY\n");
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index cd827ff..9fdca60 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -626,7 +626,7 @@ static int octeon_mgmt_ioctl(struct net_device *netdev,
 	return phy_mii_ioctl(p->phydev, rq, cmd);
 }
 
-static void octeon_mgmt_adjust_link(struct net_device *netdev)
+static void octeon_mgmt_adjust_link(struct net_device *netdev, void *context)
 {
 	struct octeon_mgmt *p = netdev_priv(netdev);
 	int port = p->port;
@@ -681,7 +681,7 @@ static int octeon_mgmt_init_phy(struct net_device *netdev)
 	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", p->port);
 
 	p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0,
-				PHY_INTERFACE_MODE_MII);
+				PHY_INTERFACE_MODE_MII, NULL);
 
 	if (IS_ERR(p->phydev)) {
 		p->phydev = NULL;
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index e559dfa..9aba6b4 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1021,7 +1021,7 @@ static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static void pasemi_adjust_link(struct net_device *dev)
+static void pasemi_adjust_link(struct net_device *dev, void *context)
 {
 	struct pasemi_mac *mac = netdev_priv(dev);
 	int msg;
@@ -1099,7 +1099,7 @@ static int pasemi_mac_phy_init(struct net_device *dev)
 	mac->duplex = -1;
 
 	phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0,
-				PHY_INTERFACE_MODE_SGMII);
+				PHY_INTERFACE_MODE_SGMII, NULL);
 
 	if (IS_ERR(phydev)) {
 		printk(KERN_ERR "%s: Could not attach to phy\n", dev->name);
diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c
index d1827e8..c2f3e53 100644
--- a/drivers/net/ethernet/rdc/r6040.c
+++ b/drivers/net/ethernet/rdc/r6040.c
@@ -1000,7 +1000,7 @@ static const struct net_device_ops r6040_netdev_ops = {
 #endif
 };
 
-static void r6040_adjust_link(struct net_device *dev)
+static void r6040_adjust_link(struct net_device *dev, void *context)
 {
 	struct r6040_private *lp = netdev_priv(dev);
 	struct phy_device *phydev = lp->phydev;
@@ -1045,7 +1045,7 @@ static int r6040_mii_probe(struct net_device *dev)
 	}
 
 	phydev = phy_connect(dev, dev_name(&phydev->dev), &r6040_adjust_link,
-				0, PHY_INTERFACE_MODE_MII);
+				0, PHY_INTERFACE_MODE_MII, NULL);
 
 	if (IS_ERR(phydev)) {
 		dev_err(&lp->pdev->dev, "could not attach to PHY\n");
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 79bf09b..eb089e6 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1302,7 +1302,7 @@ static void sh_eth_timer(unsigned long data)
 }
 
 /* PHY state control function */
-static void sh_eth_adjust_link(struct net_device *ndev)
+static void sh_eth_adjust_link(struct net_device *ndev, void *context)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	struct phy_device *phydev = mdp->phydev;
@@ -1355,7 +1355,7 @@ static int sh_eth_phy_init(struct net_device *ndev)
 
 	/* Try connect to PHY */
 	phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
-				0, mdp->phy_interface);
+				0, mdp->phy_interface, NULL);
 	if (IS_ERR(phydev)) {
 		dev_err(&ndev->dev, "phy_connect failed\n");
 		return PTR_ERR(phydev);
diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c
index 2ed3ab4..d882267 100644
--- a/drivers/net/ethernet/s6gmac.c
+++ b/drivers/net/ethernet/s6gmac.c
@@ -739,7 +739,7 @@ static inline void s6gmac_linkisup(struct net_device *dev, int isup)
 	phy_print_status(phydev);
 }
 
-static void s6gmac_adjust_link(struct net_device *dev)
+static void s6gmac_adjust_link(struct net_device *dev, void *context)
 {
 	struct s6gmac *pd = netdev_priv(dev);
 	struct phy_device *phydev = pd->phydev;
@@ -796,7 +796,7 @@ static inline int s6gmac_phy_start(struct net_device *dev)
 	while ((i < PHY_MAX_ADDR) && (!(p = pd->mii.bus->phy_map[i])))
 		i++;
 	p = phy_connect(dev, dev_name(&p->dev), &s6gmac_adjust_link, 0,
-			PHY_INTERFACE_MODE_RGMII);
+			PHY_INTERFACE_MODE_RGMII, NULL);
 	if (IS_ERR(p)) {
 		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
 		return PTR_ERR(p);
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 1466e5d..1221e242 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -916,7 +916,7 @@ static void smsc911x_phy_update_flowcontrol(struct smsc911x_data *pdata)
 
 /* Update link mode if anything has changed.  Called periodically when the
  * PHY is in polling mode, even if nothing has changed. */
-static void smsc911x_phy_adjust_link(struct net_device *dev)
+static void smsc911x_phy_adjust_link(struct net_device *dev, void *context)
 {
 	struct smsc911x_data *pdata = netdev_priv(dev);
 	struct phy_device *phy_dev = pdata->phy_dev;
@@ -999,7 +999,7 @@ static int smsc911x_mii_probe(struct net_device *dev)
 
 	ret = phy_connect_direct(dev, phydev,
 			&smsc911x_phy_adjust_link, 0,
-			pdata->config.phy_interface);
+			pdata->config.phy_interface, NULL);
 
 	if (ret) {
 		netdev_err(dev, "Could not attach to PHY\n");
diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c
index fd33b21..40e727b 100644
--- a/drivers/net/ethernet/smsc/smsc9420.c
+++ b/drivers/net/ethernet/smsc/smsc9420.c
@@ -1130,7 +1130,7 @@ static void smsc9420_phy_update_flowcontrol(struct smsc9420_pdata *pd)
 
 /* Update link mode if anything has changed.  Called periodically when the
  * PHY is in polling mode, even if nothing has changed. */
-static void smsc9420_phy_adjust_link(struct net_device *dev)
+static void smsc9420_phy_adjust_link(struct net_device *dev, void *context)
 {
 	struct smsc9420_pdata *pd = netdev_priv(dev);
 	struct phy_device *phy_dev = pd->phy_dev;
@@ -1179,7 +1179,8 @@ static int smsc9420_mii_probe(struct net_device *dev)
 		phydev->phy_id);
 
 	phydev = phy_connect(dev, dev_name(&phydev->dev),
-		smsc9420_phy_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+				smsc9420_phy_adjust_link, 0,
+				PHY_INTERFACE_MODE_MII, NULL);
 
 	if (IS_ERR(phydev)) {
 		pr_err("%s: Could not attach to PHY\n", dev->name);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 51b3b68..431f9b0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -232,9 +232,10 @@ static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
 /**
  * stmmac_adjust_link
  * @dev: net device structure
+ * @context: context callback structure
  * Description: it adjusts the link parameters.
  */
-static void stmmac_adjust_link(struct net_device *dev)
+static void stmmac_adjust_link(struct net_device *dev, void *context)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 	struct phy_device *phydev = priv->phydev;
@@ -350,7 +351,8 @@ static int stmmac_init_phy(struct net_device *dev)
 		 priv->plat->phy_addr);
 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id);
 
-	phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, interface);
+	phydev = phy_connect(dev, phy_id, &stmmac_adjust_link,
+			     0, interface, NULL);
 
 	if (IS_ERR(phydev)) {
 		pr_err("%s: Could not attach to PHY\n", dev->name);
diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c
index 860c252..f2cddc1 100644
--- a/drivers/net/ethernet/ti/cpmac.c
+++ b/drivers/net/ethernet/ti/cpmac.c
@@ -920,7 +920,7 @@ static const struct ethtool_ops cpmac_ethtool_ops = {
 	.set_ringparam = cpmac_set_ringparam,
 };
 
-static void cpmac_adjust_link(struct net_device *dev)
+static void cpmac_adjust_link(struct net_device *dev, void *context)
 {
 	struct cpmac_priv *priv = netdev_priv(dev);
 	int new_state = 0;
@@ -1174,7 +1174,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
 						mdio_bus_id, phy_id);
 
 	priv->phy = phy_connect(dev, priv->phy_name, cpmac_adjust_link, 0,
-						PHY_INTERFACE_MODE_MII);
+				PHY_INTERFACE_MODE_MII, NULL);
 
 	if (IS_ERR(priv->phy)) {
 		if (netif_msg_drv(priv))
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 6685bbb..5c97725 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -398,7 +398,7 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
 	slave->mac_control = mac_control;
 }
 
-static void cpsw_adjust_link(struct net_device *ndev)
+static void cpsw_adjust_link(struct net_device *ndev, void *context)
 {
 	struct cpsw_priv	*priv = netdev_priv(ndev);
 	bool			link = false;
@@ -451,7 +451,8 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 			   1 << slave_port, 0, ALE_MCAST_FWD_2);
 
 	slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
-				 &cpsw_adjust_link, 0, slave->data->phy_if);
+				 &cpsw_adjust_link, 0,
+				 slave->data->phy_if, NULL);
 	if (IS_ERR(slave->phy)) {
 		dev_err(priv->dev, "phy %s not found on slave %d\n",
 			slave->data->phy_id, slave->slave_num);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 4da93a5..a902a2d 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1446,7 +1446,7 @@ void emac_poll_controller(struct net_device *ndev)
 }
 #endif
 
-static void emac_adjust_link(struct net_device *ndev)
+static void emac_adjust_link(struct net_device *ndev, void *context)
 {
 	struct emac_priv *priv = netdev_priv(ndev);
 	struct phy_device *phydev = priv->phydev;
@@ -1597,7 +1597,7 @@ static int emac_dev_open(struct net_device *ndev)
 	if (priv->phy_id && *priv->phy_id) {
 		priv->phydev = phy_connect(ndev, priv->phy_id,
 					   &emac_adjust_link, 0,
-					   PHY_INTERFACE_MODE_MII);
+					   PHY_INTERFACE_MODE_MII, NULL);
 
 		if (IS_ERR(priv->phydev)) {
 			dev_err(emac_dev, "could not connect to phy %s\n",
diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index 651a70c..ef21735 100644
--- a/drivers/net/ethernet/toshiba/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -537,7 +537,7 @@ static int tc_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 val)
 	return 0;
 }
 
-static void tc_handle_link_change(struct net_device *dev)
+static void tc_handle_link_change(struct net_device *dev, void *context)
 {
 	struct tc35815_local *lp = netdev_priv(dev);
 	struct phy_device *phydev = lp->phy_dev;
@@ -635,7 +635,8 @@ static int tc_mii_probe(struct net_device *dev)
 	phydev = phy_connect(dev, dev_name(&phydev->dev),
 			     &tc_handle_link_change, 0,
 			     lp->chiptype == TC35815_TX4939 ?
-			     PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII);
+			     PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII,
+			     NULL);
 	if (IS_ERR(phydev)) {
 		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
 		return PTR_ERR(phydev);
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 1eaf712..97e2d77 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -590,7 +590,7 @@ static void temac_device_reset(struct net_device *ndev)
 	ndev->trans_start = jiffies; /* prevent tx timeout */
 }
 
-void temac_adjust_link(struct net_device *ndev)
+void temac_adjust_link(struct net_device *ndev, void *context)
 {
 	struct temac_local *lp = netdev_priv(ndev);
 	struct phy_device *phy = lp->phy_dev;
@@ -857,7 +857,7 @@ static int temac_open(struct net_device *ndev)
 
 	if (lp->phy_node) {
 		lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
-					     temac_adjust_link, 0, 0);
+					     temac_adjust_link, 0, 0, NULL);
 		if (!lp->phy_dev) {
 			dev_err(lp->dev, "of_phy_connect() failed\n");
 			return -ENODEV;
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 9c365e1..d69ae3c 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -522,6 +522,7 @@ static void axienet_device_reset(struct net_device *ndev)
 /**
  * axienet_adjust_link - Adjust the PHY link speed/duplex.
  * @ndev:	Pointer to the net_device structure
+ * @context:    Pointer to the context argument
  *
  * This function is called to change the speed and duplex setting after
  * auto negotiation is done by the PHY. This is the function that gets
@@ -934,7 +935,7 @@ static int axienet_open(struct net_device *ndev)
 	if (lp->phy_node) {
 		lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
 					     axienet_adjust_link, 0,
-					     PHY_INTERFACE_MODE_GMII);
+					     PHY_INTERFACE_MODE_GMII, NULL);
 		if (!lp->phy_dev) {
 			dev_err(lp->dev, "of_phy_connect() failed\n");
 			return -ENODEV;
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 77cfe51..eb641aa 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -892,11 +892,12 @@ err_register:
 /**
  * xemaclite_adjust_link - Link state callback for the Emaclite device
  * @ndev: pointer to net_device struct
+ * @context: pointer to context argument
  *
  * There's nothing in the Emaclite device to be configured when the link
  * state changes. We just print the status.
  */
-void xemaclite_adjust_link(struct net_device *ndev)
+void xemaclite_adjust_link(struct net_device *ndev, void *context)
 {
 	struct net_local *lp = netdev_priv(ndev);
 	struct phy_device *phy = lp->phy_dev;
@@ -932,7 +933,7 @@ static int xemaclite_open(struct net_device *dev)
 
 		lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
 					     xemaclite_adjust_link, 0,
-					     PHY_INTERFACE_MODE_MII);
+					     PHY_INTERFACE_MODE_MII, NULL);
 		if (!lp->phy_dev) {
 			dev_err(&lp->ndev->dev, "of_phy_connect() failed\n");
 			return -ENODEV;
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index 482648f..5c39324 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -543,7 +543,7 @@ static void ixp4xx_mdio_remove(void)
 }
 
 
-static void ixp4xx_adjust_link(struct net_device *dev)
+static void ixp4xx_adjust_link(struct net_device *dev, void *context)
 {
 	struct port *port = netdev_priv(dev);
 	struct phy_device *phydev = port->phydev;
@@ -1448,7 +1448,7 @@ static int __devinit eth_init_one(struct platform_device *pdev)
 	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
 		mdio_bus->id, plat->phy);
 	port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
-				   PHY_INTERFACE_MODE_MII);
+				   PHY_INTERFACE_MODE_MII, NULL);
 	if (IS_ERR(port->phydev)) {
 		err = PTR_ERR(port->phydev);
 		goto err_free_mem;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 3/4] of/mdio: add context argument to adjust link callback
From: s-paulraj @ 2012-07-06 20:09 UTC (permalink / raw)
  To: netdev, davem, cyril, grant.likely, linux-keystone; +Cc: Sandeep Paulraj

From: Sandeep Paulraj <s-paulraj@ti.com>

This patch implements extensions to device-tree phy interfaces in order to
have context information passed back into the adjust link callbacks.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
---
 drivers/of/of_mdio.c    |   24 +++++++++++++++---------
 include/linux/of_mdio.h |   15 ++++++++-------
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 2574abd..a0a09db 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -136,20 +136,24 @@ EXPORT_SYMBOL(of_phy_find_device);
  * @phy_np: Pointer to device tree node for the PHY
  * @hndlr: Link state callback for the network device
  * @iface: PHY data interface type
+ * @context: Context for callback handler
  *
  * Returns a pointer to the phy_device if successful.  NULL otherwise
  */
-struct phy_device *of_phy_connect(struct net_device *dev,
-				  struct device_node *phy_np,
-				  void (*hndlr)(struct net_device *), u32 flags,
-				  phy_interface_t iface)
+struct phy_device *
+of_phy_connect(struct net_device *dev,
+	       struct device_node *phy_np,
+	       void (*hndlr)(struct net_device *, void *context),
+	       u32 flags, phy_interface_t iface, void *context)
 {
 	struct phy_device *phy = of_phy_find_device(phy_np);
+	int error;
 
 	if (!phy)
 		return NULL;
 
-	return phy_connect_direct(dev, phy, hndlr, flags, iface) ? NULL : phy;
+	error = phy_connect_direct(dev, phy, hndlr, flags, iface, context);
+	return error ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_connect);
 
@@ -158,14 +162,16 @@ EXPORT_SYMBOL(of_phy_connect);
  * @dev: pointer to net_device claiming the phy
  * @hndlr: Link state callback for the network device
  * @iface: PHY data interface type
+ * @context: Context for callback handler
  *
  * This function is a temporary stop-gap and will be removed soon.  It is
  * only to support the fs_enet, ucc_geth and gianfar Ethernet drivers.  Do
  * not call this function from new drivers.
  */
-struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
-					     void (*hndlr)(struct net_device *),
-					     phy_interface_t iface)
+struct phy_device *
+of_phy_connect_fixed_link(struct net_device *dev,
+			  void (*hndlr)(struct net_device *, void *context),
+			  phy_interface_t iface, void *context)
 {
 	struct device_node *net_np;
 	char bus_id[MII_BUS_ID_SIZE + 3];
@@ -186,7 +192,7 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
 
 	sprintf(bus_id, PHY_ID_FMT, "fixed-0", be32_to_cpu(phy_id[0]));
 
-	phy = phy_connect(dev, bus_id, hndlr, 0, iface);
+	phy = phy_connect(dev, bus_id, hndlr, 0, iface, context);
 	return IS_ERR(phy) ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_connect_fixed_link);
diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h
index 912c27a..d72d0c6 100644
--- a/include/linux/of_mdio.h
+++ b/include/linux/of_mdio.h
@@ -14,13 +14,14 @@
 
 extern int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np);
 extern struct phy_device *of_phy_find_device(struct device_node *phy_np);
-extern struct phy_device *of_phy_connect(struct net_device *dev,
-					 struct device_node *phy_np,
-					 void (*hndlr)(struct net_device *),
-					 u32 flags, phy_interface_t iface);
-extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
-					 void (*hndlr)(struct net_device *),
-					 phy_interface_t iface);
+extern struct phy_device *
+of_phy_connect(struct net_device *dev, struct device_node *phy_np,
+	       void (*hndlr)(struct net_device *, void *context),
+	       u32 flags, phy_interface_t iface, void *context);
+extern struct phy_device *
+of_phy_connect_fixed_link(struct net_device *dev,
+			  void (*hndlr)(struct net_device *, void *context),
+			  phy_interface_t iface, void *context);
 
 extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 2/4] phylib: add context argument to adjust link callback
From: s-paulraj @ 2012-07-06 20:09 UTC (permalink / raw)
  To: netdev, davem, cyril, grant.likely, linux-keystone; +Cc: Sandeep Paulraj

From: Sandeep Paulraj <s-paulraj@ti.com>

This patch introduces a context argument for the adjust link callback.  This
context information is set at phy_connect() (and its variants), and is passed
back into the adjust_link callbacks on link state change events.

Such context information is necessary when a network device has multiple
underlying ports.  Specifically, this comes into play when the netdev is
really one of the ports going into an on-chip switch of some sort.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
---
 drivers/net/phy/phy.c        |    6 +++---
 drivers/net/phy/phy_device.c |   23 +++++++++++++++--------
 include/linux/phy.h          |   20 ++++++++++++--------
 3 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 36ca912..491a608 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -433,7 +433,7 @@ static void phy_change(struct work_struct *work);
  *   function.
  */
 void phy_start_machine(struct phy_device *phydev,
-		void (*handler)(struct net_device *))
+		       void (*handler)(struct net_device *, void *context))
 {
 	phydev->adjust_state = handler;
 
@@ -763,7 +763,7 @@ EXPORT_SYMBOL(phy_start);
 
 static inline void phy_adjust_link(struct phy_device *phydev)
 {
-	phydev->adjust_link(phydev->attached_dev);
+	phydev->adjust_link(phydev->attached_dev, phydev->context);
 }
 
 /**
@@ -781,7 +781,7 @@ void phy_state_machine(struct work_struct *work)
 	mutex_lock(&phydev->lock);
 
 	if (phydev->adjust_state)
-		phydev->adjust_state(phydev->attached_dev);
+		phydev->adjust_state(phydev->attached_dev, phydev->context);
 
 	switch(phydev->state) {
 		case PHY_DOWN:
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index de86a55..a4e5313 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -310,6 +310,7 @@ EXPORT_SYMBOL(phy_find_first);
  * phy_prepare_link - prepares the PHY layer to monitor link status
  * @phydev: target phy_device struct
  * @handler: callback function for link status change notifications
+ * @context: context information for callback handler
  *
  * Description: Tells the PHY infrastructure to handle the
  *   gory details on monitoring link status (whether through
@@ -319,9 +320,11 @@ EXPORT_SYMBOL(phy_find_first);
  *   this function.
  */
 static void phy_prepare_link(struct phy_device *phydev,
-		void (*handler)(struct net_device *))
+		void (*handler)(struct net_device *, void *context),
+		void *context)
 {
 	phydev->adjust_link = handler;
+	phydev->context = context;
 }
 
 /**
@@ -331,10 +334,11 @@ static void phy_prepare_link(struct phy_device *phydev,
  * @handler: callback function for state change notifications
  * @flags: PHY device's dev_flags
  * @interface: PHY device's interface
+ * @context: context information for callback handler
  */
 int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
-		       void (*handler)(struct net_device *), u32 flags,
-		       phy_interface_t interface)
+		       void (*handler)(struct net_device *, void *context),
+		       u32 flags, phy_interface_t interface, void *context)
 {
 	int rc;
 
@@ -342,7 +346,7 @@ int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
 	if (rc)
 		return rc;
 
-	phy_prepare_link(phydev, handler);
+	phy_prepare_link(phydev, handler, context);
 	phy_start_machine(phydev, NULL);
 	if (phydev->irq > 0)
 		phy_start_interrupts(phydev);
@@ -358,6 +362,7 @@ EXPORT_SYMBOL(phy_connect_direct);
  * @handler: callback function for state change notifications
  * @flags: PHY device's dev_flags
  * @interface: PHY device's interface
+ * @context: context information for callback handler
  *
  * Description: Convenience function for connecting ethernet
  *   devices to PHY devices.  The default behavior is for
@@ -367,9 +372,10 @@ EXPORT_SYMBOL(phy_connect_direct);
  *   choose to call only the subset of functions which provide
  *   the desired functionality.
  */
-struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
-		void (*handler)(struct net_device *), u32 flags,
-		phy_interface_t interface)
+struct phy_device *
+phy_connect(struct net_device *dev, const char *bus_id,
+	    void (*handler)(struct net_device *, void *context),
+	    u32 flags, phy_interface_t interface, void *context)
 {
 	struct phy_device *phydev;
 	struct device *d;
@@ -384,7 +390,8 @@ struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
 	}
 	phydev = to_phy_device(d);
 
-	rc = phy_connect_direct(dev, phydev, handler, flags, interface);
+	rc = phy_connect_direct(dev, phydev, handler, flags, interface,
+				context);
 	if (rc)
 		return ERR_PTR(rc);
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index c291cae..596b8fe 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -263,6 +263,7 @@ enum phy_state {
  * changes in the link state.
  * adjust_state: Callback for the enet driver to respond to
  * changes in the state machine.
+ * context: Context information for adjust_link and adjust_state callbacks
  *
  * speed, duplex, pause, supported, advertising, and
  * autoneg are used like in mii_if_info
@@ -337,9 +338,11 @@ struct phy_device {
 
 	struct net_device *attached_dev;
 
-	void (*adjust_link)(struct net_device *dev);
+	void (*adjust_link)(struct net_device *dev, void *context);
 
-	void (*adjust_state)(struct net_device *dev);
+	void (*adjust_state)(struct net_device *dev, void *context);
+
+	void *context;
 };
 #define to_phy_device(d) container_of(d, struct phy_device, dev)
 
@@ -487,11 +490,12 @@ struct phy_device * phy_attach(struct net_device *dev,
 		const char *bus_id, u32 flags, phy_interface_t interface);
 struct phy_device *phy_find_first(struct mii_bus *bus);
 int phy_connect_direct(struct net_device *dev, struct phy_device *phydev,
-		void (*handler)(struct net_device *), u32 flags,
-		phy_interface_t interface);
-struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
-		void (*handler)(struct net_device *), u32 flags,
-		phy_interface_t interface);
+		       void (*handler)(struct net_device *, void *context),
+		       u32 flags, phy_interface_t interface, void *context);
+struct phy_device *
+phy_connect(struct net_device *dev, const char *bus_id,
+	    void (*handler)(struct net_device *, void *context),
+	    u32 flags, phy_interface_t interface, void *context);
 void phy_disconnect(struct phy_device *phydev);
 void phy_detach(struct phy_device *phydev);
 void phy_start(struct phy_device *phydev);
@@ -514,7 +518,7 @@ void phy_driver_unregister(struct phy_driver *drv);
 int phy_driver_register(struct phy_driver *new_driver);
 void phy_state_machine(struct work_struct *work);
 void phy_start_machine(struct phy_device *phydev,
-		void (*handler)(struct net_device *));
+		       void (*handler)(struct net_device *, void *context));
 void phy_stop_machine(struct phy_device *phydev);
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 1/4] phylib: factor out handler callouts into helper
From: s-paulraj @ 2012-07-06 20:09 UTC (permalink / raw)
  To: netdev, davem, cyril, grant.likely, linux-keystone; +Cc: Sandeep Paulraj

From: Sandeep Paulraj <s-paulraj@ti.com>

This patch pulls out adjust_link handler callbacks into a helper function.
The patch does not modify phylib behavior in any material way.

Signed-off-by: Cyril Chemparathy <cyril@ti.com>
Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
---
 drivers/net/phy/phy.c |   21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 3cbda08..36ca912 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -761,6 +761,11 @@ void phy_start(struct phy_device *phydev)
 EXPORT_SYMBOL(phy_stop);
 EXPORT_SYMBOL(phy_start);
 
+static inline void phy_adjust_link(struct phy_device *phydev)
+{
+	phydev->adjust_link(phydev->attached_dev);
+}
+
 /**
  * phy_state_machine - Handle the state machine
  * @work: work_struct that describes the work to be done
@@ -801,7 +806,7 @@ void phy_state_machine(struct work_struct *work)
 			if (!phydev->link) {
 				phydev->state = PHY_NOLINK;
 				netif_carrier_off(phydev->attached_dev);
-				phydev->adjust_link(phydev->attached_dev);
+				phy_adjust_link(phydev);
 				break;
 			}
 
@@ -815,7 +820,7 @@ void phy_state_machine(struct work_struct *work)
 			if (err > 0) {
 				phydev->state = PHY_RUNNING;
 				netif_carrier_on(phydev->attached_dev);
-				phydev->adjust_link(phydev->attached_dev);
+				phy_adjust_link(phydev);
 
 			} else if (0 == phydev->link_timeout--) {
 				int idx;
@@ -853,7 +858,7 @@ void phy_state_machine(struct work_struct *work)
 			if (phydev->link) {
 				phydev->state = PHY_RUNNING;
 				netif_carrier_on(phydev->attached_dev);
-				phydev->adjust_link(phydev->attached_dev);
+				phy_adjust_link(phydev);
 			}
 			break;
 		case PHY_FORCING:
@@ -872,7 +877,7 @@ void phy_state_machine(struct work_struct *work)
 				}
 			}
 
-			phydev->adjust_link(phydev->attached_dev);
+			phy_adjust_link(phydev);
 			break;
 		case PHY_RUNNING:
 			/* Only register a CHANGE if we are
@@ -894,7 +899,7 @@ void phy_state_machine(struct work_struct *work)
 				netif_carrier_off(phydev->attached_dev);
 			}
 
-			phydev->adjust_link(phydev->attached_dev);
+			phy_adjust_link(phydev);
 
 			if (PHY_POLL != phydev->irq)
 				err = phy_config_interrupt(phydev,
@@ -904,7 +909,7 @@ void phy_state_machine(struct work_struct *work)
 			if (phydev->link) {
 				phydev->link = 0;
 				netif_carrier_off(phydev->attached_dev);
-				phydev->adjust_link(phydev->attached_dev);
+				phy_adjust_link(phydev);
 			}
 			break;
 		case PHY_RESUMING:
@@ -938,7 +943,7 @@ void phy_state_machine(struct work_struct *work)
 						netif_carrier_on(phydev->attached_dev);
 					} else
 						phydev->state = PHY_NOLINK;
-					phydev->adjust_link(phydev->attached_dev);
+					phy_adjust_link(phydev);
 				} else {
 					phydev->state = PHY_AN;
 					phydev->link_timeout = PHY_AN_TIMEOUT;
@@ -953,7 +958,7 @@ void phy_state_machine(struct work_struct *work)
 					netif_carrier_on(phydev->attached_dev);
 				} else
 					phydev->state = PHY_NOLINK;
-				phydev->adjust_link(phydev->attached_dev);
+				phy_adjust_link(phydev);
 			}
 			break;
 	}
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 0/4] phylib: add context argument to adjust link callbacks
From: s-paulraj @ 2012-07-06 19:57 UTC (permalink / raw)
  To: netdev, davem, cyril, grant.likely, linux-keystone; +Cc: Sandeep Paulraj

From: Sandeep Paulraj <s-paulraj@ti.com>

This series of 4 patches adds a new context argument for the adjust link
callbacks. The existing phy_connect() and its variants don't have a way to
pass any private context information. This becomes necessary when, a SOC
has an on chip switch with multiple ports. We need port specific information
to figure out which port a given callback belongs to.
We can pass this context information in the phy_connect() and its
variants. This in turn gets passed into the adjust link callbacks on link
state change events.

NOTE: At this point of time patch 4 in this series passes a "NULL" to
the phy_connect() and its variants for all drivers that currently use
phy_connect() and its variants. This patch has been tested on a
Texas Instruments SOC, patches for which, as of now have not yet been
upstreamed; as a result of which this patch series does not yet
have an example of how this new feature is being actually used.

Sandeep Paulraj (4):
  phylib: factor out handler callouts into helper
  phylib: add context argument to adjust link callback
  of/mdio: add context argument to adjust link callback
  net: add context callback parameter to phy connect

 drivers/net/ethernet/8390/ax88796.c                |    4 ++--
 drivers/net/ethernet/adi/bfin_mac.c                |    4 ++--
 drivers/net/ethernet/aeroflex/greth.c              |    7 +++---
 drivers/net/ethernet/amd/au1000_eth.c              |    4 ++--
 drivers/net/ethernet/broadcom/bcm63xx_enet.c       |    4 ++--
 drivers/net/ethernet/broadcom/sb1250-mac.c         |    6 ++---
 drivers/net/ethernet/broadcom/tg3.c                |    4 ++--
 drivers/net/ethernet/cadence/macb.c                |    4 ++--
 drivers/net/ethernet/dnet.c                        |    6 ++---
 drivers/net/ethernet/ethoc.c                       |    4 ++--
 drivers/net/ethernet/faraday/ftgmac100.c           |    4 ++--
 drivers/net/ethernet/freescale/fec.c               |    4 ++--
 drivers/net/ethernet/freescale/fec_mpc52xx.c       |    5 ++--
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |    6 ++---
 drivers/net/ethernet/freescale/gianfar.c           |    8 +++----
 drivers/net/ethernet/freescale/ucc_geth.c          |    6 ++---
 drivers/net/ethernet/lantiq_etop.c                 |    4 ++--
 drivers/net/ethernet/nxp/lpc_eth.c                 |    5 ++--
 drivers/net/ethernet/octeon/octeon_mgmt.c          |    4 ++--
 drivers/net/ethernet/pasemi/pasemi_mac.c           |    4 ++--
 drivers/net/ethernet/rdc/r6040.c                   |    4 ++--
 drivers/net/ethernet/renesas/sh_eth.c              |    4 ++--
 drivers/net/ethernet/s6gmac.c                      |    4 ++--
 drivers/net/ethernet/smsc/smsc911x.c               |    4 ++--
 drivers/net/ethernet/smsc/smsc9420.c               |    5 ++--
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |    6 +++--
 drivers/net/ethernet/ti/cpmac.c                    |    4 ++--
 drivers/net/ethernet/ti/cpsw.c                     |    5 ++--
 drivers/net/ethernet/ti/davinci_emac.c             |    4 ++--
 drivers/net/ethernet/toshiba/tc35815.c             |    5 ++--
 drivers/net/ethernet/xilinx/ll_temac_main.c        |    4 ++--
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c  |    3 ++-
 drivers/net/ethernet/xilinx/xilinx_emaclite.c      |    5 ++--
 drivers/net/ethernet/xscale/ixp4xx_eth.c           |    4 ++--
 drivers/net/phy/phy.c                              |   25 ++++++++++++--------
 drivers/net/phy/phy_device.c                       |   23 +++++++++++-------
 drivers/of/of_mdio.c                               |   24 ++++++++++++-------
 include/linux/of_mdio.h                            |   15 ++++++------
 include/linux/phy.h                                |   20 +++++++++-------
 39 files changed, 149 insertions(+), 116 deletions(-)

-- 
1.7.9.5

^ permalink raw reply

* Re: Network namespace and bonding WARNING at fs/proc/generic.c remove_proc_entry
From: Serge E. Hallyn @ 2012-07-06 19:47 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Dilip Daya, linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <87fw94g1kq.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

Quoting Eric W. Biederman (ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org):
> "Serge E. Hallyn" <serge-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org> writes:
> 
> >> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> >> index 2ee8cf9..818ed64 100644
> >> --- a/drivers/net/bonding/bond_main.c
> >> +++ b/drivers/net/bonding/bond_main.c
> >> @@ -4345,6 +4345,9 @@ static void bond_setup(struct net_device *bond_dev)
> >>         bond_dev->priv_flags |= IFF_BONDING;
> >>         bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
> >>  
> >> +       /* Don't allow bond devices to change network namespaces. */
> >> +       bond_dev->features |= NETIF_F_LOCAL;
> >
> > I believe this needs to be NETIF_F_NETNS_LOCAL.  Test build still going with
> > that change.
> 
> Yes that is what I mean.

With that change, build is fine, boots fine, I can't pass a bond to another
netns (preventing the problem), and I can create a bond in a child netns
just fine.

Thanks!

Acked-by: Serge Hallyn <serge.hallyn-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>

-serge

^ permalink raw reply

* pull request: wireless 2012-07-06
From: John W. Linville @ 2012-07-06 19:20 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev, linux-kernel

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

commit 50787c0dfcffe9be908994bdd7bb28b1a49192b5

Dave,

Please accept these fixes for the 3.5 stream...

Eliad Peller provides a mac80211 fix to properly clean-up after an
association failure.

Sasha Levin offers an NFC fix to prevent a NULL pointer derference
in llcp_sock_getname.

Thomas Huehn provides an mwl8k fix for a race that can result in
a use-after-free bug.  Also, he provides a mac80211 fix to correct
some kzalloc arguments, and another fix to address an issue found
with that fix after I had already committed the original patch.

Please let me know if there are problems!

Thanks,

John

---

The following changes since commit 9e85a6f9dc231f3ed3c1dc1b12217505d970142a:

  Merge tag 'clk-fixes-for-linus' of git://git.linaro.org/people/mturquette/linux (2012-07-03 18:06:49 -0700)

are available in the git repository at:


  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem

for you to fetch changes up to 50787c0dfcffe9be908994bdd7bb28b1a49192b5:

  Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem (2012-07-06 14:48:50 -0400)

----------------------------------------------------------------

Eliad Peller (1):
      mac80211: destroy assoc_data correctly if assoc fails

John W. Linville (1):
      Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem

Sasha Levin (1):
      NFC: Prevent NULL deref when getting socket name

Thomas Huehn (3):
      mac80211: correct size the argument to kzalloc in minstrel_ht
      mwl8k: fix possible race condition in info->control.sta use
      mac80211: fix kzalloc memory corruption introduced in minstrel_ht

 drivers/net/wireless/mwl8k.c       |    3 ++-
 net/mac80211/mlme.c                |    6 ++----
 net/mac80211/rc80211_minstrel_ht.c |    2 +-
 net/nfc/llcp/sock.c                |    2 +-
 4 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index cf7bdc6..1404373 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1665,7 +1665,8 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
 
 		info = IEEE80211_SKB_CB(skb);
 		if (ieee80211_is_data(wh->frame_control)) {
-			sta = info->control.sta;
+			sta = ieee80211_find_sta_by_ifaddr(hw, wh->addr1,
+								wh->addr2);
 			if (sta) {
 				sta_info = MWL8K_STA(sta);
 				BUG_ON(sta_info == NULL);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a4bb856..0db5d34 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2174,15 +2174,13 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 		       sdata->name, mgmt->sa, status_code);
 		ieee80211_destroy_assoc_data(sdata, false);
 	} else {
-		printk(KERN_DEBUG "%s: associated\n", sdata->name);
-
 		if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
 			/* oops -- internal error -- send timeout for now */
-			ieee80211_destroy_assoc_data(sdata, true);
-			sta_info_destroy_addr(sdata, mgmt->bssid);
+			ieee80211_destroy_assoc_data(sdata, false);
 			cfg80211_put_bss(*bss);
 			return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
 		}
+		printk(KERN_DEBUG "%s: associated\n", sdata->name);
 
 		/*
 		 * destroy assoc_data afterwards, as otherwise an idle
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 2d1acc6..f9e51ef 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -809,7 +809,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
 			max_rates = sband->n_bitrates;
 	}
 
-	msp = kzalloc(sizeof(struct minstrel_ht_sta), gfp);
+	msp = kzalloc(sizeof(*msp), gfp);
 	if (!msp)
 		return NULL;
 
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 17a707d..e06d458 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -292,7 +292,7 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr,
 
 	pr_debug("%p\n", sk);
 
-	if (llcp_sock == NULL)
+	if (llcp_sock == NULL || llcp_sock->dev == NULL)
 		return -EBADFD;
 
 	addr->sa_family = AF_NFC;
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply related

* Re: Network namespace and bonding WARNING at fs/proc/generic.c remove_proc_entry
From: Eric W. Biederman @ 2012-07-06 18:57 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Dilip Daya, linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20120706170538.GA31679-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>

"Serge E. Hallyn" <serge-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org> writes:

>> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>> index 2ee8cf9..818ed64 100644
>> --- a/drivers/net/bonding/bond_main.c
>> +++ b/drivers/net/bonding/bond_main.c
>> @@ -4345,6 +4345,9 @@ static void bond_setup(struct net_device *bond_dev)
>>         bond_dev->priv_flags |= IFF_BONDING;
>>         bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
>>  
>> +       /* Don't allow bond devices to change network namespaces. */
>> +       bond_dev->features |= NETIF_F_LOCAL;
>
> I believe this needs to be NETIF_F_NETNS_LOCAL.  Test build still going with
> that change.

Yes that is what I mean.

Eric

^ permalink raw reply

* Re: [PATCH] ipv4: Avoid overhead when no custom FIB rules are installed.
From: David Miller @ 2012-07-06 18:53 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev
In-Reply-To: <1341595171.2923.2.camel@bwh-desktop.uk.solarflarecom.com>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Fri, 6 Jul 2012 18:19:31 +0100

> Do you really mean to set fib_has_custom_rules = true on deletion?

Yes, because someone could delete one of the default rules, which
would make our shortcut invalid.

^ permalink raw reply

* Re: Network namespace and bonding WARNING at fs/proc/generic.c remove_proc_entry
From: Eric W. Biederman @ 2012-07-06 18:40 UTC (permalink / raw)
  To: dilip.daya; +Cc: Serge E. Hallyn, linux-kernel, containers, netdev
In-Reply-To: <1341597680.2829.22.camel@pro6455b.example.com>

Dilip Daya <dilip.daya@hp.com> writes:

> Hi Eric,

> We do need to move bonds between namespaces - because we require
> physical interfaces in each namespace -- we don't want the overheads of
> virtual interfaces, don't have the management infrastructure, and don't
> want to manufacture fake mac addresses that would be required for
> macvlan interfaces.   Since the bonds are implicitly created in the host
> namespace, the only way we know to get bonds directly into the
> namespaces is to move them.

There about 3 ways to create bonding devices.  One of those ways
is to create bonding devices when loading the module.  Another
way is to create a bond device with "echo '+bond35 > /sys/class/net/bonding_masters".
them when loading the module, and my favorite is the standard way
"ip link add type bond".  All but loading the bonding device work in the
network namespace you are in at the type.

> Would "NETDEV_UNREGISTER and NETDEV_REGISTER events to remove/add the
> per device proc files at the appropriate time." help in the case?

Yes.  But since you can create the bonding device in the network
namespace you need it in, I don't see the point, of adding a code
path no one will test for 3 years at a time.

It seems easier to me to just not allow migration of bonding devices
and set peoples expectations a little lower.  Especially given
the very complex user space interfaces.

On ther other hand if you want to write and test and generally own the
patch I will review it.

Eric

^ permalink raw reply

* Re: AF_BUS socket address family
From: Chris Friesen @ 2012-07-06 18:27 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Vincent Sanders, David Miller, netdev, linux-kernel
In-Reply-To: <alpine.LNX.2.01.1207052242450.2202@frira.zrqbmnf.qr>

> On Saturday 2012-06-30 01:12, Vincent Sanders wrote:
>> Firstly it is intended is an interprocess mechanism and not to rely on
>> a configured IP system, indeed one of its primary usages is to
>> provide mechanism for various tools to set up IP networking.
> Using IP as a localhost IPC is not uncommon (independent of
> software preferring AF_UNIX, if so available). Distro boot
> scripts have been running `ip addr add ::1/128 dev lo`
> all these years along.
>
> And now we suddently need a DBUS program just to configure
> IP-based localhost IPC? I can see the flaw in that.
>

I haven't tried it in a while but it used to be that you couldn't use IP 
multicast on the "lo" device.  Has that been fixed?

Chris

^ permalink raw reply

* [PATCH] smsc95xx: support ethtool get_regs
From: Émeric Vigier @ 2012-07-06 18:15 UTC (permalink / raw)
  To: Steve Glendinning, steve glendinning; +Cc: netdev, Nancy Lin
In-Reply-To: <1291035348.223127.1341596173191.JavaMail.root@mail.savoirfairelinux.com>

From: Emeric Vigier <emeric.vigier@savoirfairelinux.com>

Inspired by implementation in smsc911x.c and smsc9420.c
Tested on ARM/pandaboard rev A3

Signed-off-by: Emeric Vigier <emeric.vigier@savoirfairelinux.com>
---
 drivers/net/usb/smsc95xx.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index b1112e7..bce14f6 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -578,6 +578,41 @@ static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev,
 	return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data);
 }
 
+
+static int smsc95xx_ethtool_getregslen(struct net_device *dev)
+{
+	/* all smsc95xx registers plus all phy registers */
+	return COE_CR - ID_REV + 1 + 32 * sizeof(u32);
+}
+
+static void
+smsc95xx_ethtool_getregs(struct net_device *netdev, struct ethtool_regs *regs,
+			 void *buf)
+{
+	struct usbnet *dev = netdev_priv(netdev);
+	unsigned int i, j = 0, retval;
+	u32 *data = buf;
+
+	netif_dbg(dev, hw, dev->net, "ethtool_getregs\n");
+
+	retval = smsc95xx_read_reg(dev, ID_REV, &regs->version);
+	if (retval < 0) {
+		netdev_warn(dev->net, "REGS: cannot read ID_REV\n");
+		return;
+	}
+
+	for (i = 0; i <= COE_CR; i += (sizeof(u32))) {
+		retval = smsc95xx_read_reg(dev, i, &data[j++]);
+		if (retval < 0) {
+			netdev_warn(dev->net, "REGS: cannot read reg[%x]\n", i);
+			return;
+		}
+	}
+
+	for (i = 0; i <= PHY_SPECIAL; i++)
+		data[j++] = smsc95xx_mdio_read(netdev, dev->mii.phy_id, i);
+}
+
 static const struct ethtool_ops smsc95xx_ethtool_ops = {
 	.get_link	= usbnet_get_link,
 	.nway_reset	= usbnet_nway_reset,
@@ -589,6 +624,8 @@ static const struct ethtool_ops smsc95xx_ethtool_ops = {
 	.get_eeprom_len	= smsc95xx_ethtool_get_eeprom_len,
 	.get_eeprom	= smsc95xx_ethtool_get_eeprom,
 	.set_eeprom	= smsc95xx_ethtool_set_eeprom,
+	.get_regs_len	= smsc95xx_ethtool_getregslen,
+	.get_regs	= smsc95xx_ethtool_getregs,
 };
 
 static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
-- 
1.7.5.4

Emeric

^ permalink raw reply related

* Re: [PATCH] gianfar: fix potential sk_wmem_alloc imbalance
From: Paul Gortmaker @ 2012-07-06 18:09 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, netdev, Manfred Rudigier, Claudiu Manoil, Jiajun Wu,
	Andy Fleming
In-Reply-To: <1341524713.3265.41.camel@edumazet-glaptop>

[[PATCH] gianfar: fix potential sk_wmem_alloc imbalance] On 05/07/2012 (Thu 23:45) Eric Dumazet wrote:

> From: Eric Dumazet <edumazet@google.com>
> 
> commit db83d136d7f753 (gianfar: Fix missing sock reference when
> processing TX time stamps) added a potential sk_wmem_alloc imbalance
> 
> If the new skb has a different truesize than old one, we can get a
> negative sk_wmem_alloc once new skb is orphaned at TX completion.
> 
> Now we no longer early orphan skbs in dev_hard_start_xmit(), this
> probably can lead to fatal bugs.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Manfred Rudigier <manfred.rudigier@omicron.at>
> Cc: Claudiu Manoil <claudiu.manoil@freescale.com>
> Cc: Jiajun Wu <b06378@freescale.com>
> Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
> Cc: Andy Fleming <afleming@freescale.com>
> ---
> 
> Note : I don't have the hardware and discovered this problem by code
> analysis. So please compile and run this patch before Acking it,
> thanks !

I can do that on Monday when I'm back in the office if nobody else has
already done it by then.

> 
> BTW, dev->needed_headroom should be set to GMAC_FCB_LEN + GMAC_TXPAL_LEN
> to avoid reallocations...

Aside from the one line change at driver init, is there more to it than
that?  More specifically, it currently does:

fcb_length = GMAC_FCB_LEN;

if (...timestamps...)
	fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN;

if (... && (skb_headroom(skb) < fcb_length))
	...
	skb_new = skb_realloc_headroom(skb, fcb_length);

and I don't know the code well enough to know if setting the
needed_headroom value _guarantees_ the above fcb_length comparison
will always be false, and hence can be deleted.  It kind of looks
like it via LL_RESERVED_SPACE, but I'm not 100% sure...

Thanks,
Paul.
--

> 
>  drivers/net/ethernet/freescale/gianfar.c |    7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
> index f2db8fc..ab1d80f 100644
> --- a/drivers/net/ethernet/freescale/gianfar.c
> +++ b/drivers/net/ethernet/freescale/gianfar.c
> @@ -2063,10 +2063,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  			return NETDEV_TX_OK;
>  		}
>  
> -		/* Steal sock reference for processing TX time stamps */
> -		swap(skb_new->sk, skb->sk);
> -		swap(skb_new->destructor, skb->destructor);
> -		kfree_skb(skb);
> +		if (skb->sk)
> +			skb_set_owner_w(skb_new, skb->sk);
> +		consume_skb(skb);
>  		skb = skb_new;
>  	}
>  
> 
> 

^ permalink raw reply

* Re: Network namespace and bonding WARNING at fs/proc/generic.c remove_proc_entry
From: Dilip Daya @ 2012-07-06 18:01 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Eric W. Biederman, linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20120706170538.GA31679-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>

Hi Serge,

On Fri, 2012-07-06 at 17:05 +0000, Serge E. Hallyn wrote:
> Quoting Eric W. Biederman (ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org):
> > "Serge E. Hallyn" <serge-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org> writes:
> > 
> > > Quoting Dilip Daya (dilip.daya-VXdhtT5mjnY@public.gmane.org):
> > >> Hi,
> > >> 
> > >> I'd discussed the following with Serge Hallyn.
> > >> 
> > >> => Environment based on 3.2.18 / x86_64 kernel.
> > >> => WARNING: at fs/proc/generic.c:808 remove_proc_entry+0xdb/0x21f()
> > >> => WARNING: at fs/proc/generic.c:849 remove_proc_entry+0x208/0x21f()
> > >
> > > Hi,
> > >
> > > thanks much for sending this.  I'm still getting this error on
> > > 3.5.0-2-generic (today's ubuntu quantal kernel)
> > >
> > >> network namespace and bonding
> > >> -----------------------------
> > >> 
> > >> * Migrate two phy nics from host to netns (netns0).
> > >>   - ip link set ethX netns netns0
> > >> 
> > >> * In host environment:
> > >>   - load bonding module, /sbin/modprobe -v bonding mode=1 miimon=100
> > >>   - /sys/class/net/bond0 exists.
> > >>   - /proc/net/bonding/bond0 exists.
> > >>   - /sys/class/net/bonding_masters has bond0.
> > >> 
> > >> * Migrate bond0 to netns (netns0):
> > >>   - ip link set bond0 netns netns0.
> > >> 
> > >> * Within netns (netns0):
> > >>   - /sys/class/net/bonding_masters is empty.
> > >>   - /sys/class/net/bond0 exist.
> > >>   - configure bond0 and ifenslave with two phy nics.
> > >>   - /proc/net/bonding/bond0 does not exist within netns0, but does
> > >>     exist in the host environment.
> > >>   - /sys/class/net/bonding_masters is empty.
> > >
> > > mine is not empty, fwiw.  However
> > >
> > >>   - ping to remote end of bond0 works.
> > >> 
> > >> * Within netns (netns0), flushing ethX and bondY:
> > >>   - down bond0 and its phy nic interfaces:
> > >>   - ip link set ... down
> > >>   - ip addr flush dev [bond0 | eth#]
> > >>   - deleting bond0, /sbin/ip link del dev bond0
> > >
> > > Yup I still get a remove_proc_entry WARNING at fs/proc/generic.c:808,
> > > which is the warning when (!de)
> > 
> > It looks like Dilip is running an old kernel.  There should have been
> > some version of /sys/class/net/bonding_masters in every network
> > namespace since sometime in 2009.
> > 
> > >From the warning it looks like the proc files are being added/removed
> > to the wrong network namespace.  So in one namespace we get an error
> > when we delete the moved device and in the other network namespace
> > we get an error when we remove the /proc/directory.
> > 
> > An old kernel without proper network namespace support is the only
> > reason I can imagine someone would be moving an existing bond device
> > between network namespaces.
> > 
> > If there are other reasons for wanting to move a bonding device between
> > network namespaces it is possible to catch the NETDEV_UNREGISTER and
> > NETDEV_REGISTER events to remove/add the per device proc files at the
> > appropriate time.
> > 
> > However since moving bonding devices appears to be an unneded operation
> > let's just do things simply and forbid moving bonding devices between
> > network namespaces.  Serge, Dilip can you two test the patch below
> > and see if it fixes the warnings.
> > 
> > Eric
> > 
> > 
> > diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> > index 2ee8cf9..818ed64 100644
> > --- a/drivers/net/bonding/bond_main.c
> > +++ b/drivers/net/bonding/bond_main.c
> > @@ -4345,6 +4345,9 @@ static void bond_setup(struct net_device *bond_dev)
> >         bond_dev->priv_flags |= IFF_BONDING;
> >         bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
> >  
> > +       /* Don't allow bond devices to change network namespaces. */
> > +       bond_dev->features |= NETIF_F_LOCAL;
> 
> I believe this needs to be NETIF_F_NETNS_LOCAL.  Test build still going with
> that change.


Correct, I made that change and rebuilt bonding driver:

# modinfo bonding | head
filename:       /lib/modules/3.2.18-clim-3-amd64/kernel/drivers/net/bonding/bonding.ko
alias:          rtnl-link-bond
author:         Thomas Davis, tadavis-/3juihCSby0@public.gmane.org and many others
description:    Ethernet Channel Bonding Driver, v3.7.1-netns
version:        3.7.1-netns
...


My results with the above bonding driver:

(1) Migrating bond0 from host to netns:

  # ip link set bond0 netns netns0
  RTNETLINK answers: Invalid argument

  => cannot migrate bond0 from host to netns.
  => No warnings.


(2) Loading bonding module in host environment and unloading bonding
    module from within netns:

  # modprobe -v -r bonding
  #
rmmod /lib/modules/3.2.18-clim-3-amd64/kernel/drivers/net/bonding/bonding.ko

	# lsmod | grep bond
	<<< bonding module does not exist >>>

	# ll /sys/class/net/
total 0
lrwxrwxrwx 1 root root 0 Jul  6 11:00 lo
-> ../../devices/virtual/net/lo/
lrwxrwxrwx 1 root root 0 Jul  6 11:00 eth7
-> ../../devices/pci0000:00/0000:00:05.0/0000:14:00.1/net/eth7/
lrwxrwxrwx 1 root root 0 Jul  6 11:00 eth6
-> ../../devices/pci0000:00/0000:00:05.0/0000:14:00.0/net/eth6/

	=> No warnings.


-DilipD.

^ permalink raw reply

* Re: Network namespace and bonding WARNING at fs/proc/generic.c remove_proc_entry
From: Dilip Daya @ 2012-07-06 18:01 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <87ehopu3e5.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

Hi Eric,

On Thu, 2012-07-05 at 17:41 -0700, Eric W. Biederman wrote:
> "Serge E. Hallyn" <serge-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org> writes:
> 
> > Quoting Dilip Daya (dilip.daya-VXdhtT5mjnY@public.gmane.org):
> >> Hi,
> >> 
> >> I'd discussed the following with Serge Hallyn.
> >> 
> >> => Environment based on 3.2.18 / x86_64 kernel.
> >> => WARNING: at fs/proc/generic.c:808 remove_proc_entry+0xdb/0x21f()
> >> => WARNING: at fs/proc/generic.c:849 remove_proc_entry+0x208/0x21f()
> >
> > Hi,
> >
> > thanks much for sending this.  I'm still getting this error on
> > 3.5.0-2-generic (today's ubuntu quantal kernel)
> >
> >> network namespace and bonding
> >> -----------------------------
> >> 
> >> * Migrate two phy nics from host to netns (netns0).
> >>   - ip link set ethX netns netns0
> >> 
> >> * In host environment:
> >>   - load bonding module, /sbin/modprobe -v bonding mode=1 miimon=100
> >>   - /sys/class/net/bond0 exists.
> >>   - /proc/net/bonding/bond0 exists.
> >>   - /sys/class/net/bonding_masters has bond0.
> >> 
> >> * Migrate bond0 to netns (netns0):
> >>   - ip link set bond0 netns netns0.
> >> 
> >> * Within netns (netns0):
> >>   - /sys/class/net/bonding_masters is empty.
> >>   - /sys/class/net/bond0 exist.
> >>   - configure bond0 and ifenslave with two phy nics.
> >>   - /proc/net/bonding/bond0 does not exist within netns0, but does
> >>     exist in the host environment.
> >>   - /sys/class/net/bonding_masters is empty.
> >
> > mine is not empty, fwiw.  However
> >
> >>   - ping to remote end of bond0 works.
> >> 
> >> * Within netns (netns0), flushing ethX and bondY:
> >>   - down bond0 and its phy nic interfaces:
> >>   - ip link set ... down
> >>   - ip addr flush dev [bond0 | eth#]
> >>   - deleting bond0, /sbin/ip link del dev bond0
> >
> > Yup I still get a remove_proc_entry WARNING at fs/proc/generic.c:808,
> > which is the warning when (!de)
> 
> It looks like Dilip is running an old kernel.  There should have been
> some version of /sys/class/net/bonding_masters in every network
> namespace since sometime in 2009.
> 
> >From the warning it looks like the proc files are being added/removed
> to the wrong network namespace.  So in one namespace we get an error
> when we delete the moved device and in the other network namespace
> we get an error when we remove the /proc/directory.
> 
> An old kernel without proper network namespace support is the only
> reason I can imagine someone would be moving an existing bond device
> between network namespaces.
> 
> If there are other reasons for wanting to move a bonding device between
> network namespaces it is possible to catch the NETDEV_UNREGISTER and
> NETDEV_REGISTER events to remove/add the per device proc files at the
> appropriate time.


We do need to move bonds between namespaces - because we require
physical interfaces in each namespace -- we don't want the overheads of
virtual interfaces, don't have the management infrastructure, and don't
want to manufacture fake mac addresses that would be required for
macvlan interfaces.   Since the bonds are implicitly created in the host
namespace, the only way we know to get bonds directly into the
namespaces is to move them.

Would "NETDEV_UNREGISTER and NETDEV_REGISTER events to remove/add the
per device proc files at the appropriate time." help in the case?


-DilipD.


> However since moving bonding devices appears to be an unneded operation
> let's just do things simply and forbid moving bonding devices between
> network namespaces.  Serge, Dilip can you two test the patch below
> and see if it fixes the warnings.
> 
> Eric
> 
> 
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 2ee8cf9..818ed64 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -4345,6 +4345,9 @@ static void bond_setup(struct net_device *bond_dev)
>         bond_dev->priv_flags |= IFF_BONDING;
>         bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
>  
> +       /* Don't allow bond devices to change network namespaces. */
> +       bond_dev->features |= NETIF_F_LOCAL;
> +
>         /* At first, we block adding VLANs. That's the only way to
>          * prevent problems that occur when adding VLANs over an
>          * empty bond. The block will be removed once non-challenged

^ permalink raw reply

* Re: [PATCH 4/4] asix: Add a new driver for the AX88172A
From: Ben Hutchings @ 2012-07-06 17:37 UTC (permalink / raw)
  To: Christian Riesch
  Cc: netdev, Oliver Neukum, Eric Dumazet, Allan Chou, Mark Lord,
	Grant Grundler, Ming Lei, Michael Riesch
In-Reply-To: <1341574388-7464-5-git-send-email-christian.riesch@omicron.at>

On Fri, 2012-07-06 at 13:33 +0200, Christian Riesch wrote:
> The Asix AX88172A is a USB 2.0 Ethernet interface that supports both an
> internal PHY as well as an external PHY (connected via MII).
> 
> This patch adds a driver for the AX88172A and provides support for
> both modes and supports phylib.
[...]
> +static int ax88172a_init_mdio(struct usbnet *dev)
> +{
> +	struct ax88172a_private *priv =
> +		(struct ax88172a_private *)dev->driver_priv;
> +	int ret, i;
> +
> +	priv->mdio = mdiobus_alloc();
> +	if (!priv->mdio) {
> +		dbg("Could not allocate MDIO bus");
> +		return -1;
> +	}
> +
> +	priv->mdio->priv = (void *)dev;
> +	priv->mdio->read = &asix_mdio_bus_read;
> +	priv->mdio->write = &asix_mdio_bus_write;
> +	priv->mdio->name = "Asix MDIO Bus";
> +	snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "asix-%s",
> +		 dev_name(dev->net->dev.parent));
[...]

I think you need to ensure that the bus identifier is unique throughout
its lifetime, but net devices can be renamed and that could lead to a
collision.  Perhaps you could use the ifindex or the USB device path
(though that might be too long).

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
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 next-next] ppp: change default for incoming protocol filter to NPMODE_DROP
From: Benjamin LaHaise @ 2012-07-06 17:28 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-ppp
In-Reply-To: <20120705.030027.655926012207641451.davem@davemloft.net>

On Thu, Jul 05, 2012 at 03:00:27AM -0700, David Miller wrote:
> As far as I can tell, this has been this way for a very long time.
> 
> Therefore it is the applications responsibility to adjust the filters
> to suit their needs and we really can't make such adjustments to this
> behavior.

Okay.  Clearing all the protocols the kernel may support in the future is a 
bit expensive due to a lack of a way to get the protocols supported -- the 
code would have to walk the entire protocol id space.  How about the 
following addition instead to provide a list of protocols to disable?

		-ben


[PATCH net-next] ppp: add PPPIOCGPROTOS ioctl to get the list of protocols

At present there is no means for a userspace ppp implementation to get a 
list of protocols supported by the kernel.  Add an ioctl, PPPIOCGPROTOS to 
get the protocol list array where [0] is the number of protocols in the 
array.

Signed-off-by: Benjamin LaHaise <bcrl@kvack.org>

diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 5c05572..daf50aa 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -565,6 +565,20 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 
+	if (cmd == PPPIOCGPROTOS) {
+		if (get_user(val, p))
+			return err;
+		if (val <= 0)
+			return -EINVAL;
+		if (NUM_NP < val)
+			val = NUM_NP;
+		if (put_user(val, p))
+			return err;
+		if (copy_to_user(p + 1, &npindex_to_proto, sizeof(int) * val))
+			return err;
+		return 0;
+	}
+
 	if (!pf)
 		return ppp_unattached_ioctl(current->nsproxy->net_ns,
 					pf, file, cmd, arg);
diff --git a/include/linux/ppp-ioctl.h b/include/linux/ppp-ioctl.h
index 2d9a885..d2cc304 100644
--- a/include/linux/ppp-ioctl.h
+++ b/include/linux/ppp-ioctl.h
@@ -81,6 +81,7 @@ struct pppol2tp_ioc_stats {
  * Ioctl definitions.
  */
 
+#define	PPPIOCGPROTOS	_IOWR('t', 90, int)	/* get protocol list array */
 #define	PPPIOCGFLAGS	_IOR('t', 90, int)	/* get configuration flags */
 #define	PPPIOCSFLAGS	_IOW('t', 89, int)	/* set configuration flags */
 #define	PPPIOCGASYNCMAP	_IOR('t', 88, int)	/* get async map */

^ permalink raw reply related

* Re: [PATCH] ipv4: Avoid overhead when no custom FIB rules are installed.
From: Ben Hutchings @ 2012-07-06 17:19 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20120705.223142.2236039770560842377.davem@davemloft.net>

On Thu, 2012-07-05 at 22:31 -0700, David Miller wrote:
> If the user hasn't actually installed any custom rules, or fiddled
> with the default ones, don't go through the whole FIB rules layer.
> 
> It's just pure overhead.
> 
> Instead do what we do with CONFIG_IP_MULTIPLE_TABLES disabled, check
> the individual tables by hand, one by one.
> 
> Also, move fib_num_tclassid_users into the ipv4 network namespace.
[...]
> --- a/net/ipv4/fib_rules.c
> +++ b/net/ipv4/fib_rules.c
[...]
> @@ -189,12 +190,14 @@ errout:
>  
>  static void fib4_rule_delete(struct fib_rule *rule)
>  {
> +	struct net *net = rule->fr_net;
>  #ifdef CONFIG_IP_ROUTE_CLASSID
>  	struct fib4_rule *rule4 = (struct fib4_rule *) rule;
>  
>  	if (rule4->tclassid)
> -		fib_num_tclassid_users--;
> +		net->ipv4.fib_num_tclassid_users--;
>  #endif
> +	net->ipv4.fib_has_custom_rules = true;
>  }
[...]

Do you really mean to set fib_has_custom_rules = true on deletion?
Shouldn't it conditionally be set false?  (Though the condition may be
too expensive to evaluate here without maintaining a separate counter.)

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
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: Network namespace and bonding WARNING at fs/proc/generic.c remove_proc_entry
From: Serge E. Hallyn @ 2012-07-06 17:05 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Dilip Daya, linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <87ehopu3e5.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

Quoting Eric W. Biederman (ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org):
> "Serge E. Hallyn" <serge-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org> writes:
> 
> > Quoting Dilip Daya (dilip.daya-VXdhtT5mjnY@public.gmane.org):
> >> Hi,
> >> 
> >> I'd discussed the following with Serge Hallyn.
> >> 
> >> => Environment based on 3.2.18 / x86_64 kernel.
> >> => WARNING: at fs/proc/generic.c:808 remove_proc_entry+0xdb/0x21f()
> >> => WARNING: at fs/proc/generic.c:849 remove_proc_entry+0x208/0x21f()
> >
> > Hi,
> >
> > thanks much for sending this.  I'm still getting this error on
> > 3.5.0-2-generic (today's ubuntu quantal kernel)
> >
> >> network namespace and bonding
> >> -----------------------------
> >> 
> >> * Migrate two phy nics from host to netns (netns0).
> >>   - ip link set ethX netns netns0
> >> 
> >> * In host environment:
> >>   - load bonding module, /sbin/modprobe -v bonding mode=1 miimon=100
> >>   - /sys/class/net/bond0 exists.
> >>   - /proc/net/bonding/bond0 exists.
> >>   - /sys/class/net/bonding_masters has bond0.
> >> 
> >> * Migrate bond0 to netns (netns0):
> >>   - ip link set bond0 netns netns0.
> >> 
> >> * Within netns (netns0):
> >>   - /sys/class/net/bonding_masters is empty.
> >>   - /sys/class/net/bond0 exist.
> >>   - configure bond0 and ifenslave with two phy nics.
> >>   - /proc/net/bonding/bond0 does not exist within netns0, but does
> >>     exist in the host environment.
> >>   - /sys/class/net/bonding_masters is empty.
> >
> > mine is not empty, fwiw.  However
> >
> >>   - ping to remote end of bond0 works.
> >> 
> >> * Within netns (netns0), flushing ethX and bondY:
> >>   - down bond0 and its phy nic interfaces:
> >>   - ip link set ... down
> >>   - ip addr flush dev [bond0 | eth#]
> >>   - deleting bond0, /sbin/ip link del dev bond0
> >
> > Yup I still get a remove_proc_entry WARNING at fs/proc/generic.c:808,
> > which is the warning when (!de)
> 
> It looks like Dilip is running an old kernel.  There should have been
> some version of /sys/class/net/bonding_masters in every network
> namespace since sometime in 2009.
> 
> >From the warning it looks like the proc files are being added/removed
> to the wrong network namespace.  So in one namespace we get an error
> when we delete the moved device and in the other network namespace
> we get an error when we remove the /proc/directory.
> 
> An old kernel without proper network namespace support is the only
> reason I can imagine someone would be moving an existing bond device
> between network namespaces.
> 
> If there are other reasons for wanting to move a bonding device between
> network namespaces it is possible to catch the NETDEV_UNREGISTER and
> NETDEV_REGISTER events to remove/add the per device proc files at the
> appropriate time.
> 
> However since moving bonding devices appears to be an unneded operation
> let's just do things simply and forbid moving bonding devices between
> network namespaces.  Serge, Dilip can you two test the patch below
> and see if it fixes the warnings.
> 
> Eric
> 
> 
> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> index 2ee8cf9..818ed64 100644
> --- a/drivers/net/bonding/bond_main.c
> +++ b/drivers/net/bonding/bond_main.c
> @@ -4345,6 +4345,9 @@ static void bond_setup(struct net_device *bond_dev)
>         bond_dev->priv_flags |= IFF_BONDING;
>         bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
>  
> +       /* Don't allow bond devices to change network namespaces. */
> +       bond_dev->features |= NETIF_F_LOCAL;

I believe this needs to be NETIF_F_NETNS_LOCAL.  Test build still going with
that change.

> +
>         /* At first, we block adding VLANs. That's the only way to
>          * prevent problems that occur when adding VLANs over an
>          * empty bond. The block will be removed once non-challenged

^ permalink raw reply

* Re: [net-next RFC V5 0/5] Multiqueue virtio-net
From: Rick Jones @ 2012-07-06 16:23 UTC (permalink / raw)
  To: Jason Wang
  Cc: krkumar2, habanero, mashirle, kvm, mst, netdev, linux-kernel,
	virtualization, edumazet, tahm, jwhan, davem, sri
In-Reply-To: <4FF696C9.5070907@redhat.com>

On 07/06/2012 12:42 AM, Jason Wang wrote:
> I'm not expert of tcp, but looks like the changes are reasonable:
> - we can do full-sized TSO check in tcp_tso_should_defer() only for
> westwood, according to tcp westwood
> - run tcp_tso_should_defer for tso_segs = 1 when tso is enabled.

I'm sure Eric and David will weigh-in on the TCP change.  My initial 
inclination would have been to say "well, if multiqueue is draining 
faster, that means ACKs come-back faster, which means the "race" between 
more data being queued by netperf and ACKs will go more to the ACKs 
which means the segments being sent will be smaller - as TCP_NODELAY is 
not set, the Nagle algorithm is in force, which means once there is data 
outstanding on the connection, no more will be sent until either the 
outstanding data is ACKed, or there is an accumulation of > MSS worth of 
data to send.

>> Also, how are you combining the concurrent netperf results?  Are you
>> taking sums of what netperf reports, or are you gathering statistics
>> outside of netperf?
>>
>
> The throughput were just sumed from netperf result like what netperf
> manual suggests. The cpu utilization were measured by mpstat.

Which mechanism to address skew error?  The netperf manual describes 
more than one:

http://www.netperf.org/svn/netperf2/trunk/doc/netperf.html#Using-Netperf-to-Measure-Aggregate-Performance

Personally, my preference these days is to use the "demo mode" method of 
aggregate results as it can be rather faster than (ab)using the 
confidence intervals mechanism, which I suspect may not really scale all 
that well to large numbers of concurrent netperfs.

I also tend to use the --enable-burst configure option to allow me to 
minimize the number of concurrent netperfs in the first place.  Set 
TCP_NODELAY (the test-specific -D option) and then have several 
transactions outstanding at one time (test-specific -b option with a 
number of additional in-flight transactions).

This is expressed in the runemomniaggdemo.sh script:

http://www.netperf.org/svn/netperf2/trunk/doc/examples/runemomniaggdemo.sh

which uses the find_max_burst.sh script:

http://www.netperf.org/svn/netperf2/trunk/doc/examples/find_max_burst.sh

to pick the burst size to use in the concurrent netperfs, the results of 
which can be post-processed with:

http://www.netperf.org/svn/netperf2/trunk/doc/examples/post_proc.py

The nice feature of using the "demo mode" mechanism is when it is 
coupled with systems with reasonably synchronized clocks (eg NTP) it can 
be used for many-to-many testing in addition to one-to-many testing 
(which cannot be dealt with by the confidence interval method of dealing 
with skew error)

>> A single instance TCP_RR test would help confirm/refute any
>> non-trivial change in (effective) path length between the two cases.
>>
>
> Yes, I would test this thanks.

Excellent.

happy benchmarking,

rick jones

^ permalink raw reply

* Re: [RFC PATCH] bridge: netfilter: fix skb->nf_bridge NULL panic in br_nf_forward_finish
From: Lin Ming @ 2012-07-06 15:37 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Massimo Cetra, netdev, Stephen Hemminger, David S. Miller,
	Julian Anastasov
In-Reply-To: <1341587206.3265.696.camel@edumazet-glaptop>

On Fri, Jul 6, 2012 at 11:06 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Fri, 2012-07-06 at 22:19 +0800, Lin Ming wrote:
>> I can reproduce similiar panic with 3.5-rc5 kernel as Massimo reported at:
>> http://marc.info/?l=linux-netdev&m=134089242113979&w=2
>>
>> The steps to reproduce as follow,
>>
>> 1. On Host1, setup brige br0(192.168.1.106)
>> 2. Boot a kvm guest(192.168.1.105) on Host1 and start httpd
>> 3. Start IPVS service on Host1
>>    ipvsadm -A -t 192.168.1.106:80 -s rr
>>    ipvsadm -a -t 192.168.1.106:80 -r 192.168.1.105:80 -m
>> 4. Run apache benchmark on Host2(192.168.1.101)
>>    ab -n 1000 http://192.168.1.106/
>>
>> The panic happened in br_nf_forward_finish because skb->nf_bridge is NULL.
>> skb->nf_bridge is set to NULL in ip_vs_reply4 hook.
>>
>> br_nf_forward_ip():
>>   NF_HOOK(pf, NF_INET_FORWARD, skb, brnf_get_logical_dev(skb, in), parent,
>>                 br_nf_forward_finish);
>>
>> This calls IPVS hook ip_vs_reply4.
>>
>> ip_vs_reply4
>>   ip_vs_out
>>     handle_response
>>       ip_vs_notrack
>>         nf_reset()
>>         {
>>           skb->nf_bridge = NULL;
>>         }
>>
>> This patch added skb->nf_bridge check in br_nf_forward_finish and the panic gone.
>> But I am really not sure if this is the right fix.
>> Please help to review.
>>
>> The panic log attached.
> ...
>> Signed-off-by: Lin Ming <mlin@ss.pku.edu.cn>
>> ---
>>  net/bridge/br_netfilter.c |    2 +-
>>  1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
>> index e41456b..10da415 100644
>> --- a/net/bridge/br_netfilter.c
>> +++ b/net/bridge/br_netfilter.c
>> @@ -719,7 +719,7 @@ static int br_nf_forward_finish(struct sk_buff *skb)
>>       struct nf_bridge_info *nf_bridge = skb->nf_bridge;
>>       struct net_device *in;
>>
>> -     if (!IS_ARP(skb) && !IS_VLAN_ARP(skb)) {
>> +     if (!IS_ARP(skb) && !IS_VLAN_ARP(skb) && nf_bridge) {
>>               in = nf_bridge->physindev;
>>               if (nf_bridge->mask & BRNF_PKT_TYPE) {
>>                       skb->pkt_type = PACKET_OTHERHOST;
>
> So after your patch we have the code in the else clause :
>
> } else {
>         in = *((struct net_device **)(skb->cb));
> }
>
> But do we really have a "struct net_device" pointer stored in skb->cb[]
> at this stage ?
>
> AFAIK this is set only for ARP_FORWARD (br_nf_forward_arp() line 838 :
> *d = (struct net_device *)in;),
> not in br_nf_forward_ip()
>
> If we have garbage instead, we can have other bugs later...

You are right.

The fundamental problem maybe in IPVS hook ip_vs_reply4 ......

^ permalink raw reply


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