Netdev List
 help / color / mirror / Atom feed
* Re: [RFC Patch] net: reserve ports for applications using fixed port numbers
From: Octavian Purdila @ 2010-02-04 18:15 UTC (permalink / raw)
  To: David Miller
  Cc: amwang-H+wXaHxf7aLQT0dZR+AlfA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	nhorman-2XuSBdqkA4R54TAoqtyWWQ, linux-sctp-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20100204.094110.64247447.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>

On Thursday 04 February 2010 19:41:10 you wrote:

> From: Octavian Purdila <opurdila-+zzKsuq53OdBDgjK7y7TUQ@public.gmane.org>
> Date: Thu, 4 Feb 2010 14:44:01 +0200
> 
> > My concern is that we can have multiple applications that require a
> > fixed port and if those ports are significantly apart we will
> > decrease the port range available for connect. And that will hurt
> > the rate of which new connections can be opened.
> 
> I'm already uneasy about adding the simple check every time
> we loop around in the bind port allocator.
> 
> Adding an LSM hook to this spot?  I absolutely refuse to allow
> that, it will completely kill bind performance.
> 

I think Tetsuo was proposing the LSM hook, so I'll leave him the daunting task 
of convincing you of the benefit of that :) - I have no opinion on this due to 
massive lack of knowledge.

I was just proposing to use a discrete set of ports instead of a range. The 
check in the current patch:

int inet_is_reserved_local_port(int port)
{
       int min, max;

       inet_get_local_reserved_ports(&min, &max);
       if (min && max)
               return (port >= min && port <= max);
       return 0;
}

would become:

int inet_is_reserved_local_port(int port)
{
	if (test_bit(port, reserved_ports))
		return 1;
	return 0;
}

In theory it might be slower because of the reserved_ports bitmap will have a 
larger memory footprint than just a min/max, especially with random port 
allocation. But is this an issue in practice?
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] net: emaclite: adding MDIO and phy lib support
From: Grant Likely @ 2010-02-04 18:12 UTC (permalink / raw)
  To: John Linn
  Cc: netdev, linuxppc-dev, jgarzik, jwboyer, john.williams,
	Sadanand Mutyala
In-Reply-To: <00044664-e9db-419f-88bd-4de21af118b6@VA3EHSMHS001.ehs.local>

Hi John and Sadanand.  Looks like a good patch, but a few issues to
resolve.  Comments below.

g.

On Wed, Feb 3, 2010 at 5:49 PM, John Linn <john.linn@xilinx.com> wrote:
> These changes add MDIO and phy lib support to the driver as the
> IP core now supports the MDIO bus.
>
> The MDIO bus and phy are added as a child to the emaclite in the device
> tree as illustrated below.
>
> mdio {
>        #address-cells = <1>;
>        #size-cells = <0>;
>        phy0: phy@7 {
>                reg = <7>;

For completeness, phy node need a "compatible" property.

>        } ;
> }
>
> Signed-off-by: Sadanand Mutyala <Sadanand.Mutyala@xilinx.com>
> Signed-off-by: John Linn <john.linn@xilinx.com>
> ---
>  drivers/net/Kconfig           |    1 +
>  drivers/net/xilinx_emaclite.c |  362 ++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 319 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 396fd38..2056cd2 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -1947,6 +1947,7 @@ config ATL2
>  config XILINX_EMACLITE
>        tristate "Xilinx 10/100 Ethernet Lite support"
>        depends on PPC32 || MICROBLAZE
> +       select PHYLIB
>        help
>          This driver supports the 10/100 Ethernet Lite from Xilinx.
>

Patch appears to be whitespace damaged.  All tabs have been converted to spaces.

> diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
> index 83a044d..8c7d7ae 100644
> --- a/drivers/net/xilinx_emaclite.c
> +++ b/drivers/net/xilinx_emaclite.c
> @@ -22,11 +22,17 @@
>
>  #include <linux/of_device.h>
>  #include <linux/of_platform.h>
> +#include <linux/of_mdio.h>
> +#include <linux/phy.h>
>
>  #define DRIVER_NAME "xilinx_emaclite"
>
>  /* Register offsets for the EmacLite Core */
>  #define XEL_TXBUFF_OFFSET      0x0             /* Transmit Buffer */
> +#define XEL_MDIOADDR_OFFSET    0x07E4          /* MDIO Address Register */
> +#define XEL_MDIOWR_OFFSET      0x07E8          /* MDIO Write Data Register */
> +#define XEL_MDIORD_OFFSET      0x07EC          /* MDIO Read Data Register */
> +#define XEL_MDIOCTRL_OFFSET    0x07F0          /* MDIO Control Register */
>  #define XEL_GIER_OFFSET                0x07F8          /* GIE Register */
>  #define XEL_TSR_OFFSET         0x07FC          /* Tx status */
>  #define XEL_TPLR_OFFSET                0x07F4          /* Tx packet length */
> @@ -37,6 +43,22 @@
>
>  #define XEL_BUFFER_OFFSET      0x0800          /* Next Tx/Rx buffer's offset */
>
> +/* MDIO Address Register Bit Masks */
> +#define XEL_MDIOADDR_REGADR_MASK  0x0000001F   /* Register Address */
> +#define XEL_MDIOADDR_PHYADR_MASK  0x000003E0   /* PHY Address */
> +#define XEL_MDIOADDR_PHYADR_SHIFT 5
> +#define XEL_MDIOADDR_OP_MASK     0x00000400    /* RD/WR Operation */
> +
> +/* MDIO Write Data Register Bit Masks */
> +#define XEL_MDIOWR_WRDATA_MASK   0x0000FFFF    /* Data to be Written */
> +
> +/* MDIO Read Data Register Bit Masks */
> +#define XEL_MDIORD_RDDATA_MASK   0x0000FFFF    /* Data to be Read */
> +
> +/* MDIO Control Register Bit Masks */
> +#define XEL_MDIOCTRL_MDIOSTS_MASK 0x00000001   /* MDIO Status Mask */
> +#define XEL_MDIOCTRL_MDIOEN_MASK  0x00000008   /* MDIO Enable */
> +
>  /* Global Interrupt Enable Register (GIER) Bit Masks */
>  #define XEL_GIER_GIE_MASK      0x80000000      /* Global Enable */
>
> @@ -87,6 +109,12 @@
>  * @reset_lock:                lock used for synchronization
>  * @deferred_skb:      holds an skb (for transmission at a later time) when the
>  *                     Tx buffer is not free
> + * @phy_dev:           pointer to the PHY device
> + * @phy_node:          pointer to the PHY device node
> + * @mii_bus:           pointer to the MII bus
> + * @mdio_irqs:         IRQs table for MDIO bus
> + * @last_link:         last link status
> + * @has_mdio:          indicates whether MDIO is included in the HW
>  */
>  struct net_local {
>
> @@ -100,6 +128,15 @@ struct net_local {
>
>        spinlock_t reset_lock;
>        struct sk_buff *deferred_skb;
> +
> +       struct phy_device *phy_dev;
> +       struct device_node *phy_node;
> +
> +       struct mii_bus *mii_bus;
> +       int mdio_irqs[PHY_MAX_ADDR];
> +
> +       int last_link;
> +       bool has_mdio;
>  };
>
>
> @@ -431,7 +468,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
>  }
>
>  /**
> - * xemaclite_set_mac_address - Set the MAC address for this device
> + * xemaclite_update_address - Update the MAC address in the device
>  * @drvdata:   Pointer to the Emaclite device private data
>  * @address_ptr:Pointer to the MAC address (MAC address is a 48-bit value)
>  *
> @@ -441,8 +478,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
>  * The MAC address can be programmed using any of the two transmit
>  * buffers (if configured).
>  */
> -static void xemaclite_set_mac_address(struct net_local *drvdata,
> -                                     u8 *address_ptr)
> +static void xemaclite_update_address(struct net_local *drvdata,
> +                                    u8 *address_ptr)
>  {
>        void __iomem *addr;
>        u32 reg_data;
> @@ -465,6 +502,30 @@ static void xemaclite_set_mac_address(struct net_local *drvdata,
>  }
>
>  /**
> + * xemaclite_set_mac_address - Set the MAC address for this device
> + * @dev:       Pointer to the network device instance
> + * @addr:      Void pointer to the sockaddr structure
> + *
> + * This function copies the HW address from the sockaddr strucutre to the
> + * net_device structure and updates the address in HW.
> + *
> + * Return:     Error if the net device is busy or 0 if the addr is set
> + *             successfully
> + */
> +static int xemaclite_set_mac_address(struct net_device *dev, void *address)
> +{
> +       struct net_local *lp = (struct net_local *) netdev_priv(dev);
> +       struct sockaddr *addr = address;
> +
> +       if (netif_running(dev))
> +               return -EBUSY;
> +
> +       memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
> +       xemaclite_update_address(lp, dev->dev_addr);
> +       return 0;
> +}
> +
> +/**
>  * xemaclite_tx_timeout - Callback for Tx Timeout
>  * @dev:       Pointer to the network device
>  *
> @@ -641,12 +702,195 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
>        return IRQ_HANDLED;
>  }
>
> +/**********************/
> +/* MDIO Bus functions */
> +/**********************/
> +/**
> + * xemaclite_mdio_read - Read from a given MII management register
> + * @bus:       the mii_bus struct
> + * @phy_id:    the phy address
> + * @reg:       register number to read from
> + *
> + * This function waits till the device is ready to accept a new MDIO
> + * request and then writes the phy address to the MDIO Address register
> + * and reads data from MDIO Read Data register, when its available.
> + *
> + * Return:     Value read from the MII management register
> + */
> +static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
> +{
> +       struct net_local *lp = bus->priv;
> +       u32 ctrl_reg;
> +       u32 rc;
> +
> +       /* Wait till the device is ready */
> +       do {
> +               ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
> +       } while (ctrl_reg & XEL_MDIOCTRL_MDIOSTS_MASK);

This is a busywait loop that just burns cycles while waiting for the
MDIO bus to become non-busy, and further down...

> +
> +       /* Write the PHY address, register number and set the OP bit in the
> +        * MDIO Address register. Set the Status bit in the MDIO Control
> +        * register to start a MDIO read transaction.
> +        */
> +       out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
> +                XEL_MDIOADDR_OP_MASK |
> +                ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
> +       out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
> +                ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
> +
> +       /* Wait for the device to complete the transaction and read the value
> +        * from MDIO Read Data register.
> +        */
> +       do {
> +               ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
> +       } while (ctrl_reg & XEL_MDIOCTRL_MDIOSTS_MASK);

... I see the same thing waiting for the issued transaction to
complete.  Busywaiting on slow events, like MDIO transfers, wastes a
lot of cycles that could be used for running other threads.

At the very least, the wait loop should msleep() so that other threads
get scheduled.  Even better is if a completion is used and the MDIO
irq can be used to wake up the thread.

Another problem with this busywait is that is has no failure path if
the MDIO bus hangs up.  The thread could get stuck spinning on this
loop forever with no way to kill it.

> +       rc = in_be32(lp->base_addr + XEL_MDIORD_OFFSET);
> +
> +       dev_dbg(&lp->ndev->dev,
> +               "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
> +               phy_id, reg, rc);
> +
> +       return rc;
> +}
> +
> +/**
> + * xemaclite_mdio_write - Write to a given MII management register
> + * @bus:       the mii_bus struct
> + * @phy_id:    the phy address
> + * @reg:       register number to write to
> + * @val:       value to write to the register number specified by reg
> + *
> + * This fucntion waits till the device is ready to accept a new MDIO
> + * request and then writes the val to the MDIO Write Data register.
> + */
> +static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
> +                               u16 val)
> +{
> +       struct net_local *lp = bus->priv;
> +       u32 ctrl_reg;
> +
> +       dev_dbg(&lp->ndev->dev,
> +               "xemaclite_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
> +               phy_id, reg, val);
> +
> +       /* Wait till the device is ready */
> +       do {
> +               ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
> +       } while (ctrl_reg & XEL_MDIOCTRL_MDIOSTS_MASK);

Ditto here.  In fact, this is a common pattern used 4 times in this
patch.  Probably a candidate to break out into a subroutine.

> +
> +       /* Write the PHY address, register number and clear the OP bit in the
> +        * MDIO Address register and then write the value into the MDIO Write
> +        * Data register. Finally, set the Status bit in the MDIO Control
> +        * register to start a MDIO write transaction.
> +        */
> +       out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
> +                ~XEL_MDIOADDR_OP_MASK &
> +                ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
> +       out_be32(lp->base_addr + XEL_MDIOWR_OFFSET, val);
> +       out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
> +                ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
> +
> +       return 0;
> +}
> +
> +/**
> + * xemaclite_mdio_reset - Reset the mdio bus.
> + * @bus:       Pointer to the MII bus
> + *
> + * This function is required(?) as per Documentation/networking/phy.txt.
> + * There is no reset in this device; this function always returns 0.
> + */
> +static int xemaclite_mdio_reset(struct mii_bus *bus)
> +{
> +       return 0;
> +}
> +
> +/**
> + * xemaclite_mdio_setup - Register mii_bus for the Emaclite device
> + * @lp:                Pointer to the Emaclite device private data
> + * @ofdev:     Pointer to OF device structure
> + *
> + * This function enables MDIO bus in the Emaclite device and registers a
> + * mii_bus.
> + *
> + * Return:     0 upon success or a negative error upon failure
> + */
> +static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
> +{
> +       struct mii_bus *bus;
> +       int rc;
> +       struct resource res;
> +       struct device_node *np = of_get_parent(lp->phy_node);
> +
> +       /* Don't register the MDIO bus if the phy_node or its parent node
> +        * can't be found.
> +        */
> +       if (!np)
> +               return -ENODEV;
> +
> +       /* Enable the MDIO bus by asserting the enable bit in MDIO Control
> +        * register.
> +        */
> +       out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
> +                XEL_MDIOCTRL_MDIOEN_MASK);
> +
> +       bus = mdiobus_alloc();
> +       if (!bus)
> +               return -ENOMEM;
> +
> +       of_address_to_resource(np, 0, &res);
> +       snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
> +                (unsigned long long)res.start);
> +       bus->priv = lp;
> +       bus->name = "Xilinx Emaclite MDIO";
> +       bus->read = xemaclite_mdio_read;
> +       bus->write = xemaclite_mdio_write;
> +       bus->reset = xemaclite_mdio_reset;
> +       bus->parent = dev;
> +       bus->irq = lp->mdio_irqs; /* preallocated IRQ table */
> +
> +       lp->mii_bus = bus;
> +
> +       rc = of_mdiobus_register(bus, np);
> +       if (rc)
> +               goto err_register;
> +
> +       return 0;
> +
> +err_register:
> +       mdiobus_free(bus);
> +       return rc;
> +}
> +
> +/**
> + * xemaclite_adjust_link - Link state callback for the Emaclite device
> + * @ndev: pointer to net_device struct
> + *
> + * 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)
> +{
> +       struct net_local *lp = netdev_priv(ndev);
> +       struct phy_device *phy = lp->phy_dev;
> +       int link_state;
> +
> +       /* hash together the state values to decide if something has changed */
> +       link_state = phy->speed | (phy->duplex << 1) | phy->link;
> +
> +       if (lp->last_link != link_state) {
> +               lp->last_link = link_state;
> +               phy_print_status(phy);
> +       }
> +}
> +
>  /**
>  * xemaclite_open - Open the network device
>  * @dev:       Pointer to the network device
>  *
>  * This function sets the MAC address, requests an IRQ and enables interrupts
>  * for the Emaclite device and starts the Tx queue.
> + * It also connects to the phy device, if MDIO is included in Emaclite device.
>  */
>  static int xemaclite_open(struct net_device *dev)
>  {
> @@ -656,14 +900,50 @@ static int xemaclite_open(struct net_device *dev)
>        /* Just to be safe, stop the device first */
>        xemaclite_disable_interrupts(lp);
>
> +       if (lp->phy_node) {
> +               u32 bmcr;
> +
> +               lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
> +                                            xemaclite_adjust_link, 0,
> +                                            PHY_INTERFACE_MODE_MII);
> +               if (!lp->phy_dev) {
> +                       dev_err(&lp->ndev->dev, "of_phy_connect() failed\n");
> +                       return -ENODEV;
> +               }
> +
> +               /* EmacLite doesn't support giga-bit speeds */
> +               lp->phy_dev->supported &= (PHY_BASIC_FEATURES);
> +               lp->phy_dev->advertising = lp->phy_dev->supported;
> +
> +               /* Don't advertise 1000BASE-T Full/Half duplex speeds */
> +               xemaclite_mdio_write(lp->mii_bus, lp->phy_dev->addr,
> +                                    MII_CTRL1000, 0x00);
> +               /* Advertise only 10 and 100mbps full/half duplex speeds */
> +               xemaclite_mdio_write(lp->mii_bus, lp->phy_dev->addr,
> +                                    MII_ADVERTISE, ADVERTISE_ALL);
> +
> +               /* Restart auto negotiation */
> +               bmcr = xemaclite_mdio_read(lp->mii_bus,
> +                                          lp->phy_dev->addr, MII_BMCR);
> +               bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
> +               xemaclite_mdio_write(lp->mii_bus, lp->phy_dev->addr,
> +                                    MII_BMCR, bmcr);
> +
> +               phy_start(lp->phy_dev);
> +       }
> +
>        /* Set the MAC address each time opened */
> -       xemaclite_set_mac_address(lp, dev->dev_addr);
> +       xemaclite_update_address(lp, dev->dev_addr);
>
>        /* Grab the IRQ */
>        retval = request_irq(dev->irq, xemaclite_interrupt, 0, dev->name, dev);
>        if (retval) {
>                dev_err(&lp->ndev->dev, "Could not allocate interrupt %d\n",
>                        dev->irq);
> +               if (lp->phy_dev)
> +                       phy_disconnect(lp->phy_dev);
> +               lp->phy_dev = NULL;
> +
>                return retval;
>        }
>
> @@ -682,6 +962,7 @@ static int xemaclite_open(struct net_device *dev)
>  *
>  * This function stops the Tx queue, disables interrupts and frees the IRQ for
>  * the Emaclite device.
> + * It also disconnects the phy device associated with the Emaclite device.
>  */
>  static int xemaclite_close(struct net_device *dev)
>  {
> @@ -691,6 +972,10 @@ static int xemaclite_close(struct net_device *dev)
>        xemaclite_disable_interrupts(lp);
>        free_irq(dev->irq, dev);
>
> +       if (lp->phy_dev)
> +               phy_disconnect(lp->phy_dev);
> +       lp->phy_dev = NULL;
> +
>        return 0;
>  }
>
> @@ -754,42 +1039,6 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
>  }
>
>  /**
> - * xemaclite_ioctl - Perform IO Control operations on the network device
> - * @dev:       Pointer to the network device
> - * @rq:                Pointer to the interface request structure
> - * @cmd:       IOCTL command
> - *
> - * The only IOCTL operation supported by this function is setting the MAC
> - * address. An error is reported if any other operations are requested.
> - *
> - * Return:     0 to indicate success, or a negative error for failure.
> - */
> -static int xemaclite_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
> -{
> -       struct net_local *lp = (struct net_local *) netdev_priv(dev);
> -       struct hw_addr_data *hw_addr = (struct hw_addr_data *) &rq->ifr_hwaddr;
> -
> -       switch (cmd) {
> -       case SIOCETHTOOL:
> -               return -EIO;
> -
> -       case SIOCSIFHWADDR:
> -               dev_err(&lp->ndev->dev, "SIOCSIFHWADDR\n");
> -
> -               /* Copy MAC address in from user space */
> -               copy_from_user((void __force *) dev->dev_addr,
> -                              (void __user __force *) hw_addr,
> -                              IFHWADDRLEN);
> -               xemaclite_set_mac_address(lp, dev->dev_addr);
> -               break;
> -       default:
> -               return -EOPNOTSUPP;
> -       }
> -
> -       return 0;
> -}
> -
> -/**
>  * xemaclite_remove_ndev - Free the network device
>  * @ndev:      Pointer to the network device to be freed
>  *
> @@ -840,6 +1089,8 @@ static struct net_device_ops xemaclite_netdev_ops;
>  * This function probes for the Emaclite device in the device tree.
>  * It initializes the driver data structure and the hardware, sets the MAC
>  * address and registers the network device.
> + * It also registers a mii_bus for the Emaclite device, if MDIO is included
> + * in the device.
>  *
>  * Return:     0, if the driver is bound to the Emaclite device, or
>  *             a negative error if there is failure.
> @@ -853,7 +1104,6 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev,
>        struct net_local *lp = NULL;
>        struct device *dev = &ofdev->dev;
>        const void *mac_address;
> -

Unrelated whitespace change.

>        int rc = 0;
>
>        dev_info(dev, "Device Tree Probing\n");
> @@ -880,6 +1130,7 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev,
>        }
>
>        dev_set_drvdata(dev, ndev);
> +       SET_NETDEV_DEV(ndev, &ofdev->dev);
>
>        ndev->irq = r_irq.start;
>        ndev->mem_start = r_mem.start;
> @@ -923,7 +1174,16 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev,
>        out_be32(lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0);
>
>        /* Set the MAC address in the EmacLite device */
> -       xemaclite_set_mac_address(lp, ndev->dev_addr);
> +       xemaclite_update_address(lp, ndev->dev_addr);
> +
> +       /* Check if MDIO is included in the HW */
> +       lp->has_mdio = get_bool(ofdev, "xlnx,include-mdio");
> +       if (lp->has_mdio) {
> +               lp->phy_node = of_parse_phandle(ofdev->node, "phy-handle", 0);
> +               rc = xemaclite_mdio_setup(lp, &ofdev->dev);
> +               if (rc)
> +                       dev_warn(&ofdev->dev, "error registering MDIO bus\n");
> +       }

What if the phy is attached to a different MDIO bus (which is
completely possible)?  The fetching of phy_node should be performed
regardless of whether or not xlnx,include-mdio is set.

>
>        dev_info(dev,
>                 "MAC address is now %2x:%2x:%2x:%2x:%2x:%2x\n",
> @@ -972,12 +1232,25 @@ static int __devexit xemaclite_of_remove(struct of_device *of_dev)
>        struct device *dev = &of_dev->dev;
>        struct net_device *ndev = dev_get_drvdata(dev);
>
> +       struct net_local *lp = (struct net_local *) netdev_priv(ndev);
> +
> +       /* Un-register the mii_bus, if configured */
> +       if (lp->has_mdio) {
> +               mdiobus_unregister(lp->mii_bus);
> +               kfree(lp->mii_bus->irq);
> +               mdiobus_free(lp->mii_bus);
> +               lp->mii_bus = NULL;
> +       }
> +
>        unregister_netdev(ndev);
>
> +       if (lp->phy_node)
> +               of_node_put(lp->phy_node);
> +       lp->phy_node = NULL;
> +
>        release_mem_region(ndev->mem_start, ndev->mem_end-ndev->mem_start + 1);
>
>        xemaclite_remove_ndev(ndev);
> -
>        dev_set_drvdata(dev, NULL);
>
>        return 0;
> @@ -987,7 +1260,7 @@ static struct net_device_ops xemaclite_netdev_ops = {
>        .ndo_open               = xemaclite_open,
>        .ndo_stop               = xemaclite_close,
>        .ndo_start_xmit         = xemaclite_send,
> -       .ndo_do_ioctl           = xemaclite_ioctl,
> +       .ndo_set_mac_address    = xemaclite_set_mac_address,
>        .ndo_tx_timeout         = xemaclite_tx_timeout,
>        .ndo_get_stats          = xemaclite_get_stats,
>  };
> @@ -999,6 +1272,7 @@ static struct of_device_id xemaclite_of_match[] __devinitdata = {
>        { .compatible = "xlnx,xps-ethernetlite-1.00.a", },
>        { .compatible = "xlnx,xps-ethernetlite-2.00.a", },
>        { .compatible = "xlnx,xps-ethernetlite-2.01.a", },
> +       { .compatible = "xlnx,xps-ethernetlite-3.00.a", },
>        { /* end of list */ },
>  };
>  MODULE_DEVICE_TABLE(of, xemaclite_of_match);
> --
> 1.6.2.1
>
>
>
> This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
>
>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [net-2.6 PATCH] igb: make certain to reassign legacy interrupt vectors after reset
From: David Miller @ 2010-02-04 17:49 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, alexander.h.duyck
In-Reply-To: <20100204075925.16897.84090.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 03 Feb 2010 23:59:51 -0800

> From: Alexander Duyck <alexander.h.duyck@intel.com>
> 
> This change corrects an issue that will cause false hangs when using either
> 82575 or 82580 in legacy interrupt mode.  The issue is caused when there is
> a slow traffic flow and an "ethtool -r" is executed while using legacy or
> MSI interrupts.  MSI-X is not affected by this issue due to the fact that
> we were already reconfiguring the vectors after reset.
> 
> If possible it would be best to push this for net-2.6 since it is resolving
> a bug but if that is not possible then net-next-2.6 will be fine.
> 
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied, thanks.

^ permalink raw reply

* Re: [RFC Patch] net: reserve ports for applications using fixed port numbers
From: David Miller @ 2010-02-04 17:41 UTC (permalink / raw)
  To: opurdila-+zzKsuq53OdBDgjK7y7TUQ
  Cc: amwang-H+wXaHxf7aLQT0dZR+AlfA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	nhorman-2XuSBdqkA4R54TAoqtyWWQ, linux-sctp-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <201002041444.01897.opurdila-+zzKsuq53OdBDgjK7y7TUQ@public.gmane.org>

From: Octavian Purdila <opurdila-+zzKsuq53OdBDgjK7y7TUQ@public.gmane.org>
Date: Thu, 4 Feb 2010 14:44:01 +0200

> My concern is that we can have multiple applications that require a
> fixed port and if those ports are significantly apart we will
> decrease the port range available for connect. And that will hurt
> the rate of which new connections can be opened.

I'm already uneasy about adding the simple check every time
we loop around in the bind port allocator.

Adding an LSM hook to this spot?  I absolutely refuse to allow
that, it will completely kill bind performance.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: linux-next: manual merge of the trivial tree with the net tree
From: David Miller @ 2010-02-04 17:33 UTC (permalink / raw)
  To: peppe.cavallaro
  Cc: jkosina, sfr, linux-next, linux-kernel, lsorense, netdev, daniel
In-Reply-To: <4B6AD11D.6050402@st.com>

From: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
Date: Thu, 04 Feb 2010 14:52:29 +0100

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Giuseppe CAVALLARO wrote:
>> Hi Jiri,
>> 
>> The stmmac driver included in net-next has been restructured: for this
>> reason both gmac.c and mac100.c files do not exist any more.
>> 
>> Let me know if I can help on this; I mean I'm happy to apply this latest
>> changes to the stmmac in net-next and send a new patch.
> 
> patch attached
> I hope it could be useful.

Applied, thank you.

^ permalink raw reply

* Re: [PATCH for 2.6.33] conntrack: restrict runtime hashsize modifications
From: Patrick McHardy @ 2010-02-04 17:26 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: davem, jonathan, eric.dumazet, netdev, netfilter-devel
In-Reply-To: <20100203203929.GA6168@x200>

Alexey Dobriyan wrote:
> Jon Masters correctly points out that conntrack hash sizes
> (nf_conntrack_htable_size) are global (not per-netns) and
> modifiable at runtime via /sys/module/nf_conntrack/hashsize .
> 
> Steps to reproduce:
> 	clone(CLONE_NEWNET)
> 	[grow /sys/module/nf_conntrack/hashsize]
> 	exit()
> 
> At netns exit we are going to scan random memory for conntracks to be killed.
> 
> Apparently there is a code which deals with hashtable resize for
> init_net (and it was there befode netns conntrack code), so prohibit
> hashsize modification if there is more than one netns exists.
> 
> To change hashtable sizes, you need to reload module.
> 
> Expectation hashtable size was simply glued to a variable with no code
> to rehash expectations, so it was a bug to allow writing to it.
> Make "expect_hashsize" readonly.

I've applied the expectation part, thanks Alexey.

> --- a/net/netfilter/nf_conntrack_expect.c
> +++ b/net/netfilter/nf_conntrack_expect.c
> @@ -569,7 +569,7 @@ static void exp_proc_remove(struct net *net)
>  #endif /* CONFIG_PROC_FS */
>  }
>  
> -module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
> +module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400);
>  
>  int nf_conntrack_expect_init(struct net *net)
>  {
> 


^ permalink raw reply

* Re: [PATCH] can: ems_usb: removed duplicated code setting local echo support
From: David Miller @ 2010-02-04 17:21 UTC (permalink / raw)
  To: cascardo; +Cc: urs.thuermann, oliver.hartkopp, netdev, linux-kernel
In-Reply-To: <1265297624-1853-1-git-send-email-cascardo@holoscopio.com>

From: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
Date: Thu,  4 Feb 2010 13:33:44 -0200

> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>

Applied, thanks.

^ permalink raw reply

* Re: [net-next-2.6 PATCH v2 1/3] ethtool: Introduce n-tuple filter programming support
From: David Miller @ 2010-02-04 17:18 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, peter.p.waskiewicz.jr
In-Reply-To: <20100204074811.16559.84676.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 03 Feb 2010 23:48:13 -0800

> +#define ETHTOOL_RXNTUPLE_ACTION_DROP -1
> +	struct list_head list;
> +};

You can't do this.

You put the list_head here in the kernel header, which BTW can
be used by userspace too, and then you elide it in the
ethtool utility copy of the header.

Use an encapsulator if you must inside of the kernel, but keep the
userspace visible data structure clean of RCU and list_head
kernel datastructures.

Thanks.


^ permalink raw reply

* [RFC 4/4] bond: add new multiqueue hash policy
From: Stephen Hemminger @ 2010-02-04 17:11 UTC (permalink / raw)
  To: David Miller, Jay Vosburgh; +Cc: netdev, bonding-devel
In-Reply-To: <20100204171118.917737392@vyatta.com>

[-- Attachment #1: bond-jhash.patch --]
[-- Type: text/plain, Size: 1686 bytes --]

This hash policy just uses existing transmit hash used for
mulitiqueue.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/drivers/net/bonding/bond_main.c	2010-02-04 08:57:52.356755294 -0800
+++ b/drivers/net/bonding/bond_main.c	2010-02-04 08:57:53.036755256 -0800
@@ -190,6 +190,7 @@ const struct bond_parm_tbl xmit_hashtype
 {	"layer2",		BOND_XMIT_POLICY_LAYER2},
 {	"layer3+4",		BOND_XMIT_POLICY_LAYER34},
 {	"layer2+3",		BOND_XMIT_POLICY_LAYER23},
+{       "multiqueue",		BOND_XMIT_POLICY_MQ},
 {	NULL,			-1},
 };
 
@@ -3670,6 +3671,13 @@ static u16 bond_xmit_hash_policy_l34(con
 
 }
 
+/*
+ * Hash for the output device based on multiqueue transmit hash policy
+ */
+static u16 bond_xmit_hash_policy_mq(const struct sk_buff *skb)
+{
+	return skb_tx_hash(skb->dev, skb);
+}
 
 /*-------------------------- Device entry points ----------------------------*/
 
@@ -4350,6 +4358,9 @@ out:
 static void bond_set_xmit_hash_policy(struct bonding *bond)
 {
 	switch (bond->params.xmit_policy) {
+	case BOND_XMIT_POLICY_MQ:
+		bond->xmit_hash_policy = bond_xmit_hash_policy_mq;
+		break;
 	case BOND_XMIT_POLICY_LAYER23:
 		bond->xmit_hash_policy = bond_xmit_hash_policy_l23;
 		break;
--- a/include/linux/if_bonding.h	2010-02-04 08:56:35.956131096 -0800
+++ b/include/linux/if_bonding.h	2010-02-04 08:57:53.036755256 -0800
@@ -87,6 +87,7 @@
 #define BOND_XMIT_POLICY_LAYER2		0 /* layer 2 (MAC only), default */
 #define BOND_XMIT_POLICY_LAYER34	1 /* layer 3+4 (IP ^ (TCP || UDP)) */
 #define BOND_XMIT_POLICY_LAYER23	2 /* layer 2+3 (IP ^ MAC) */
+#define BOND_XMIT_POLICY_MQ             3 /* transmit hash (multiqueue) */
 
 typedef struct ifbond {
 	__s32 bond_mode;

-- 


^ permalink raw reply

* [RFC 3/4] bond: support more Layer 4 protocols
From: Stephen Hemminger @ 2010-02-04 17:11 UTC (permalink / raw)
  To: David Miller, Jay Vosburgh; +Cc: netdev, bonding-devel
In-Reply-To: <20100204171118.917737392@vyatta.com>

[-- Attachment #1: bond-more-proto.patch --]
[-- Type: text/plain, Size: 1752 bytes --]

There are several protocols similar to TCP and UDP which share common L4
header format. Since proto is only one byte, use a map rather than big
conditonal.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

--- a/drivers/net/bonding/bond_main.c	2010-02-04 09:08:00.447069200 -0800
+++ b/drivers/net/bonding/bond_main.c	2010-02-04 09:08:42.545818691 -0800
@@ -3621,6 +3621,16 @@ static u16 bond_xmit_hash_policy_l23(con
 	}
 }
 
+/* Map of protocols with standard ports available to include in hash */
+static const bool has_layer4[256] = {
+	[IPPROTO_TCP] = 1,
+	[IPPROTO_UDP] = 1,
+	[IPPROTO_UDPLITE] = 1,
+	[IPPROTO_SCTP] = 1,
+	[IPPROTO_DCCP] = 1,
+	[IPPROTO_ESP] = 1,
+};
+
 /*
  * Hash for the output device based upon layer 3 and layer 4 data. If
  * the packet is a frag or not TCP or UDP, just use layer 3 data.  If it is
@@ -3634,11 +3644,10 @@ static u16 bond_xmit_hash_policy_l34(con
 		const struct iphdr *iph = ip_hdr(skb);
 		const __be16 *layer4hdr
 			= ((const void *)iph + iph->ihl);
-		u32 layer4_xor = 0;
+		u16 layer4_xor = 0;
 
 		if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) &&
-		    (iph->protocol == IPPROTO_TCP ||
-		     iph->protocol == IPPROTO_UDP))
+		    has_layer4[iph->protocol])
 			layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
 
 		return layer4_xor ^ ntohl(iph->saddr ^ iph->daddr);
@@ -3647,10 +3656,9 @@ static u16 bond_xmit_hash_policy_l34(con
 	{
 		const struct ipv6hdr *iph = ipv6_hdr(skb);
 		const __be16 *layer4hdr = (const __be16 *) (iph + 1);
-		u32 layer4_xor = 0;
+		u16 layer4_xor = 0;
 
-		if (iph->nexthdr == IPPROTO_TCP ||
-		     iph->nexthdr == IPPROTO_UDP)
+		if (has_layer4[iph->nexthdr])
 			layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
 
 		return layer4_xor ^

-- 


^ permalink raw reply

* [RFC 2/4] bond: add IPV6 layer3 hash policy support
From: Stephen Hemminger @ 2010-02-04 17:11 UTC (permalink / raw)
  To: David Miller, Jay Vosburgh; +Cc: netdev, bonding-devel
In-Reply-To: <20100204171118.917737392@vyatta.com>

[-- Attachment #1: bond-ipv6.patch --]
[-- Type: text/plain, Size: 2176 bytes --]

Add IPV6 support to Layer 3 and Layer 3+4 hash policies.
Code take fron SFQ.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>


--- a/drivers/net/bonding/bond_main.c	2010-02-04 08:58:54.617692952 -0800
+++ b/drivers/net/bonding/bond_main.c	2010-02-04 09:08:00.447069200 -0800
@@ -3601,13 +3601,24 @@ static u16 bond_xmit_hash_policy_l23(con
 {
 	const struct ethhdr *data = eth_hdr(skb);
 
-	if (skb->protocol == htons(ETH_P_IP)) {
+	switch (skb->protocol) {
+	case htons(ETH_P_IP):
+	{
 		const struct iphdr *iph = ip_hdr(skb);
 		return ntohl(iph->saddr ^ iph->daddr) ^
 			(data->h_dest[5] ^ data->h_source[5]);
 	}
+	case htons(ETH_P_IPV6):
+	{
+		const struct ipv6hdr *iph = ipv6_hdr(skb);
+		return ntohl(iph->saddr.s6_addr32[3] ^
+			     iph->daddr.s6_addr32[3]) ^
+			(data->h_dest[5] ^ data->h_source[5]);
 
-	return bond_xmit_hash_policy_l2(skb);
+	}
+	default:
+		return bond_xmit_hash_policy_l2(skb);
+	}
 }
 
 /*
@@ -3617,9 +3628,9 @@ static u16 bond_xmit_hash_policy_l23(con
  */
 static u16 bond_xmit_hash_policy_l34(const struct sk_buff *skb)
 {
-	const struct ethhdr *data = eth_hdr(skb);
-
-	if (skb->protocol == htons(ETH_P_IP)) {
+	switch (skb->protocol) {
+	case htons(ETH_P_IP):
+	{
 		const struct iphdr *iph = ip_hdr(skb);
 		const __be16 *layer4hdr
 			= ((const void *)iph + iph->ihl);
@@ -3627,14 +3638,28 @@ static u16 bond_xmit_hash_policy_l34(con
 
 		if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) &&
 		    (iph->protocol == IPPROTO_TCP ||
-		     iph->protocol == IPPROTO_UDP)) {
+		     iph->protocol == IPPROTO_UDP))
 			layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
-		}
+
 		return layer4_xor ^ ntohl(iph->saddr ^ iph->daddr);
+	}
+	case htons(ETH_P_IPV6):
+	{
+		const struct ipv6hdr *iph = ipv6_hdr(skb);
+		const __be16 *layer4hdr = (const __be16 *) (iph + 1);
+		u32 layer4_xor = 0;
 
+		if (iph->nexthdr == IPPROTO_TCP ||
+		     iph->nexthdr == IPPROTO_UDP)
+			layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
+
+		return layer4_xor ^
+			ntohl(iph->saddr.s6_addr32[3] ^ iph->daddr.s6_addr32[3]);
+	}
+	default:
+		return bond_xmit_hash_policy_l2(skb);
 	}
 
-	return bond_xmit_hash_policy_l2(skb);
 }
 
 

-- 


^ permalink raw reply

* [RFC 1/4] bond: cleanup transmit hash policy interface
From: Stephen Hemminger @ 2010-02-04 17:11 UTC (permalink / raw)
  To: David Miller, Jay Vosburgh; +Cc: netdev, bonding-devel
In-Reply-To: <20100204171118.917737392@vyatta.com>

[-- Attachment #1: bond-hash1.patch --]
[-- Type: text/plain, Size: 4288 bytes --]

Some minor cleanups of hash policy with no change in resulting
interface.
  1. Do modulus operation in caller rather than policy
  2. Pass skb as constant pointer
  3. Use common code for layer 2 policy hash

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>


--- a/drivers/net/bonding/bond_3ad.c	2010-02-04 08:56:36.106130909 -0800
+++ b/drivers/net/bonding/bond_3ad.c	2010-02-04 08:57:46.736130667 -0800
@@ -2413,7 +2413,7 @@ int bond_3ad_xmit_xor(struct sk_buff *sk
 		goto out;
 	}
 
-	slave_agg_no = bond->xmit_hash_policy(skb, slaves_in_agg);
+	slave_agg_no = bond->xmit_hash_policy(skb) % slaves_in_agg;
 
 	bond_for_each_slave(bond, slave, i) {
 		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
--- a/drivers/net/bonding/bond_main.c	2010-02-04 08:56:56.015821641 -0800
+++ b/drivers/net/bonding/bond_main.c	2010-02-04 08:57:46.736130667 -0800
@@ -3584,20 +3584,30 @@ void bond_unregister_arp(struct bonding 
 /*---------------------------- Hashing Policies -----------------------------*/
 
 /*
+ * Hash for the output device based upon layer 2 data
+ */
+static u16 bond_xmit_hash_policy_l2(const struct sk_buff *skb)
+{
+	const struct ethhdr *data = eth_hdr(skb);
+
+	return data->h_dest[5] ^ data->h_source[5];
+}
+
+/*
  * Hash for the output device based upon layer 2 and layer 3 data. If
  * the packet is not IP mimic bond_xmit_hash_policy_l2()
  */
-static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
+static u16 bond_xmit_hash_policy_l23(const struct sk_buff *skb)
 {
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-	struct iphdr *iph = ip_hdr(skb);
+	const struct ethhdr *data = eth_hdr(skb);
 
 	if (skb->protocol == htons(ETH_P_IP)) {
-		return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
-			(data->h_dest[5] ^ data->h_source[5])) % count;
+		const struct iphdr *iph = ip_hdr(skb);
+		return ntohl(iph->saddr ^ iph->daddr) ^
+			(data->h_dest[5] ^ data->h_source[5]);
 	}
 
-	return (data->h_dest[5] ^ data->h_source[5]) % count;
+	return bond_xmit_hash_policy_l2(skb);
 }
 
 /*
@@ -3605,36 +3615,28 @@ static int bond_xmit_hash_policy_l23(str
  * the packet is a frag or not TCP or UDP, just use layer 3 data.  If it is
  * altogether not IP, mimic bond_xmit_hash_policy_l2()
  */
-static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
+static u16 bond_xmit_hash_policy_l34(const struct sk_buff *skb)
 {
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-	struct iphdr *iph = ip_hdr(skb);
-	__be16 *layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
-	int layer4_xor = 0;
+	const struct ethhdr *data = eth_hdr(skb);
 
 	if (skb->protocol == htons(ETH_P_IP)) {
+		const struct iphdr *iph = ip_hdr(skb);
+		const __be16 *layer4hdr
+			= ((const void *)iph + iph->ihl);
+		u32 layer4_xor = 0;
+
 		if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) &&
 		    (iph->protocol == IPPROTO_TCP ||
 		     iph->protocol == IPPROTO_UDP)) {
 			layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1)));
 		}
-		return (layer4_xor ^
-			((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
+		return layer4_xor ^ ntohl(iph->saddr ^ iph->daddr);
 
 	}
 
-	return (data->h_dest[5] ^ data->h_source[5]) % count;
+	return bond_xmit_hash_policy_l2(skb);
 }
 
-/*
- * Hash for the output device based upon layer 2 data
- */
-static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
-{
-	struct ethhdr *data = (struct ethhdr *)skb->data;
-
-	return (data->h_dest[5] ^ data->h_source[5]) % count;
-}
 
 /*-------------------------- Device entry points ----------------------------*/
 
@@ -4224,7 +4226,7 @@ static int bond_xmit_xor(struct sk_buff 
 	if (!BOND_IS_OK(bond))
 		goto out;
 
-	slave_no = bond->xmit_hash_policy(skb, bond->slave_cnt);
+	slave_no = bond->xmit_hash_policy(skb) %  bond->slave_cnt;
 
 	bond_for_each_slave(bond, slave, i) {
 		slave_no--;
--- a/drivers/net/bonding/bonding.h	2010-02-04 08:56:56.015821641 -0800
+++ b/drivers/net/bonding/bonding.h	2010-02-04 08:57:46.736130667 -0800
@@ -203,7 +203,7 @@ struct bonding {
 #endif /* CONFIG_PROC_FS */
 	struct   list_head bond_list;
 	struct   dev_mc_list *mc_list;
-	int      (*xmit_hash_policy)(struct sk_buff *, int);
+	u16      (*xmit_hash_policy)(const struct sk_buff *);
 	__be32   master_ip;
 	u16      flags;
 	u16      rr_tx_counter;

-- 


^ permalink raw reply

* [RFC 0/4] bond hashing revised
From: Stephen Hemminger @ 2010-02-04 17:11 UTC (permalink / raw)
  To: David Miller, Jay Vosburgh; +Cc: netdev, bonding-devel

These have not been tested yet. I need to try them with some
different flows/hardware to validate.

-- 


^ permalink raw reply

* Re: [PATCH for 2.6.33] conntrack: restrict runtime hashsize modifications
From: Patrick McHardy @ 2010-02-04 17:04 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: davem, jonathan, eric.dumazet, netdev, netfilter-devel
In-Reply-To: <4B6AF36A.3050402@trash.net>

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

Patrick McHardy wrote:
> Alexey Dobriyan wrote:
>> Jon Masters correctly points out that conntrack hash sizes
>> (nf_conntrack_htable_size) are global (not per-netns) and
>> modifiable at runtime via /sys/module/nf_conntrack/hashsize .
>>
>> Steps to reproduce:
>> 	clone(CLONE_NEWNET)
>> 	[grow /sys/module/nf_conntrack/hashsize]
>> 	exit()
>>
>> At netns exit we are going to scan random memory for conntracks to be killed.
>>
>> Apparently there is a code which deals with hashtable resize for
>> init_net (and it was there befode netns conntrack code), so prohibit
>> hashsize modification if there is more than one netns exists.
>>
>> To change hashtable sizes, you need to reload module.
>>
>> Expectation hashtable size was simply glued to a variable with no code
>> to rehash expectations, so it was a bug to allow writing to it.
>> Make "expect_hashsize" readonly.
>>
>> This is temporarily until we figure out what to do.
> 
> How about alternatively moving nf_conntrack_hsize into the
> per-namespace struct? It doesn't look more complicated or
> intrusive and would allow to still change the init_net
> hashsize. Also seems less hackish :)

How about this (so far untested) patch? The htable_size is moved into
the per-namespace struct and initialized from the current (global)
value of nf_conntrack_htable_size. Changes through sysfs are still
permitted, but only affect the init namespace and newly created ones.

Additionally I removed reinitializing the hash random value when
changing the hash size since that also requires to rehash in all
namespaces.

[-- Attachment #2: x --]
[-- Type: text/plain, Size: 15175 bytes --]

diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index aed23b6..63d4498 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -11,6 +11,7 @@ struct nf_conntrack_ecache;
 struct netns_ct {
 	atomic_t		count;
 	unsigned int		expect_count;
+	unsigned int		htable_size;
 	struct kmem_cache	*nf_conntrack_cachep;
 	struct hlist_nulls_head	*hash;
 	struct hlist_head	*expect_hash;
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 2eb3814..9a4b8b7 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -40,6 +40,7 @@ struct netns_ipv4 {
 	struct xt_table		*iptable_security;
 	struct xt_table		*nat_table;
 	struct hlist_head	*nat_bysource;
+	unsigned int		nat_htable_size;
 	int			nat_vmalloced;
 #endif
 
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index d171b12..d1ea38a 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -210,7 +210,7 @@ static ctl_table ip_ct_sysctl_table[] = {
 	},
 	{
 		.procname	= "ip_conntrack_buckets",
-		.data		= &nf_conntrack_htable_size,
+		.data		= &init_net.ct.htable_size,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0444,
 		.proc_handler	= proc_dointvec,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 8668a3d..2fb7b76 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -32,7 +32,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq)
 	struct hlist_nulls_node *n;
 
 	for (st->bucket = 0;
-	     st->bucket < nf_conntrack_htable_size;
+	     st->bucket < net->ct.htable_size;
 	     st->bucket++) {
 		n = rcu_dereference(net->ct.hash[st->bucket].first);
 		if (!is_a_nulls(n))
@@ -50,7 +50,7 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq,
 	head = rcu_dereference(head->next);
 	while (is_a_nulls(head)) {
 		if (likely(get_nulls_value(head) == st->bucket)) {
-			if (++st->bucket >= nf_conntrack_htable_size)
+			if (++st->bucket >= net->ct.htable_size)
 				return NULL;
 		}
 		head = rcu_dereference(net->ct.hash[st->bucket].first);
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index fe1a644..5cff943 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -35,9 +35,6 @@ static DEFINE_SPINLOCK(nf_nat_lock);
 
 static struct nf_conntrack_l3proto *l3proto __read_mostly;
 
-/* Calculated at init based on memory size */
-static unsigned int nf_nat_htable_size __read_mostly;
-
 #define MAX_IP_NAT_PROTO 256
 static const struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO]
 						__read_mostly;
@@ -72,7 +69,7 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put);
 
 /* We keep an extra hash for each conntrack, for fast searching. */
 static inline unsigned int
-hash_by_src(const struct nf_conntrack_tuple *tuple)
+hash_by_src(const struct net *net, const struct nf_conntrack_tuple *tuple)
 {
 	unsigned int hash;
 
@@ -80,7 +77,7 @@ hash_by_src(const struct nf_conntrack_tuple *tuple)
 	hash = jhash_3words((__force u32)tuple->src.u3.ip,
 			    (__force u32)tuple->src.u.all,
 			    tuple->dst.protonum, 0);
-	return ((u64)hash * nf_nat_htable_size) >> 32;
+	return ((u64)hash * net->ipv4.nat_htable_size) >> 32;
 }
 
 /* Is this tuple already taken? (not by us) */
@@ -147,7 +144,7 @@ find_appropriate_src(struct net *net,
 		     struct nf_conntrack_tuple *result,
 		     const struct nf_nat_range *range)
 {
-	unsigned int h = hash_by_src(tuple);
+	unsigned int h = hash_by_src(net, tuple);
 	const struct nf_conn_nat *nat;
 	const struct nf_conn *ct;
 	const struct hlist_node *n;
@@ -330,7 +327,7 @@ nf_nat_setup_info(struct nf_conn *ct,
 	if (have_to_hash) {
 		unsigned int srchash;
 
-		srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+		srchash = hash_by_src(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 		spin_lock_bh(&nf_nat_lock);
 		/* nf_conntrack_alter_reply might re-allocate exntension aera */
 		nat = nfct_nat(ct);
@@ -679,8 +676,11 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct,
 
 static int __net_init nf_nat_net_init(struct net *net)
 {
-	net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
-						      &net->ipv4.nat_vmalloced, 0);
+	/* Leave them the same for the moment. */
+	net->ipv4.nat_htable_size = net->ct.htable_size;
+
+	net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&net->ipv4.nat_htable_size,
+						       &net->ipv4.nat_vmalloced, 0);
 	if (!net->ipv4.nat_bysource)
 		return -ENOMEM;
 	return 0;
@@ -703,7 +703,7 @@ static void __net_exit nf_nat_net_exit(struct net *net)
 	nf_ct_iterate_cleanup(net, &clean_nat, NULL);
 	synchronize_rcu();
 	nf_ct_free_hashtable(net->ipv4.nat_bysource, net->ipv4.nat_vmalloced,
-			     nf_nat_htable_size);
+			     net->ipv4.nat_htable_size);
 }
 
 static struct pernet_operations nf_nat_net_ops = {
@@ -724,9 +724,6 @@ static int __init nf_nat_init(void)
 		return ret;
 	}
 
-	/* Leave them the same for the moment. */
-	nf_nat_htable_size = nf_conntrack_htable_size;
-
 	ret = register_pernet_subsys(&nf_nat_net_ops);
 	if (ret < 0)
 		goto cleanup_extend;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 9de4bd4..ef1c856 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -84,9 +84,10 @@ static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple,
 	return ((u64)h * size) >> 32;
 }
 
-static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
+static inline u_int32_t hash_conntrack(const struct net *net,
+				       const struct nf_conntrack_tuple *tuple)
 {
-	return __hash_conntrack(tuple, nf_conntrack_htable_size,
+	return __hash_conntrack(tuple, net->ct.htable_size,
 				nf_conntrack_hash_rnd);
 }
 
@@ -294,7 +295,7 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conntrack_tuple_hash *h;
 	struct hlist_nulls_node *n;
-	unsigned int hash = hash_conntrack(tuple);
+	unsigned int hash = hash_conntrack(net, tuple);
 
 	/* Disable BHs the entire time since we normally need to disable them
 	 * at least once for the stats anyway.
@@ -364,10 +365,11 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct,
 
 void nf_conntrack_hash_insert(struct nf_conn *ct)
 {
+	struct net *net = nf_ct_net(ct);
 	unsigned int hash, repl_hash;
 
-	hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-	repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+	hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+	repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 
 	__nf_conntrack_hash_insert(ct, hash, repl_hash);
 }
@@ -395,8 +397,8 @@ __nf_conntrack_confirm(struct sk_buff *skb)
 	if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
 		return NF_ACCEPT;
 
-	hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-	repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+	hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+	repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 
 	/* We're not in hash table, and we refuse to set up related
 	   connections for unconfirmed conns.  But packet copies and
@@ -466,7 +468,7 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
 	struct net *net = nf_ct_net(ignored_conntrack);
 	struct nf_conntrack_tuple_hash *h;
 	struct hlist_nulls_node *n;
-	unsigned int hash = hash_conntrack(tuple);
+	unsigned int hash = hash_conntrack(net, tuple);
 
 	/* Disable BHs the entire time since we need to disable them at
 	 * least once for the stats anyway.
@@ -501,7 +503,7 @@ static noinline int early_drop(struct net *net, unsigned int hash)
 	int dropped = 0;
 
 	rcu_read_lock();
-	for (i = 0; i < nf_conntrack_htable_size; i++) {
+	for (i = 0; i < net->ct.htable_size; i++) {
 		hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash],
 					 hnnode) {
 			tmp = nf_ct_tuplehash_to_ctrack(h);
@@ -521,7 +523,7 @@ static noinline int early_drop(struct net *net, unsigned int hash)
 		if (cnt >= NF_CT_EVICTION_RANGE)
 			break;
 
-		hash = (hash + 1) % nf_conntrack_htable_size;
+		hash = (hash + 1) % net->ct.htable_size;
 	}
 	rcu_read_unlock();
 
@@ -555,7 +557,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
 
 	if (nf_conntrack_max &&
 	    unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) {
-		unsigned int hash = hash_conntrack(orig);
+		unsigned int hash = hash_conntrack(net, orig);
 		if (!early_drop(net, hash)) {
 			atomic_dec(&net->ct.count);
 			if (net_ratelimit())
@@ -1012,7 +1014,7 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data),
 	struct hlist_nulls_node *n;
 
 	spin_lock_bh(&nf_conntrack_lock);
-	for (; *bucket < nf_conntrack_htable_size; (*bucket)++) {
+	for (; *bucket < net->ct.htable_size; (*bucket)++) {
 		hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) {
 			ct = nf_ct_tuplehash_to_ctrack(h);
 			if (iter(ct, data))
@@ -1130,7 +1132,7 @@ static void nf_conntrack_cleanup_net(struct net *net)
 	}
 
 	nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
-			     nf_conntrack_htable_size);
+			     net->ct.htable_size);
 	nf_conntrack_ecache_fini(net);
 	nf_conntrack_acct_fini(net);
 	nf_conntrack_expect_fini(net);
@@ -1190,7 +1192,6 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
 {
 	int i, bucket, vmalloced, old_vmalloced;
 	unsigned int hashsize, old_size;
-	int rnd;
 	struct hlist_nulls_head *hash, *old_hash;
 	struct nf_conntrack_tuple_hash *h;
 
@@ -1206,33 +1207,29 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
 	if (!hash)
 		return -ENOMEM;
 
-	/* We have to rehahs for the new table anyway, so we also can
-	 * use a newrandom seed */
-	get_random_bytes(&rnd, sizeof(rnd));
-
 	/* Lookups in the old hash might happen in parallel, which means we
 	 * might get false negatives during connection lookup. New connections
 	 * created because of a false negative won't make it into the hash
 	 * though since that required taking the lock.
 	 */
 	spin_lock_bh(&nf_conntrack_lock);
-	for (i = 0; i < nf_conntrack_htable_size; i++) {
+	for (i = 0; i < init_net.ct.htable_size; i++) {
 		while (!hlist_nulls_empty(&init_net.ct.hash[i])) {
 			h = hlist_nulls_entry(init_net.ct.hash[i].first,
 					struct nf_conntrack_tuple_hash, hnnode);
 			hlist_nulls_del_rcu(&h->hnnode);
-			bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
+			bucket = __hash_conntrack(&h->tuple, hashsize,
+						  nf_conntrack_hash_rnd);
 			hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]);
 		}
 	}
-	old_size = nf_conntrack_htable_size;
+	old_size = init_net.ct.htable_size;
 	old_vmalloced = init_net.ct.hash_vmalloc;
 	old_hash = init_net.ct.hash;
 
-	nf_conntrack_htable_size = hashsize;
+	init_net.ct.htable_size = nf_conntrack_htable_size = hashsize;
 	init_net.ct.hash_vmalloc = vmalloced;
 	init_net.ct.hash = hash;
-	nf_conntrack_hash_rnd = rnd;
 	spin_unlock_bh(&nf_conntrack_lock);
 
 	nf_ct_free_hashtable(old_hash, old_vmalloced, old_size);
@@ -1328,7 +1325,9 @@ static int nf_conntrack_init_net(struct net *net)
 		ret = -ENOMEM;
 		goto err_cache;
 	}
-	net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
+
+	net->ct.htable_size = nf_conntrack_htable_size;
+	net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size,
 					     &net->ct.hash_vmalloc, 1);
 	if (!net->ct.hash) {
 		ret = -ENOMEM;
@@ -1353,7 +1352,7 @@ err_acct:
 	nf_conntrack_expect_fini(net);
 err_expect:
 	nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
-			     nf_conntrack_htable_size);
+			     net->ct.htable_size);
 err_hash:
 	kmem_cache_destroy(net->ct.nf_conntrack_cachep);
 err_cache:
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index fdf5d2a..1e751b1 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -577,7 +577,7 @@ int nf_conntrack_expect_init(struct net *net)
 
 	if (net_eq(net, &init_net)) {
 		if (!nf_ct_expect_hsize) {
-			nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
+			nf_ct_expect_hsize = net->ct.htable_size / 256;
 			if (!nf_ct_expect_hsize)
 				nf_ct_expect_hsize = 1;
 		}
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 65c2a7b..4b1a56b 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -192,7 +192,7 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me,
 	/* Get rid of expecteds, set helpers to NULL. */
 	hlist_nulls_for_each_entry(h, nn, &net->ct.unconfirmed, hnnode)
 		unhelp(h, me);
-	for (i = 0; i < nf_conntrack_htable_size; i++) {
+	for (i = 0; i < net->ct.htable_size; i++) {
 		hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode)
 			unhelp(h, me);
 	}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 42f21c0..0ffe689 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -594,7 +594,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 
 	rcu_read_lock();
 	last = (struct nf_conn *)cb->args[1];
-	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
+	for (; cb->args[0] < init_net.ct.htable_size; cb->args[0]++) {
 restart:
 		hlist_nulls_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]],
 					 hnnode) {
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 028aba6..e310f15 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -51,7 +51,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq)
 	struct hlist_nulls_node *n;
 
 	for (st->bucket = 0;
-	     st->bucket < nf_conntrack_htable_size;
+	     st->bucket < net->ct.htable_size;
 	     st->bucket++) {
 		n = rcu_dereference(net->ct.hash[st->bucket].first);
 		if (!is_a_nulls(n))
@@ -69,7 +69,7 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq,
 	head = rcu_dereference(head->next);
 	while (is_a_nulls(head)) {
 		if (likely(get_nulls_value(head) == st->bucket)) {
-			if (++st->bucket >= nf_conntrack_htable_size)
+			if (++st->bucket >= net->ct.htable_size)
 				return NULL;
 		}
 		head = rcu_dereference(net->ct.hash[st->bucket].first);
@@ -355,7 +355,7 @@ static ctl_table nf_ct_sysctl_table[] = {
 	},
 	{
 		.procname       = "nf_conntrack_buckets",
-		.data           = &nf_conntrack_htable_size,
+		.data           = &init_net.ct.htable_size,
 		.maxlen         = sizeof(unsigned int),
 		.mode           = 0444,
 		.proc_handler   = proc_dointvec,
@@ -421,6 +421,7 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
 		goto out_kmemdup;
 
 	table[1].data = &net->ct.count;
+	table[2].data = &net->ct.htable_size;
 	table[3].data = &net->ct.sysctl_checksum;
 	table[4].data = &net->ct.sysctl_log_invalid;
 

^ permalink raw reply related

* Re: pull request: wireless-next-2.6 2010-02-03
From: David Miller @ 2010-02-04 17:00 UTC (permalink / raw)
  To: linville-2XuSBdqkA4R54TAoqtyWWQ
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20100203211900.GJ2882-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>

From: "John W. Linville" <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Date: Wed, 3 Feb 2010 16:19:01 -0500

> Another huge batch of updates intended for 2.6.34, mostly the usual bits
> by the usual suspects.  This batch does contain a number of mac80211
> fixes that (presumably) originated in OpenWRT and a number of steps
> toward N-phy support in b43, along with the usual driver updates from
> Intel, Atheros, and many others.  And, of course, Johannes makes his
> usual strong showing. :-)
> 
> Please let me know if there are problems!

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

^ permalink raw reply

* Re: netfilter/iptables and network interface names
From: Patrick McHardy @ 2010-02-04 16:49 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Thomas Woerner, netdev, Netfilter Developer Mailing List
In-Reply-To: <alpine.LSU.2.01.1002041743360.21982@obet.zrqbmnf.qr>

Jan Engelhardt wrote:
>> The kernel also forbids ".".
> 
> My first thought was the same, but:
> 
> a) Interestingly, it does not prohibit '.'
> 
> 	ip tunnel add foo0.3 mode sit local 1.2.3.4 remote 5.6.7.8
> 
> b) The '.' is to be seen as valid as far as xtables.c goes, so
>    as to match VLAN interfaces.

Ah of course, its only invalid at the beginning of the name.

^ permalink raw reply

* Re: netfilter/iptables and network interface names
From: Jan Engelhardt @ 2010-02-04 16:48 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Thomas Woerner, netdev, Netfilter Developer Mailing List
In-Reply-To: <4B6ADFFB.4050407@trash.net>


On Thursday 2010-02-04 15:55, Patrick McHardy wrote:

>>>>> What do you think?
>> 
>> When was the last time you needed a control character in your
>> interface name?
>
>Actually I did use ansi-colors in my interface names once for fun :)

Madness!

>Anyways, I don't see why iptables should impose arbitrary restrictions.

Well iptables does allow \e!

>> Like this?
>> 
>> @@ -473,12 +473,11 @@ void xtables_parse_interface(const char *arg, char *vianame,
>>  		memset(mask, 0xFF, vialen + 1);
>>  		memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
>>  		for (i = 0; vianame[i]; i++) {
>> -			if (vianame[i] == ':' ||
>> -			    vianame[i] == '!' ||
>> -			    vianame[i] == '*') {
>> +			if (vianame[i] == '/' ||
>> +			    vianame[i] == ' ') {
>>  				fprintf(stderr,
>>  					"Warning: weird character in interface"
>> -					" `%s' (No aliases, :, ! or *).\n",
>> +					" `%s' ('/' and ' ' are not allowed by the kernel).\n",
>>  					vianame);
>
>The kernel also forbids ".".

My first thought was the same, but:

a) Interestingly, it does not prohibit '.'

	ip tunnel add foo0.3 mode sit local 1.2.3.4 remote 5.6.7.8

b) The '.' is to be seen as valid as far as xtables.c goes, so
   as to match VLAN interfaces.


^ permalink raw reply

* Re: [PATCH for 2.6.33] conntrack: restrict runtime hashsize modifications
From: Patrick McHardy @ 2010-02-04 16:27 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: davem, jonathan, eric.dumazet, netdev, netfilter-devel
In-Reply-To: <4B6AF36A.3050402@trash.net>

Patrick McHardy wrote:
> Alexey Dobriyan wrote:
>> Jon Masters correctly points out that conntrack hash sizes
>> (nf_conntrack_htable_size) are global (not per-netns) and
>> modifiable at runtime via /sys/module/nf_conntrack/hashsize .
>>
>> Steps to reproduce:
>> 	clone(CLONE_NEWNET)
>> 	[grow /sys/module/nf_conntrack/hashsize]
>> 	exit()
>>
>> At netns exit we are going to scan random memory for conntracks to be killed.
>>
>> Apparently there is a code which deals with hashtable resize for
>> init_net (and it was there befode netns conntrack code), so prohibit
>> hashsize modification if there is more than one netns exists.
>>
>> To change hashtable sizes, you need to reload module.
>>
>> Expectation hashtable size was simply glued to a variable with no code
>> to rehash expectations, so it was a bug to allow writing to it.
>> Make "expect_hashsize" readonly.
>>
>> This is temporarily until we figure out what to do.
> 
> How about alternatively moving nf_conntrack_hsize into the
> per-namespace struct? It doesn't look more complicated or
> intrusive and would allow to still change the init_net
> hashsize. Also seems less hackish :)

Just to avoid duplicate work, I'm currently trying that.

^ permalink raw reply

* Re: [PATCH for 2.6.33] conntrack: restrict runtime hashsize modifications
From: Patrick McHardy @ 2010-02-04 16:18 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: davem, jonathan, eric.dumazet, netdev, netfilter-devel
In-Reply-To: <20100203203929.GA6168@x200>

Alexey Dobriyan wrote:
> Jon Masters correctly points out that conntrack hash sizes
> (nf_conntrack_htable_size) are global (not per-netns) and
> modifiable at runtime via /sys/module/nf_conntrack/hashsize .
> 
> Steps to reproduce:
> 	clone(CLONE_NEWNET)
> 	[grow /sys/module/nf_conntrack/hashsize]
> 	exit()
> 
> At netns exit we are going to scan random memory for conntracks to be killed.
> 
> Apparently there is a code which deals with hashtable resize for
> init_net (and it was there befode netns conntrack code), so prohibit
> hashsize modification if there is more than one netns exists.
> 
> To change hashtable sizes, you need to reload module.
> 
> Expectation hashtable size was simply glued to a variable with no code
> to rehash expectations, so it was a bug to allow writing to it.
> Make "expect_hashsize" readonly.
> 
> This is temporarily until we figure out what to do.

How about alternatively moving nf_conntrack_hsize into the
per-namespace struct? It doesn't look more complicated or
intrusive and would allow to still change the init_net
hashsize. Also seems less hackish :)

^ permalink raw reply

* Re: [net-next PATCH 3/3] qlge: Add watchdog timer.
From: Ron Mercer @ 2010-02-04 16:04 UTC (permalink / raw)
  To: David Miller; +Cc: netdev@vger.kernel.org
In-Reply-To: <20100203.193222.64773800.davem@davemloft.net>

> This does a PIO to the chip every single second?
> 
> How about something like 5 or 10 seconds, and use the
> deferrable interfaces so that it's more friendly to
> power management on an otherwise idle system?
>

You are correct that we don't need to check every second.
I will increase the duration and test it out a deferrable timer.

Thanks

^ permalink raw reply

* [PATCH 23/23 v3] mlx4_en: querying link state
From: Yevgeny Petrilin @ 2010-02-04 15:57 UTC (permalink / raw)
  To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
In-Reply-To: <49BFC313.1030901@mellanox.co.il>

In multifunction device, a certain function can initialize its port after some
other function already done that. In that case link event would not be generated.
Need to query the port to retrieve the port state.

Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_netdev.c |   10 ++++++++++
 drivers/net/mlx4/en_port.c   |   31 +++++++++++++++++++++++++++++++
 drivers/net/mlx4/en_port.h   |   15 +++++++++++++++
 drivers/net/mlx4/mlx4_en.h   |    8 ++++++++
 4 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 947fb2f..22511ec 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -229,6 +229,16 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
 		goto out;
 	}
 
+	if (!netif_carrier_ok(dev)) {
+		if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
+			if (priv->port_state.link_state) {
+				priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
+				netif_carrier_on(dev);
+				en_dbg(LINK, priv, "Link Up\n");
+			}
+		}
+	}
+
 	/*
 	 * Promsicuous mode: disable all filters
 	 */
diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index 2863a30..8b3c537 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -41,6 +41,37 @@
 #include "mlx4_en.h"
 
 
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
+{
+	struct mlx4_en_query_port_context *qport_context;
+	struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
+	struct mlx4_en_port_state *state = &priv->port_state;
+	struct mlx4_cmd_mailbox *mailbox;
+	int err;
+
+	mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+	memset(mailbox->buf, 0, sizeof(*qport_context));
+	err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
+			   MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B);
+	if (err)
+		goto out;
+	qport_context = mailbox->buf;
+
+	state->link_state = !!(qport_context->link_up & MLX4_EN_LINK_UP_MASK);
+	if ((qport_context->link_speed & MLX4_EN_SPEED_MASK) ==
+	    MLX4_EN_1G_SPEED)
+		state->link_speed = 1000;
+	else
+		state->link_speed = 10000;
+	state->transciver = qport_context->transceiver;
+
+out:
+	mlx4_free_cmd_mailbox(mdev->dev, mailbox);
+	return err;
+}
+
 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
 {
 	struct mlx4_en_stat_out_mbox *mlx4_en_stats;
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index 40918ab..8c387a0 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -42,6 +42,21 @@ enum {
 };
 
 
+struct mlx4_en_query_port_context {
+	u8 link_up;
+#define MLX4_EN_LINK_UP_MASK	0x80
+	u8 reserved;
+	__be16 mtu;
+	u8 reserved2;
+	u8 link_speed;
+#define MLX4_EN_SPEED_MASK	0x3
+#define MLX4_EN_1G_SPEED	0x2
+	u16 reserved3[5];
+	__be64 mac;
+	u8 transceiver;
+};
+
+
 struct mlx4_en_stat_out_mbox {
 	/* Received frames with a length of 64 octets */
 	__be64 R64_prio_0;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 834fd24..5f6c080 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -391,6 +391,12 @@ struct mlx4_en_rss_context {
 	__be32 rss_key[10];
 };
 
+struct mlx4_en_port_state {
+	int link_state;
+	int link_speed;
+	int transciver;
+};
+
 struct mlx4_en_pkt_stats {
 	unsigned long broadcast;
 	unsigned long rx_prio[8];
@@ -439,6 +445,7 @@ struct mlx4_en_priv {
 	struct vlan_group *vlgrp;
 	struct net_device_stats stats;
 	struct net_device_stats ret_stats;
+	struct mlx4_en_port_state port_state;
 	spinlock_t stats_lock;
 
 	unsigned long last_moder_packets;
@@ -563,6 +570,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
 			   u8 promisc);
 
 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
+int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
 
 u64 mlx4_en_mac_to_u64(u8 *addr);
 /*
-- 
1.6.1.3



^ permalink raw reply related

* [PATCH 22/23 v3] mlx4_en: Use reasonable resources for slaves
From: Yevgeny Petrilin @ 2010-02-04 15:57 UTC (permalink / raw)
  To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
In-Reply-To: <49BFC313.1030901@mellanox.co.il>

>From d42a1ac0bbfeb2522e11d2aca2f41396b070d6eb Mon Sep 17 00:00:00 2001
From: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Date: Fri, 6 Nov 2009 01:10:28 +0200
Subject: [PATCH 22/23] mlx4_en: Use reasonable resources for slaves.

Each slave gets a single MSI-X vector when in multi function mode.
In this case each slave would allocate less resources (which
normally depend on number of completion vectors).
We set a minimum number of RX and TX queues to achieve an
acceptable performance in multi function mode.

Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_main.c   |   12 +++++++-----
 drivers/net/mlx4/en_netdev.c |    3 ++-
 drivers/net/mlx4/en_tx.c     |    2 +-
 drivers/net/mlx4/mlx4_en.h   |    8 +++++---
 4 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 507e11f..3883071 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -93,8 +93,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
 		params->prof[i].tx_ppp = pfctx;
 		params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
 		params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
-		params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
-			(!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
 	}
 
 	return 0;
@@ -216,11 +214,15 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
 	/* If we did not receive an explicit number of Rx rings, default to
 	 * the number of completion vectors populated by the mlx4_core */
 	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
+		mdev->profile.prof[i].tx_ring_num = max_t(int,
+			min_t(int, roundup_pow_of_two(dev->caps.num_comp_vectors),
+			NUM_TX_RINGS), MIN_TX_RINGS) +
+			(!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
 		mlx4_info(mdev, "Using %d tx rings for port:%d\n",
 			  mdev->profile.prof[i].tx_ring_num, i);
-		mdev->profile.prof[i].rx_ring_num = min_t(int,
-			roundup_pow_of_two(dev->caps.num_comp_vectors),
-			MAX_RX_RINGS);
+		mdev->profile.prof[i].rx_ring_num = max_t(int,
+			min_t(int, roundup_pow_of_two(dev->caps.num_comp_vectors),
+			MAX_RX_RINGS), MIN_RX_RINGS);
 		mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
 			  mdev->profile.prof[i].rx_ring_num, i);
 	}
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 751c79d..947fb2f 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -1053,7 +1053,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	 */
 	dev->netdev_ops = &mlx4_netdev_ops;
 	dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
-	dev->real_num_tx_queues = MLX4_EN_NUM_TX_RINGS;
+	dev->real_num_tx_queues = priv->tx_ring_num -
+				!!(priv->prof->rx_ppp) * MLX4_EN_NUM_PPP_RINGS;
 
 	SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
 
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index d4af0fe..b8e994d 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -583,7 +583,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
 	 */
 	if (priv->prof->rx_ppp && priv->vlgrp && vlan_tx_tag_present(skb)) {
 		vlan_tag = vlan_tx_tag_get(skb);
-		return MLX4_EN_NUM_TX_RINGS + (vlan_tag >> 13);
+		return priv->tx_ring_num - MLX4_EN_NUM_PPP_RINGS + (vlan_tag >> 13);
 	}
 
 	return skb_tx_hash(dev, skb);
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 809c45d..834fd24 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -93,8 +93,11 @@
 
 #define MLX4_EN_PAGE_SHIFT	12
 #define MLX4_EN_PAGE_SIZE	(1 << MLX4_EN_PAGE_SHIFT)
-#define MAX_TX_RINGS		16
-#define MAX_RX_RINGS		16
+#define MAX_TX_RINGS		12
+#define MAX_RX_RINGS		8
+#define MIN_RX_RINGS		4
+#define NUM_TX_RINGS		4
+#define MIN_TX_RINGS		4
 #define TXBB_SIZE		64
 #define HEADROOM		(2048 / TXBB_SIZE + 1)
 #define STAMP_STRIDE		64
@@ -137,7 +140,6 @@ enum {
 #define MLX4_EN_MIN_TX_SIZE	(4096 / TXBB_SIZE)
 
 #define MLX4_EN_SMALL_PKT_SIZE		64
-#define MLX4_EN_NUM_TX_RINGS		8
 #define MLX4_EN_NUM_PPP_RINGS		8
 #define MLX4_EN_DEF_TX_RING_SIZE	512
 #define MLX4_EN_DEF_RX_RING_SIZE  	1024
-- 
1.6.1.3



^ permalink raw reply related

* [PATCH 21/23 v3] mlx4_core: Adding VEP number in resource allocation
From: Yevgeny Petrilin @ 2010-02-04 15:57 UTC (permalink / raw)
  To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
In-Reply-To: <49BFC313.1030901@mellanox.co.il>

Each slave would have its relative range of resources.
Specifying the function number at resource allocation allows the firmware
to calculate the absolute resource number

Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/cmd.c |   58 ++++++++++++++++++++++++++++++++++-------------
 drivers/net/mlx4/fw.c  |    2 +-
 2 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index 2605344..7eab34d 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -533,6 +533,32 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
 	return 0;
 }
 
+static int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
+			    struct mlx4_vhcr *vhcr,
+			    struct mlx4_cmd_mailbox *inbox,
+			    struct mlx4_cmd_mailbox *outbox)
+{
+	u64 in_param = inbox ? inbox->dma : vhcr->in_param;
+
+	in_param |= (u64) slave;
+	return mlx4_cmd(dev, in_param, vhcr->in_modifier,
+			vhcr->op_modifier, vhcr->op, MLX4_CMD_TIME_CLASS_C);
+}
+
+static int mlx4_DMA_outbox_wrapper(struct mlx4_dev *dev, int slave,
+				   struct mlx4_vhcr *vhcr,
+				   struct mlx4_cmd_mailbox *inbox,
+				   struct mlx4_cmd_mailbox *outbox)
+{
+	u64 in_param = inbox ? inbox->dma : vhcr->in_param;
+	u64 out_param = outbox ? outbox->dma : vhcr->out_param;
+
+	in_param |= (u64) slave;
+	return mlx4_cmd_box(dev, in_param, out_param,
+			    vhcr->in_modifier, vhcr->op_modifier, vhcr->op,
+			    MLX4_CMD_TIME_CLASS_C);
+}
+
 static struct mlx4_cmd_info {
 	u16 opcode;
 	bool has_inbox;
@@ -615,7 +641,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /*need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_NOP,
@@ -664,7 +690,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL,
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_QUERY_MPT,
@@ -710,10 +736,10 @@ static struct mlx4_cmd_info {
 	{
 		.opcode = MLX4_CMD_HW2SW_EQ,
 		.has_inbox = false,
-		.has_outbox = false,
+		.has_outbox = true,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_outbox_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_QUERY_EQ,
@@ -729,7 +755,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_HW2SW_CQ,
@@ -737,7 +763,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_QUERY_CQ,
@@ -761,7 +787,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_HW2SW_SRQ,
@@ -793,7 +819,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_INIT2RTR_QP,
@@ -801,7 +827,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_RTR2RTS_QP,
@@ -809,7 +835,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_RTS2RTS_QP,
@@ -817,7 +843,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_SQERR2RTS_QP,
@@ -825,7 +851,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_2ERR_QP,
@@ -833,7 +859,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_RTS2SQD_QP,
@@ -841,7 +867,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_SQD2SQD_QP,
@@ -849,7 +875,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_SQD2RTS_QP,
@@ -857,7 +883,7 @@ static struct mlx4_cmd_info {
 		.has_outbox = false,
 		.out_is_imm = false,
 		.verify = NULL, /* need verifier */
-		.wrapper = NULL
+		.wrapper = mlx4_DMA_wrapper
 	},
 	{
 		.opcode = MLX4_CMD_2RST_QP,
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 18294c3..18a35af 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -300,7 +300,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET);
 	dev_cap->max_mpts = 1 << (field & 0x3f);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET);
-	dev_cap->reserved_eqs = field & 0xf;
+	dev_cap->reserved_eqs = field & 0xff;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET);
 	dev_cap->max_eqs = 1 << (field & 0xf);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET);
-- 
1.6.1.3



^ permalink raw reply related

* [PATCH 20/23 v3] mlx4_core: binding virtual function to physical function
From: Yevgeny Petrilin @ 2010-02-04 15:57 UTC (permalink / raw)
  To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
In-Reply-To: <49BFC313.1030901@mellanox.co.il>


Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/cmd.c   |    8 ++++++++
 drivers/net/mlx4/fw.c    |   23 +++++++++++++++++++++++
 drivers/net/mlx4/fw.h    |    1 +
 drivers/net/mlx4/main.c  |    4 ++--
 drivers/net/mlx4/mcg.c   |    3 ++-
 drivers/net/mlx4/mlx4.h  |    2 ++
 drivers/net/mlx4/port.c  |    5 +++--
 include/linux/mlx4/cmd.h |    1 +
 8 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx4/cmd.c b/drivers/net/mlx4/cmd.c
index e437d74..2605344 100644
--- a/drivers/net/mlx4/cmd.c
+++ b/drivers/net/mlx4/cmd.c
@@ -422,9 +422,11 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
 						       struct mlx4_cmd_mailbox *inbox,
 						       struct mlx4_cmd_mailbox *outbox)
 {
+	struct mlx4_priv *priv = mlx4_priv(dev);
 	u32 param1 = *((u32 *) &vhcr->in_param);
 	u32 param2 = *(((u32 *) &vhcr->in_param) + 1);
 	int ret;
+	u8 pf_num = priv->mfunc.master.slave_state[slave].pf_num;
 
 #if 0
 	char *res[] = {"QP", "CQ", "SRQ", "MPT", "MTT"};
@@ -507,6 +509,7 @@ static int mlx4_RESOURCE_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vh
 			mlx4_free_mtt_range(dev, param1 /* first */, param2 /* order */);
 		break;
 	case RES_MAC:
+		vhcr->in_param |= (u64) (pf_num) << 48;
 		switch (vhcr->op) {
 		case MLX4_CMD_ALLOC_RES:
 			ret = mlx4_register_mac(dev, vhcr->op_modifier,
@@ -1119,6 +1122,11 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, u16 para
 		if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2)
 			goto reset_slave;
 		slave_state[slave].vhcr_dma |= param;
+		if (mlx4_QUERY_FUNC(dev, slave, &slave_state[slave].pf_num)) {
+			mlx4_err(dev, "Failed to determine physical function "
+				      "number for slave %d\n", slave);
+			goto reset_slave;
+		}
 		break;
 	case MLX4_COMM_CMD_VHCR_POST:
 		if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) &&
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 202a256..18294c3 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -1038,3 +1038,26 @@ int mlx4_NOP(struct mlx4_dev *dev)
 	/* Input modifier of 0x1f means "finish as soon as possible." */
 	return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
 }
+
+int mlx4_QUERY_FUNC(struct mlx4_dev *dev, int func, u8 *pf_num)
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	u8 *outbox;
+	int ret;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+	outbox = mailbox->buf;
+
+	ret = mlx4_cmd_box(dev, 0, mailbox->dma, func & 0xff, 0,
+			   MLX4_CMD_QUERY_FUNC, MLX4_CMD_TIME_CLASS_A);
+	if (ret)
+		goto out;
+
+	*pf_num = outbox[3];
+
+out:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return ret;
+}
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index e033d26..4ec92f4 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -181,5 +181,6 @@ int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
 int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev);
 int mlx4_NOP(struct mlx4_dev *dev);
 int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg);
+int mlx4_QUERY_FUNC(struct mlx4_dev *dev, int func, u8 *pf_num);
 
 #endif /* MLX4_FW_H */
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index d825cc1..b57bac2 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -276,7 +276,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
 		}
 	}
 
-	mlx4_set_port_mask(dev, &dev->caps, dev->caps.pf_num);
+	mlx4_set_port_mask(dev, &dev->caps, dev->caps.function);
 
 	dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps;
 	dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] =
@@ -389,7 +389,7 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
 				goto out;
 			}
 		}
-		mlx4_set_port_mask(dev, &dev->caps, dev->caps.pf_num);
+		mlx4_set_port_mask(dev, &dev->caps, dev->caps.function);
 		err = mlx4_register_device(dev);
 	}
 
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index 9a678d2..4e2b422 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -361,9 +361,10 @@ int mlx4_MCAST_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
 	struct mlx4_qp qp; /* dummy for calling attach/detach */
 	u8 *gid = inbox->buf;
 	enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7;
+	u8 pf_num = mlx4_priv(dev)->mfunc.master.slave_state[slave].pf_num;
 
 	if (prot == MLX4_PROT_ETH)
-		gid[7] = slave << 4;
+		gid[7] = pf_num << 4;
 
 	qp.qpn = vhcr->in_modifier & 0xffffff;
 	if (vhcr->op_modifier)
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 1cc4c13..cdf6aff 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -238,6 +238,8 @@ struct mlx4_slave_state {
 	u8 comm_toggle;
 	u8 last_cmd;
 	u8 init_port_mask;
+	u8 pf_num;
+	u8 function;
 	dma_addr_t vhcr_dma;
 	u16 mtu[MLX4_MAX_PORTS + 1];
 	__be32 ib_cap_mask[MLX4_MAX_PORTS + 1];
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index e94a373..22a224e 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -104,7 +104,8 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
 		if (!err)
 			*qpn = out_param;
 		return err;
-	}
+	} else
+		mac |= (u64) (dev->caps.function) << 48;
 
 	mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
 	mutex_lock(&table->mutex);
@@ -115,7 +116,7 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn)
 		}
 
 		if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
-			/* MAC already registered, Must not have duplicates */
+			/* MAC + PF already registered, Must not have duplicates */
 			err = -EEXIST;
 			goto out;
 		}
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 9526dfd..0b68447 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -57,6 +57,7 @@ enum {
 	MLX4_CMD_QUERY_PORT	 = 0x43,
 	MLX4_CMD_SENSE_PORT	 = 0x4d,
 	MLX4_CMD_SET_PORT	 = 0xc,
+	MLX4_CMD_QUERY_FUNC	 = 0x56,
 	MLX4_CMD_ACCESS_DDR	 = 0x2e,
 	MLX4_CMD_MAP_ICM	 = 0xffa,
 	MLX4_CMD_UNMAP_ICM	 = 0xff9,
-- 
1.6.1.3



^ permalink raw reply related

* [PATCH 19/23 v3] mlx4: SET port for Ethernet moved to mlx4_core
From: Yevgeny Petrilin @ 2010-02-04 15:56 UTC (permalink / raw)
  To: Roland Dreier; +Cc: general, netdev, liranl, tziporet
In-Reply-To: <49BFC313.1030901@mellanox.co.il>

The physical port is common resource for all the functions.
Its management should go through the multifunction mechanism.

Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
---
 drivers/net/mlx4/en_port.c  |   64 -------------------------
 drivers/net/mlx4/en_port.h  |   43 -----------------
 drivers/net/mlx4/mlx4.h     |   44 ++++++++++++++++++
 drivers/net/mlx4/port.c     |  107 ++++++++++++++++++++++++++++++++++++++-----
 include/linux/mlx4/device.h |    5 ++
 5 files changed, 144 insertions(+), 119 deletions(-)

diff --git a/drivers/net/mlx4/en_port.c b/drivers/net/mlx4/en_port.c
index b099f81..2863a30 100644
--- a/drivers/net/mlx4/en_port.c
+++ b/drivers/net/mlx4/en_port.c
@@ -41,70 +41,6 @@
 #include "mlx4_en.h"
 
 
-int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
-			  u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
-{
-	struct mlx4_cmd_mailbox *mailbox;
-	struct mlx4_set_port_general_context *context;
-	int err;
-	u32 in_mod;
-
-	mailbox = mlx4_alloc_cmd_mailbox(dev);
-	if (IS_ERR(mailbox))
-		return PTR_ERR(mailbox);
-	context = mailbox->buf;
-	memset(context, 0, sizeof *context);
-
-	context->flags = SET_PORT_GEN_ALL_VALID;
-	context->mtu = cpu_to_be16(mtu);
-	context->pptx = (pptx * (!pfctx)) << 7;
-	context->pfctx = pfctx;
-	context->pprx = (pprx * (!pfcrx)) << 7;
-	context->pfcrx = pfcrx;
-
-	in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
-	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
-		       MLX4_CMD_TIME_CLASS_B);
-
-	mlx4_free_cmd_mailbox(dev, mailbox);
-	return err;
-}
-
-int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
-			   u8 promisc)
-{
-	struct mlx4_cmd_mailbox *mailbox;
-	struct mlx4_set_port_rqp_calc_context *context;
-	int err;
-	u32 in_mod;
-	u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT;
-
-	mailbox = mlx4_alloc_cmd_mailbox(dev);
-	if (IS_ERR(mailbox))
-		return PTR_ERR(mailbox);
-	context = mailbox->buf;
-	memset(context, 0, sizeof *context);
-
-	context->base_qpn = cpu_to_be32(base_qpn);
-	context->n_mac = 0x7;
-	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
-				       base_qpn);
-	context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
-				     base_qpn);
-	context->intra_no_vlan = 0;
-	context->no_vlan = MLX4_NO_VLAN_IDX;
-	context->intra_vlan_miss = 0;
-	context->vlan_miss = MLX4_VLAN_MISS_IDX;
-
-	in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
-	err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
-		       MLX4_CMD_TIME_CLASS_B);
-
-	mlx4_free_cmd_mailbox(dev, mailbox);
-	return err;
-}
-
-
 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
 {
 	struct mlx4_en_stat_out_mbox *mlx4_en_stats;
diff --git a/drivers/net/mlx4/en_port.h b/drivers/net/mlx4/en_port.h
index 8b221d6..40918ab 100644
--- a/drivers/net/mlx4/en_port.h
+++ b/drivers/net/mlx4/en_port.h
@@ -35,49 +35,6 @@
 #define _MLX4_EN_PORT_H_
 
 
-#define SET_PORT_GEN_ALL_VALID		0x7
-#define SET_PORT_PROMISC_SHIFT		31
-#define SET_PORT_MC_PROMISC_SHIFT	30
-
-enum {
-	MCAST_DIRECT_ONLY	= 0,
-	MCAST_DIRECT		= 1,
-	MCAST_DEFAULT		= 2
-};
-
-
-struct mlx4_set_port_general_context {
-	u8 reserved[3];
-	u8 flags;
-	u16 reserved2;
-	__be16 mtu;
-	u8 pptx;
-	u8 pfctx;
-	u16 reserved3;
-	u8 pprx;
-	u8 pfcrx;
-	u16 reserved4;
-};
-
-struct mlx4_set_port_rqp_calc_context {
-	__be32 base_qpn;
-	u8 rererved;
-	u8 n_mac;
-	u8 n_vlan;
-	u8 n_prio;
-	u8 reserved2[3];
-	u8 mac_miss;
-	u8 intra_no_vlan;
-	u8 no_vlan;
-	u8 intra_vlan_miss;
-	u8 vlan_miss;
-	u8 reserved3[3];
-	u8 no_vlan_prio;
-	__be32 promisc;
-	__be32 mcast;
-};
-
-
 enum {
 	MLX4_MCAST_CONFIG       = 0,
 	MLX4_MCAST_DISABLE      = 1,
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 74543d7..1cc4c13 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -382,6 +382,50 @@ struct mlx4_vlan_table {
 	int			max;
 };
 
+
+#define SET_PORT_GEN_ALL_VALID		0x7
+#define SET_PORT_PROMISC_SHIFT		31
+#define SET_PORT_MC_PROMISC_SHIFT	30
+
+enum {
+	MCAST_DIRECT_ONLY	= 0,
+	MCAST_DIRECT		= 1,
+	MCAST_DEFAULT		= 2
+};
+
+
+struct mlx4_set_port_general_context {
+	u8 reserved[3];
+	u8 flags;
+	u16 reserved2;
+	__be16 mtu;
+	u8 pptx;
+	u8 pfctx;
+	u16 reserved3;
+	u8 pprx;
+	u8 pfcrx;
+	u16 reserved4;
+};
+
+struct mlx4_set_port_rqp_calc_context {
+	__be32 base_qpn;
+	u8 rererved;
+	u8 n_mac;
+	u8 n_vlan;
+	u8 n_prio;
+	u8 reserved2[3];
+	u8 mac_miss;
+	u8 intra_no_vlan;
+	u8 no_vlan;
+	u8 intra_vlan_miss;
+	u8 vlan_miss;
+	u8 reserved3[3];
+	u8 no_vlan_prio;
+	__be32 promisc;
+	__be32 mcast;
+};
+
+
 struct mlx4_port_info {
 	struct mlx4_dev	       *dev;
 	int			port;
diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c
index 1bec155..e94a373 100644
--- a/drivers/net/mlx4/port.c
+++ b/drivers/net/mlx4/port.c
@@ -348,9 +348,8 @@ int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps)
 	return err;
 }
 
-int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
-							struct mlx4_cmd_mailbox *inbox,
-							struct mlx4_cmd_mailbox *outbox)
+static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
+				u8 op_mod, struct mlx4_cmd_mailbox *inbox)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_port_info *port_info;
@@ -370,9 +369,9 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhc
 	__be32 slave_cap_mask;
 	__be32 new_cap_mask;
 
-	port = vhcr->in_modifier & 0xff;
-	in_modifier = vhcr->in_modifier >> 8;
-	is_eth = vhcr->op_modifier;
+	port = in_mod & 0xff;
+	in_modifier = in_mod >> 8;
+	is_eth = op_mod;
 	port_info = &priv->port[port];
 
 	/* All slaves can perform SET_PORT operations, just need to verify
@@ -417,10 +416,8 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhc
 			gen_context->mtu = cpu_to_be16(master->max_mtu[port]);
 			break;
 		}
-		return mlx4_cmd(dev, inbox->dma, vhcr->in_modifier,
-						 vhcr->op_modifier,
-						 MLX4_CMD_SET_PORT,
-						 MLX4_CMD_TIME_CLASS_B);
+		return mlx4_cmd(dev, inbox->dma, in_mod, op_mod,
+				MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B);
 	}
 
 	/* For IB, we only consider:
@@ -471,6 +468,16 @@ int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhc
 	return err;
 }
 
+int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave,
+			  struct mlx4_vhcr *vhcr,
+			  struct mlx4_cmd_mailbox *inbox,
+			  struct mlx4_cmd_mailbox *outbox)
+{
+	return mlx4_common_set_port(dev, slave, vhcr->in_modifier,
+				    vhcr->op_modifier, inbox);
+}
+
+
 int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
 {
 	struct mlx4_cmd_mailbox *mailbox;
@@ -486,12 +493,88 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port)
 	memset(mailbox->buf, 0, 256);
 
 	((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port];
-	err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
-		       MLX4_CMD_TIME_CLASS_B);
+
+	if (mlx4_is_master(dev))
+		err = mlx4_common_set_port(dev, dev->caps.function, port, 0, mailbox);
+	else
+		err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
+			       MLX4_CMD_TIME_CLASS_B);
+
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return err;
+}
+
+
+int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
+			  u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_set_port_general_context *context;
+	int err;
+	u32 in_mod;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+	context = mailbox->buf;
+	memset(context, 0, sizeof *context);
+
+	context->flags = SET_PORT_GEN_ALL_VALID;
+	context->mtu = cpu_to_be16(mtu);
+	context->pptx = (pptx * (!pfctx)) << 7;
+	context->pfctx = pfctx;
+	context->pprx = (pprx * (!pfcrx)) << 7;
+	context->pfcrx = pfcrx;
+
+	in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
+	if (mlx4_is_master(dev))
+		err = mlx4_common_set_port(dev, dev->caps.function, in_mod, 1, mailbox);
+	else
+		err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+			       MLX4_CMD_TIME_CLASS_B);
+
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return err;
+}
+EXPORT_SYMBOL(mlx4_SET_PORT_general);
+
+int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
+			   u8 promisc)
+{
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_set_port_rqp_calc_context *context;
+	int err;
+	u32 in_mod;
+	u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox))
+		return PTR_ERR(mailbox);
+	context = mailbox->buf;
+	memset(context, 0, sizeof *context);
+
+	context->base_qpn = cpu_to_be32(base_qpn);
+	context->n_mac = 0x7;
+	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
+				       base_qpn);
+	context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
+				     base_qpn);
+	context->intra_no_vlan = 0;
+	context->no_vlan = MLX4_NO_VLAN_IDX;
+	context->intra_vlan_miss = 0;
+	context->vlan_miss = MLX4_VLAN_MISS_IDX;
+
+	in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
+	if (mlx4_is_master(dev))
+		err = mlx4_common_set_port(dev, dev->caps.function, in_mod, 1, mailbox);
+	else
+		err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
+			       MLX4_CMD_TIME_CLASS_B);
 
 	mlx4_free_cmd_mailbox(dev, mailbox);
 	return err;
 }
+EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc);
 
 static int mlx4_common_set_mcast_fltr(struct mlx4_dev *dev, int function,
 				      int port, u64 addr, u64 clear, u8 mode)
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 8e51af5..a52caf6 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -498,6 +498,11 @@ void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq);
 int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark);
 int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark);
 
+int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
+			  u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
+int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
+			   u8 promisc);
+
 int mlx4_INIT_PORT(struct mlx4_dev *dev, int port);
 int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port);
 
-- 
1.6.1.3



^ permalink raw reply related


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