* Re: [PATCH] atm: introduce vcc_pop_skb()
From: David Woodhouse @ 2012-12-03 13:22 UTC (permalink / raw)
To: Krzysztof Mazur; +Cc: chas williams - CONTRACTOR, davem, netdev, linux-kernel
In-Reply-To: <20121128223300.GA12527@shrek.podlesie.net>
[-- Attachment #1: Type: text/plain, Size: 1190 bytes --]
On Wed, 2012-11-28 at 23:33 +0100, Krzysztof Mazur wrote:
>
> Many ATM drivers store vcc in ATM_SKB(skb)->vcc and use it for
> freeing skbs. Now they can just use atm_pop_skb() to free such
> buffers.
>
> Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Note that this one didn't make it into the tree that Dave just pulled.
Not that I didn't think it was a good idea, but it was just separate
from the other "real" fixes — and the tree had already grown into a big
enough pile from your original single patch!
In <20121006154606.GA25588@shrek.podlesie.net> you posted another patch:
> I think there is another problem here. The pppoatm gets a reference
> to atmvcc, but I don't see anything that protects against removal
> of that vcc.
>
> The vcc uses vcc->sk socket for reference counting, so sock_hold()
> and sock_put() should be used by pppoatm.
That one I think *isn't* needed, because we have properly fixed the
races with vcc_destroy_socket(). I just wanted to check you agree...?
--
David Woodhouse Open Source Technology Centre
David.Woodhouse@intel.com Intel Corporation
[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]
^ permalink raw reply
* [PATCH 1/3] net: cpsw: replace pr_xxx with dev_xxx functions
From: Jan Luebbe @ 2012-12-03 13:49 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Mugunthan V N, Vaibhav Hiremath,
linux-arm-kernel, linux-omap, Jan Luebbe
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
---
drivers/net/ethernet/ti/cpsw.c | 47 ++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index fb1a692..c0e676a 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -729,7 +729,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
return -EINVAL;
if (of_property_read_u32(node, "slaves", &prop)) {
- pr_err("Missing slaves property in the DT.\n");
+ dev_err(&pdev->dev, "Missing slaves property in the DT.\n");
return -EINVAL;
}
data->slaves = prop;
@@ -737,91 +737,91 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
data->slaves, GFP_KERNEL);
if (!data->slave_data) {
- pr_err("Could not allocate slave memory.\n");
+ dev_err(&pdev->dev, "Could not allocate slave memory.\n");
return -EINVAL;
}
data->no_bd_ram = of_property_read_bool(node, "no_bd_ram");
if (of_property_read_u32(node, "cpdma_channels", &prop)) {
- pr_err("Missing cpdma_channels property in the DT.\n");
+ dev_err(&pdev->dev, "Missing cpdma_channels property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->channels = prop;
if (of_property_read_u32(node, "host_port_no", &prop)) {
- pr_err("Missing host_port_no property in the DT.\n");
+ dev_err(&pdev->dev, "Missing host_port_no property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->host_port_num = prop;
if (of_property_read_u32(node, "cpdma_reg_ofs", &prop)) {
- pr_err("Missing cpdma_reg_ofs property in the DT.\n");
+ dev_err(&pdev->dev, "Missing cpdma_reg_ofs property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->cpdma_reg_ofs = prop;
if (of_property_read_u32(node, "cpdma_sram_ofs", &prop)) {
- pr_err("Missing cpdma_sram_ofs property in the DT.\n");
+ dev_err(&pdev->dev, "Missing cpdma_sram_ofs property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->cpdma_sram_ofs = prop;
if (of_property_read_u32(node, "ale_reg_ofs", &prop)) {
- pr_err("Missing ale_reg_ofs property in the DT.\n");
+ dev_err(&pdev->dev, "Missing ale_reg_ofs property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->ale_reg_ofs = prop;
if (of_property_read_u32(node, "ale_entries", &prop)) {
- pr_err("Missing ale_entries property in the DT.\n");
+ dev_err(&pdev->dev, "Missing ale_entries property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->ale_entries = prop;
if (of_property_read_u32(node, "host_port_reg_ofs", &prop)) {
- pr_err("Missing host_port_reg_ofs property in the DT.\n");
+ dev_err(&pdev->dev, "Missing host_port_reg_ofs property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->host_port_reg_ofs = prop;
if (of_property_read_u32(node, "hw_stats_reg_ofs", &prop)) {
- pr_err("Missing hw_stats_reg_ofs property in the DT.\n");
+ dev_err(&pdev->dev, "Missing hw_stats_reg_ofs property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->hw_stats_reg_ofs = prop;
if (of_property_read_u32(node, "bd_ram_ofs", &prop)) {
- pr_err("Missing bd_ram_ofs property in the DT.\n");
+ dev_err(&pdev->dev, "Missing bd_ram_ofs property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->bd_ram_ofs = prop;
if (of_property_read_u32(node, "bd_ram_size", &prop)) {
- pr_err("Missing bd_ram_size property in the DT.\n");
+ dev_err(&pdev->dev, "Missing bd_ram_size property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->bd_ram_size = prop;
if (of_property_read_u32(node, "rx_descs", &prop)) {
- pr_err("Missing rx_descs property in the DT.\n");
+ dev_err(&pdev->dev, "Missing rx_descs property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
data->rx_descs = prop;
if (of_property_read_u32(node, "mac_control", &prop)) {
- pr_err("Missing mac_control property in the DT.\n");
+ dev_err(&pdev->dev, "Missing mac_control property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
@@ -833,14 +833,14 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
const void *mac_addr = NULL;
if (of_property_read_string(slave_node, "phy_id", &phy_id)) {
- pr_err("Missing slave[%d] phy_id property\n", i);
+ dev_err(&pdev->dev, "Missing slave[%d] phy_id property.\n", i);
ret = -EINVAL;
goto error_ret;
}
slave_data->phy_id = phy_id;
if (of_property_read_u32(slave_node, "slave_reg_ofs", &prop)) {
- pr_err("Missing slave[%d] slave_reg_ofs property\n", i);
+ dev_err(&pdev->dev, "Missing slave[%d] slave_reg_ofs property.\n", i);
ret = -EINVAL;
goto error_ret;
}
@@ -848,8 +848,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
if (of_property_read_u32(slave_node, "sliver_reg_ofs",
&prop)) {
- pr_err("Missing slave[%d] sliver_reg_ofs property\n",
- i);
+ dev_err(&pdev->dev, "Missing slave[%d] sliver_reg_ofs property.\n", i);
ret = -EINVAL;
goto error_ret;
}
@@ -868,7 +867,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
/* We do not want to force this, as in some cases may not have child */
if (ret)
- pr_warn("Doesn't have any child node\n");
+ dev_warn(&pdev->dev, "Doesn't have any child node\n");
return 0;
@@ -890,7 +889,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
ndev = alloc_etherdev(sizeof(struct cpsw_priv));
if (!ndev) {
- pr_err("error allocating net_device\n");
+ pr_err("cpsw: error allocating net_device\n");
return -ENOMEM;
}
@@ -909,7 +908,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
if (cpsw_probe_dt(&priv->data, pdev)) {
- pr_err("cpsw: platform data missing\n");
+ dev_err(&pdev->dev, "platform data missing\n");
ret = -ENODEV;
goto clean_ndev_ret;
}
@@ -917,10 +916,10 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
if (is_valid_ether_addr(data->slave_data[0].mac_addr)) {
memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN);
- pr_info("Detected MACID = %pM", priv->mac_addr);
+ dev_info(&pdev->dev, "Detected MACID = %pM", priv->mac_addr);
} else {
eth_random_addr(priv->mac_addr);
- pr_info("Random MACID = %pM", priv->mac_addr);
+ dev_info(&pdev->dev, "Random MACID = %pM", priv->mac_addr);
}
memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
@@ -1120,7 +1119,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct cpsw_priv *priv = netdev_priv(ndev);
- pr_info("removing device");
+ dev_info(&pdev->dev, "removing device");
platform_set_drvdata(pdev, NULL);
free_irq(ndev->irq, priv);
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/3] net: cpsw: verify correct number of slaves in DT
From: Jan Luebbe @ 2012-12-03 13:49 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Mugunthan V N, Vaibhav Hiremath,
linux-arm-kernel, linux-omap, Jan Luebbe
In-Reply-To: <1354542569-6165-1-git-send-email-jlu@pengutronix.de>
Check that the number of available slaves passed from DT matches the
value of the "slaves" property in the cpsw node. Otherwise, priv->slaves
would be the wrong size.
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
---
drivers/net/ethernet/ti/cpsw.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index c0e676a..8de3e92 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -832,6 +832,16 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
const char *phy_id = NULL;
const void *mac_addr = NULL;
+ if (!of_device_is_available(slave_node))
+ continue;
+
+ if (i >= data->slaves) {
+ dev_err(&pdev->dev, "Too many slaves in the DT (> %d).\n",
+ data->slaves);
+ ret = -EINVAL;
+ goto error_ret;
+ }
+
if (of_property_read_string(slave_node, "phy_id", &phy_id)) {
dev_err(&pdev->dev, "Missing slave[%d] phy_id property.\n", i);
ret = -EINVAL;
@@ -861,6 +871,13 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
i++;
}
+ if (i < data->slaves) {
+ dev_err(&pdev->dev, "Not enough slaves in the DT (< %d).\n",
+ data->slaves);
+ ret = -EINVAL;
+ goto error_ret;
+ }
+
/*
* Populate all the child nodes here...
*/
--
1.7.10.4
^ permalink raw reply related
* [PATCH 3/3] net: cpsw: implement ioctl for MII
From: Jan Luebbe @ 2012-12-03 13:49 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Mugunthan V N, Vaibhav Hiremath,
linux-arm-kernel, linux-omap, Jan Luebbe
In-Reply-To: <1354542569-6165-1-git-send-email-jlu@pengutronix.de>
This allows using tools like mii-diag on CPSW.
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
---
drivers/net/ethernet/ti/cpsw.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8de3e92..f476c03 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -629,6 +629,20 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)
dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n");
}
+static int cpsw_ndo_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+ struct phy_device *phy = priv->slaves[0].phy;
+
+ if (!netif_running(ndev))
+ return -EINVAL;
+
+ if (!phy)
+ return -ENODEV;
+
+ return phy_mii_ioctl(phy, rq, cmd);
+}
+
static void cpsw_ndo_tx_timeout(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
@@ -670,6 +684,7 @@ static const struct net_device_ops cpsw_netdev_ops = {
.ndo_start_xmit = cpsw_ndo_start_xmit,
.ndo_change_rx_flags = cpsw_ndo_change_rx_flags,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = cpsw_ndo_do_ioctl,
.ndo_change_mtu = eth_change_mtu,
.ndo_tx_timeout = cpsw_ndo_tx_timeout,
.ndo_get_stats = cpsw_ndo_get_stats,
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] net/macb: Use dmapool to align descriptors on 64bits
From: Ben Hutchings @ 2012-12-03 14:01 UTC (permalink / raw)
To: Nicolas Ferre
Cc: David S. Miller, netdev, linux-arm-kernel, linux-kernel,
Joachim Eastwood, Jean-Christophe PLAGNIOL-VILLARD
In-Reply-To: <1354536914-6315-1-git-send-email-nicolas.ferre@atmel.com>
On Mon, 2012-12-03 at 13:15 +0100, Nicolas Ferre wrote:
> Depending on datapath, some revisions of GEM need
> 64bits aligned descriptors. Use dmapool to allocate
> these descriptors.
> Note that different size between RX and TX rings
> leads to the creation of two pools.
>
> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
[...]
dma_alloc_coherent() allocates whole pages, which I think is quite
enough alignment. You can't save memory by doing this, since each pool
needs at least one page. So what is this change meant to achieve?
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [net-next PATCH V2 5/9] net: frag, per CPU resource, mem limit and LRU list accounting
From: Jesper Dangaard Brouer @ 2012-12-03 14:02 UTC (permalink / raw)
To: Eric Dumazet
Cc: David S. Miller, Florian Westphal, netdev, Pablo Neira Ayuso,
Thomas Graf, Cong Wang, Patrick McHardy, Paul E. McKenney,
Herbert Xu
In-Reply-To: <1354208776.14302.1898.camel@edumazet-glaptop>
On Thu, 2012-11-29 at 09:06 -0800, Eric Dumazet wrote:
> On Thu, 2012-11-29 at 17:13 +0100, Jesper Dangaard Brouer wrote:
> > The major performance bottleneck on NUMA systems, is the mem limit
> > counter which is based an atomic counter. This patch removes the
> > cache-bouncing of the atomic counter, by moving this accounting to be
> > bound to each CPU. The LRU list also need to be done per CPU,
> > in-order to keep the accounting straight.
> >
> > If fragments belonging together is "sprayed" across CPUs, performance
> > will still suffer, but due to NIC rxhashing this is not very common.
> > Correct accounting in this situation is maintained by recording and
> > "assigning" a CPU to a frag queue when its allocated (caused by the
> > first packet associated packet).
> >
[...]
> > +/* Need to maintain these resource limits per CPU, else we will kill
> > + * performance due to cache-line bouncing
> > + */
> > +struct frag_cpu_limit {
> > + atomic_t mem;
> > + struct list_head lru_list;
> > + spinlock_t lru_lock;
> > +} ____cacheline_aligned_in_smp;
> > +
>
> This looks like a big patch introducing a specific infrastructure, while
> we already have lib/percpu_counter.c
For the record, I cannot use the lib/percpu_counter, because this
accounting is not kept strictly per CPU, if the fragments are "sprayed"
across CPUs (as described in the commit message above).
^ permalink raw reply
* Re: [PATCH net-next 3/7] ipv6: improve ipv6_find_hdr() to skip empty routing headers
From: Pablo Neira Ayuso @ 2012-12-03 14:04 UTC (permalink / raw)
To: Jesse Gross; +Cc: David Miller, netdev, dev, Ansis Atteka
In-Reply-To: <1354214149-33651-4-git-send-email-jesse@nicira.com>
On Thu, Nov 29, 2012 at 10:35:45AM -0800, Jesse Gross wrote:
> From: Ansis Atteka <aatteka@nicira.com>
>
> This patch prepares ipv6_find_hdr() function so that it could be
> able to skip routing headers, where segements_left is 0. This is
> required to handle multiple routing header case correctly when
> changing IPv6 addresses.
>
> Signed-off-by: Ansis Atteka <aatteka@nicira.com>
> Signed-off-by: Jesse Gross <jesse@nicira.com>
> ---
> include/net/ipv6.h | 5 +++--
> net/ipv6/exthdrs_core.c | 36 ++++++++++++++++++++++++++++--------
> 2 files changed, 31 insertions(+), 10 deletions(-)
>
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index b2f0cfb..acbd8e0 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -631,8 +631,9 @@ extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
> extern bool ipv6_ext_hdr(u8 nexthdr);
>
> enum {
> - IP6_FH_F_FRAG = (1 << 0),
> - IP6_FH_F_AUTH = (1 << 1),
> + IP6_FH_F_FRAG = (1 << 0),
> + IP6_FH_F_AUTH = (1 << 1),
> + IP6_FH_F_SKIP_RH = (1 << 2),
> };
>
> /* find specified header and get offset to it */
> diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
> index 8ea253a..11b4e29 100644
> --- a/net/ipv6/exthdrs_core.c
> +++ b/net/ipv6/exthdrs_core.c
> @@ -132,9 +132,11 @@ EXPORT_SYMBOL(ipv6_skip_exthdr);
> * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
> * isn't NULL.
> *
> - * if flags is not NULL and it's a fragment, then the frag flag IP6_FH_F_FRAG
> - * will be set. If it's an AH header, the IP6_FH_F_AUTH flag is set and
> - * target < 0, then this function will stop at the AH header.
> + * if flags is not NULL and it's a fragment, then the frag flag
> + * IP6_FH_F_FRAG will be set. If it's an AH header, the
> + * IP6_FH_F_AUTH flag is set and target < 0, then this function will
> + * stop at the AH header. If IP6_FH_F_SKIP_RH flag was passed, then this
> + * function will skip all those routing headers, where segements_left was 0.
> */
> int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> int target, unsigned short *fragoff, int *flags)
> @@ -142,6 +144,7 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
> u8 nexthdr = ipv6_hdr(skb)->nexthdr;
> unsigned int len;
> + bool found;
>
> if (fragoff)
> *fragoff = 0;
> @@ -159,9 +162,10 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> }
> len = skb->len - start;
>
> - while (nexthdr != target) {
If the offset is set as parameter via ipv6_find_hdr, we now are always
entering the loop even if we found the target header we're looking
for, before that didn't happen.
Something seems wrong here to me.
> + do {
> struct ipv6_opt_hdr _hdr, *hp;
> unsigned int hdrlen;
> + found = (nexthdr == target);
>
> if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
> if (target < 0)
> @@ -172,6 +176,20 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
> if (hp == NULL)
> return -EBADMSG;
> +
> + if (nexthdr == NEXTHDR_ROUTING) {
> + struct ipv6_rt_hdr _rh, *rh;
> +
> + rh = skb_header_pointer(skb, start, sizeof(_rh),
> + &_rh);
> + if (rh == NULL)
> + return -EBADMSG;
> +
> + if (flags && (*flags & IP6_FH_F_SKIP_RH) &&
> + rh->segments_left == 0)
> + found = false;
> + }
> +
> if (nexthdr == NEXTHDR_FRAGMENT) {
> unsigned short _frag_off;
> __be16 *fp;
> @@ -205,10 +223,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
> } else
> hdrlen = ipv6_optlen(hp);
>
> - nexthdr = hp->nexthdr;
> - len -= hdrlen;
> - start += hdrlen;
> - }
> + if (!found) {
> + nexthdr = hp->nexthdr;
> + len -= hdrlen;
> + start += hdrlen;
> + }
> + } while (!found);
>
> *offset = start;
> return nexthdr;
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 3/3] net: cpsw: implement ioctl for MII
From: Ben Hutchings @ 2012-12-03 14:16 UTC (permalink / raw)
To: Jan Luebbe
Cc: netdev, David S. Miller, Mugunthan V N, Vaibhav Hiremath,
linux-arm-kernel, linux-omap
In-Reply-To: <1354542569-6165-3-git-send-email-jlu@pengutronix.de>
On Mon, 2012-12-03 at 14:49 +0100, Jan Luebbe wrote:
> This allows using tools like mii-diag on CPSW.
>
> Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
> ---
> drivers/net/ethernet/ti/cpsw.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index 8de3e92..f476c03 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -629,6 +629,20 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)
> dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n");
> }
>
> +static int cpsw_ndo_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
> +{
> + struct cpsw_priv *priv = netdev_priv(ndev);
> + struct phy_device *phy = priv->slaves[0].phy;
> +
> + if (!netif_running(ndev))
> + return -EINVAL;
This is consistent with other drivers, and I'm not going to object to
one more instance, but I don't think this is the proper error code - we
don't know that there's anything wrong with the arguments, it's just
that the *device* is in the wrong state. I don't know what the right
error code is, though. Really I would prefer that MDIO would work even
when the device is down, unless you know that all MDIO-manageable
devices are powered off.
Ben.
> + if (!phy)
> + return -ENODEV;
> +
> + return phy_mii_ioctl(phy, rq, cmd);
> +}
> +
> static void cpsw_ndo_tx_timeout(struct net_device *ndev)
> {
> struct cpsw_priv *priv = netdev_priv(ndev);
> @@ -670,6 +684,7 @@ static const struct net_device_ops cpsw_netdev_ops = {
> .ndo_start_xmit = cpsw_ndo_start_xmit,
> .ndo_change_rx_flags = cpsw_ndo_change_rx_flags,
> .ndo_validate_addr = eth_validate_addr,
> + .ndo_do_ioctl = cpsw_ndo_do_ioctl,
> .ndo_change_mtu = eth_change_mtu,
> .ndo_tx_timeout = cpsw_ndo_tx_timeout,
> .ndo_get_stats = cpsw_ndo_get_stats,
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [patch net-next] net: call notifiers for mtu change even if iface is not up
From: Neil Horman @ 2012-12-03 14:18 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem, edumazet, bhutchings, psimerda
In-Reply-To: <1354533392-9308-1-git-send-email-jiri@resnulli.us>
On Mon, Dec 03, 2012 at 12:16:32PM +0100, Jiri Pirko wrote:
> Do the same thing as in set mac. Call notifiers every time.
>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
> ---
> net/core/dev.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 2f94df2..0685a72 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -4971,7 +4971,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
> else
> dev->mtu = new_mtu;
>
> - if (!err && dev->flags & IFF_UP)
> + if (!err)
> call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
> return err;
> }
I'm not opposed to this change, but is there something that it expressly fixes?
While it doesn't hurt to send around mtu change events, one would presume that
listeners would pick up mtu changes when the NETDEV_UP event went' around.
Neil
^ permalink raw reply
* Re: [patch net-next] net: call notifiers for mtu change even if iface is not up
From: Jiri Pirko @ 2012-12-03 14:22 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev, davem, edumazet, bhutchings, psimerda
In-Reply-To: <20121203141823.GA21816@hmsreliant.think-freely.org>
Mon, Dec 03, 2012 at 03:18:23PM CET, nhorman@tuxdriver.com wrote:
>On Mon, Dec 03, 2012 at 12:16:32PM +0100, Jiri Pirko wrote:
>> Do the same thing as in set mac. Call notifiers every time.
>>
>> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
>> ---
>> net/core/dev.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index 2f94df2..0685a72 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -4971,7 +4971,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
>> else
>> dev->mtu = new_mtu;
>>
>> - if (!err && dev->flags & IFF_UP)
>> + if (!err)
>> call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
>> return err;
>> }
>
>I'm not opposed to this change, but is there something that it expressly fixes?
This is about a consistency. To have the same behaviour as set_mac
for example.
>While it doesn't hurt to send around mtu change events, one would presume that
>listeners would pick up mtu changes when the NETDEV_UP event went' around.
>
>Neil
>
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: [PATCH v2] net/macb: Use non-coherent memory for rx buffers
From: David Laight @ 2012-12-03 14:25 UTC (permalink / raw)
To: Nicolas Ferre
Cc: David S. Miller, netdev, linux-arm-kernel, linux-kernel,
Joachim Eastwood, Jean-Christophe PLAGNIOL-VILLARD,
Havard Skinnemoen
In-Reply-To: <50BCA746.1020705@atmel.com>
> On 12/03/2012 01:43 PM, David Laight :
> >> Allocate regular pages to use as backing for the RX ring and use the
> >> DMA API to sync the caches. This should give a bit better performance
> >> since it allows the CPU to do burst transfers from memory. It is also
> >> a necessary step on the way to reduce the amount of copying done by
> >> the driver.
> >
> > I've not tried to understand the patches, but you have to be
> > very careful using non-snooped memory for descriptor rings.
> > No amount of DMA API calls can sort out some of the issues.
>
> David,
>
> Maybe I have not described the patch properly but the non-coherent
> memory is not used for descriptor rings. It is used for DMA buffers
> pointed out by descriptors (that are allocated as coherent memory).
>
> As buffers are filled up by the interface DMA and then, afterwards, used
> by the driver to pass data to the net layer, it seems to me that the use
> of non-coherent memory is sensible.
Ah, ok - difficult to actually determine from a fast read of the code.
So you invalidate (I think that is the right term) all the cache lines
that are part of each rx buffer before giving it back to the MAC unit.
(Maybe that first time, and just those cache lines that might have been
written to after reception - I'd worry about whether the CRC is written
into the rx buffer!)
I was wondering if the code needs to do per page allocations?
Perhaps that is necessary to avoid needing a large block of
contiguous physical memory (and virtual addresses)?
I know from some experiments done many years ago that a data
copy in the MAC tx and rx path isn't necessarily as bad as
people may think - especially if it removes complicated
'buffer loaning' schemes and/or iommu setup (or bounce
buffers due to limited hardware memory addressing).
The rx copy can usually be made to be a 'whole word' copy
(ie you copy the two bytes of garbage that (mis)align the
destination MAC address, and some bytes after the CRC.
With some hardware I believe it is possible for the cache
controller to do cache-line aligned copies very quickly!
(Some very new x86 cpus might be doing this for 'rep movsd'.)
The copy in the rx path is also better for short packets
the can end up queued for userspace (although a copy in
the socket code would solve that one.
David
^ permalink raw reply
* [PATCH net-next] bridge: implement multicast fast leave
From: Cong Wang @ 2012-12-03 14:36 UTC (permalink / raw)
To: netdev; +Cc: Herbert Xu, Stephen Hemminger, bridge, David S. Miller, Cong Wang
Fast leave allows bridge to immediately stops the multicast
traffic on the port receives IGMP Leave when IGMP snooping is enabled,
no timeouts are observed.
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index d53e4f4..05e0572 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1226,6 +1226,40 @@ static void br_multicast_leave_group(struct net_bridge *br,
if (!mp)
goto out;
+ if (br->multicast_fast_leave) {
+ struct net_bridge_port_group __rcu **pp;
+
+ if (!port) {
+ mp->mglist = false;
+
+ if (mp->ports)
+ goto out;
+
+ hlist_del_rcu(&mp->hlist[mdb->ver]);
+ mdb->size--;
+ del_timer(&mp->timer);
+ call_rcu_bh(&mp->rcu, br_multicast_free_group);
+ goto out;
+ }
+
+ for (pp = &mp->ports;
+ (p = mlock_dereference(*pp, br)) != NULL;
+ pp = &p->next) {
+ if (p->port != port)
+ continue;
+
+ rcu_assign_pointer(*pp, p->next);
+ hlist_del_init(&p->mglist);
+ del_timer(&p->timer);
+ call_rcu_bh(&p->rcu, br_multicast_free_pg);
+
+ if (!mp->ports && !mp->mglist &&
+ netif_running(br->dev))
+ mod_timer(&mp->timer, jiffies);
+ }
+ goto out;
+ }
+
now = jiffies;
time = now + br->multicast_last_member_count *
br->multicast_last_member_interval;
@@ -1567,6 +1601,7 @@ void br_multicast_init(struct net_bridge *br)
br->hash_max = 512;
br->multicast_router = 1;
+ br->multicast_fast_leave = 0;
br->multicast_querier = 0;
br->multicast_last_member_count = 2;
br->multicast_startup_query_count = 2;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 6484069..2f5f5b8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -230,6 +230,7 @@ struct net_bridge
u8 multicast_disabled:1;
u8 multicast_querier:1;
+ u8 multicast_fast_leave:1;
u32 hash_elasticity;
u32 hash_max;
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 5913a3a..f88389f 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -375,6 +375,32 @@ static ssize_t store_multicast_snooping(struct device *d,
static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,
show_multicast_snooping, store_multicast_snooping);
+static ssize_t show_multicast_fast_leave(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct net_bridge *br = to_bridge(d);
+ return sprintf(buf, "%d\n", br->multicast_fast_leave);
+}
+
+static int set_fast_leave(struct net_bridge *br, unsigned long val)
+{
+ if (br->multicast_disabled)
+ return -EINVAL;
+
+ br->multicast_fast_leave = !!val;
+ return 0;
+}
+
+static ssize_t store_multicast_fast_leave(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ return store_bridge_parm(d, buf, len, set_fast_leave);
+}
+static DEVICE_ATTR(multicast_fast_leave, S_IRUGO | S_IWUSR,
+ show_multicast_fast_leave, store_multicast_fast_leave);
+
static ssize_t show_multicast_querier(struct device *d,
struct device_attribute *attr,
char *buf)
@@ -715,6 +741,7 @@ static struct attribute *bridge_attrs[] = {
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
&dev_attr_multicast_router.attr,
&dev_attr_multicast_snooping.attr,
+ &dev_attr_multicast_fast_leave.attr,
&dev_attr_multicast_querier.attr,
&dev_attr_hash_elasticity.attr,
&dev_attr_hash_max.attr,
^ permalink raw reply related
* Re: [patch net-next] net: call notifiers for mtu change even if iface is not up
From: Neil Horman @ 2012-12-03 15:22 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem, edumazet, bhutchings, psimerda
In-Reply-To: <20121203142229.GA3054@minipsycho.orion>
On Mon, Dec 03, 2012 at 03:22:29PM +0100, Jiri Pirko wrote:
> Mon, Dec 03, 2012 at 03:18:23PM CET, nhorman@tuxdriver.com wrote:
> >On Mon, Dec 03, 2012 at 12:16:32PM +0100, Jiri Pirko wrote:
> >> Do the same thing as in set mac. Call notifiers every time.
> >>
> >> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
> >> ---
> >> net/core/dev.c | 2 +-
> >> 1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/net/core/dev.c b/net/core/dev.c
> >> index 2f94df2..0685a72 100644
> >> --- a/net/core/dev.c
> >> +++ b/net/core/dev.c
> >> @@ -4971,7 +4971,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
> >> else
> >> dev->mtu = new_mtu;
> >>
> >> - if (!err && dev->flags & IFF_UP)
> >> + if (!err)
> >> call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
> >> return err;
> >> }
> >
> >I'm not opposed to this change, but is there something that it expressly fixes?
>
> This is about a consistency. To have the same behaviour as set_mac
> for example.
>
> >While it doesn't hurt to send around mtu change events, one would presume that
> >listeners would pick up mtu changes when the NETDEV_UP event went' around.
> >
> >Neil
> >
I figured, I just wanted to be sure that there wasn't a bug fix that needed
documenting in the changelog, or that listeners for this event didn't expect the
interface to already be up. It looks pretty clean, with the exception of the
TIPC protocol. It appears that it might require enable_bearer to be called
prior to any netdevice CHANGEMTU events, so that the eth_bearers array gets
filled out, and it looks like that has to get triggered either by user space, or
the receipt of a message over the network. Let me know what you think
Neil
> >--
> >To unsubscribe from this list: send the line "unsubscribe netdev" in
> >the body of a message to majordomo@vger.kernel.org
> >More majordomo info at http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH] vxlan: Fix error that was resulting in VXLAN MTU size being 10 bytes too large
From: Joseph Glanville @ 2012-12-03 15:26 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, alexander.h.duyck, netdev
In-Reply-To: <20121119080351.477525b3@nehalam.linuxnetplumber.net>
On 20 November 2012 03:03, Stephen Hemminger <shemminger@vyatta.com> wrote:
> On Mon, 19 Nov 2012 22:33:50 +1100
> Joseph Glanville <joseph.glanville@orionvm.com.au> wrote:
>
>> On 14 November 2012 08:33, Stephen Hemminger <shemminger@vyatta.com> wrote:
>> > On Tue, 13 Nov 2012 14:37:19 -0500 (EST)
>> > David Miller <davem@davemloft.net> wrote:
>> >
>> >> From: Alexander Duyck <alexander.h.duyck@intel.com>
>> >> Date: Fri, 09 Nov 2012 15:35:24 -0800
>> >>
>> >> > This change fixes an issue I found where VXLAN frames were fragmented when
>> >> > they were up to the VXLAN MTU size. I root caused the issue to the fact that
>> >> > the headroom was 4 + 20 + 8 + 8. This math doesn't appear to be correct
>> >> > because we are not inserting a VLAN header, but instead a 2nd Ethernet header.
>> >> > As such the math for the overhead should be 20 + 8 + 8 + 14 to account for the
>> >> > extra headers that are inserted for VXLAN.
>> >> >
>> >> > Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
>> >>
>> >> Applied, thanks for the detailed commit message.
>> >
>> > Probably need smarter code there to look at header length requirement
>> > of underlying device as well, maybe someone will be perverse and runn
>> > vxlan over a tunnel or IPoIB.
>>
>> Forgive my ignorance but why would running VXLAN on IPoIB require
>> special header handling? (and would it work or behave strangely?)
>>
>> I was planning on giving this a go when 3.7 is released but I might do
>> that sooner if problems are anticipated.
>>
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe netdev" in
>> > the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>> Joseph.
>>
>
> Some lower layers require bigger (or smaller headers). As it was, vxlan
> was only allocating skb with a fixed amount of headroom. This would lead to
> lower layers having to copy the skb.
>
> My suggestion has already been addressed by a later patch.
Hi,
I have tested VXLAN on IPoIB and it works perfectly. :)
Joseph.
--
CTO | Orion Virtualisation Solutions | www.orionvm.com.au
Phone: 1300 56 99 52 | Mobile: 0428 754 846
^ permalink raw reply
* Re: [Suggestion] net/atm : for sprintf, need check the total write length whether larger than a page.
From: chas williams - CONTRACTOR @ 2012-12-03 15:48 UTC (permalink / raw)
To: Chen Gang
Cc: David.Woodhouse, David Miller, krzysiek, Joe Perches, edumazet,
netdev
In-Reply-To: <50BC6958.6080803@asianux.com>
yes this seems like it should be done. maybe this week i will try to
put something together unless you already have a patch somewhere.
On Mon, 03 Dec 2012 16:56:56 +0800
Chen Gang <gang.chen@asianux.com> wrote:
> Hello Maintainers:
>
> was this suggestion replied ? (it seems not).
>
> and please help to check whether this suggestion is valid.
>
> thanks.
>
> gchen.
>
>
> 于 2012年11月21日 12:29, Chen Gang 写道:
> > Hello David Miller:
> >
> > in net/atm/atm_sysfs.c:
> > suggest to check the write length whether larger than a page.
> > the length of parameter buf is one page size (reference: fill_read_buffer at fs/sysfs/file.c)
> > and the count of atm adresses are not limited (reference: atm_dev_ioctl -> atm_add_addr)
> >
> > thanks.
> >
> > gchen.
> >
> > 34 static ssize_t show_atmaddress(struct device *cdev,
> > 35 struct device_attribute *attr, char *buf)
> > 36 {
> > 37 unsigned long flags;
> > 38 char *pos = buf;
> > 39 struct atm_dev *adev = to_atm_dev(cdev);
> > 40 struct atm_dev_addr *aaddr;
> > 41 int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin;
> > 42 int i, j;
> > 43
> > 44 spin_lock_irqsave(&adev->lock, flags);
> > 45 list_for_each_entry(aaddr, &adev->local, entry) {
> > 46 for (i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) {
> > 47 if (j == *fmt) {
> > 48 pos += sprintf(pos, ".");
> > 49 ++fmt;
> > 50 j = 0;
> > 51 }
> > 52 pos += sprintf(pos, "%02x",
> > 53 aaddr->addr.sas_addr.prv[i]);
> > 54 }
> > 55 pos += sprintf(pos, "\n");
> > 56 }
> > 57 spin_unlock_irqrestore(&adev->lock, flags);
> > 58
> > 59 return pos - buf;
> > 60 }
> > 61
> >
> >
> >
> > in net/atm/addr.c
> >
> > 67 int atm_add_addr(struct atm_dev *dev, const struct sockaddr_atmsvc *addr,
> > 68 enum atm_addr_type_t atype)
> > 69 {
> > 70 unsigned long flags;
> > 71 struct atm_dev_addr *this;
> > 72 struct list_head *head;
> > 73 int error;
> > 74
> > 75 error = check_addr(addr);
> > 76 if (error)
> > 77 return error;
> > 78 spin_lock_irqsave(&dev->lock, flags);
> > 79 if (atype == ATM_ADDR_LECS)
> > 80 head = &dev->lecs;
> > 81 else
> > 82 head = &dev->local;
> > 83 list_for_each_entry(this, head, entry) {
> > 84 if (identical(&this->addr, addr)) {
> > 85 spin_unlock_irqrestore(&dev->lock, flags);
> > 86 return -EEXIST;
> > 87 }
> > 88 }
> > 89 this = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC);
> > 90 if (!this) {
> > 91 spin_unlock_irqrestore(&dev->lock, flags);
> > 92 return -ENOMEM;
> > 93 }
> > 94 this->addr = *addr;
> > 95 list_add(&this->entry, head);
> > 96 spin_unlock_irqrestore(&dev->lock, flags);
> > 97 if (head == &dev->local)
> > 98 notify_sigd(dev);
> > 99 return 0;
> > 100 }
> > 101
> >
> >
> > in net/atm/resources.c
> >
> > 195 int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
> > 196 {
> > 197 void __user *buf;
> > 198 int error, len, number, size = 0;
> > 199 struct atm_dev *dev;
> > 200 struct list_head *p;
> > 201 int *tmp_buf, *tmp_p;
> > 202 int __user *sioc_len;
> > 203 int __user *iobuf_len;
> > 204
> > 205 #ifndef CONFIG_COMPAT
> > 206 compat = 0; /* Just so the compiler _knows_ */
> > 207 #endif
> > 208
> > 209 switch (cmd) {
> > 210 case ATM_GETNAMES:
> > 211 if (compat) {
> > 212 #ifdef CONFIG_COMPAT
> > 213 struct compat_atm_iobuf __user *ciobuf = arg;
> > 214 compat_uptr_t cbuf;
> > 215 iobuf_len = &ciobuf->length;
> > 216 if (get_user(cbuf, &ciobuf->buffer))
> > 217 return -EFAULT;
> > 218 buf = compat_ptr(cbuf);
> > 219 #endif
> > 220 } else {
> > 221 struct atm_iobuf __user *iobuf = arg;
> > 222 iobuf_len = &iobuf->length;
> > 223 if (get_user(buf, &iobuf->buffer))
> > 224 return -EFAULT;
> > 225 }
> > 226 if (get_user(len, iobuf_len))
> > 227 return -EFAULT;
> > 228 mutex_lock(&atm_dev_mutex);
> > 229 list_for_each(p, &atm_devs)
> > 230 size += sizeof(int);
> > 231 if (size > len) {
> > 232 mutex_unlock(&atm_dev_mutex);
> > 233 return -E2BIG;
> > 234 }
> > 235 tmp_buf = kmalloc(size, GFP_ATOMIC);
> > 236 if (!tmp_buf) {
> > 237 mutex_unlock(&atm_dev_mutex);
> > 238 return -ENOMEM;
> > 239 }
> > 240 tmp_p = tmp_buf;
> > 241 list_for_each(p, &atm_devs) {
> > 242 dev = list_entry(p, struct atm_dev, dev_list);
> > 243 *tmp_p++ = dev->number;
> > 244 }
> > 245 mutex_unlock(&atm_dev_mutex);
> > 246 error = ((copy_to_user(buf, tmp_buf, size)) ||
> > 247 put_user(size, iobuf_len))
> > 248 ? -EFAULT : 0;
> > 249 kfree(tmp_buf);
> > 250 return error;
> > 251 default:
> > 252 break;
> > 253 }
> > 254
> > 255 if (compat) {
> > 256 #ifdef CONFIG_COMPAT
> > 257 struct compat_atmif_sioc __user *csioc = arg;
> > 258 compat_uptr_t carg;
> > 259
> > 260 sioc_len = &csioc->length;
> > 261 if (get_user(carg, &csioc->arg))
> > 262 return -EFAULT;
> > 263 buf = compat_ptr(carg);
> > 264
> > 265 if (get_user(len, &csioc->length))
> > 266 return -EFAULT;
> > 267 if (get_user(number, &csioc->number))
> > 268 return -EFAULT;
> > 269 #endif
> > 270 } else {
> > 271 struct atmif_sioc __user *sioc = arg;
> > 272
> > 273 sioc_len = &sioc->length;
> > 274 if (get_user(buf, &sioc->arg))
> > 275 return -EFAULT;
> > 276 if (get_user(len, &sioc->length))
> > 277 return -EFAULT;
> > 278 if (get_user(number, &sioc->number))
> > 279 return -EFAULT;
> > 280 }
> > 281
> > 282 dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d",
> > 283 number);
> > 284 if (!dev)
> > 285 return -ENODEV;
> > 286
> > 287 switch (cmd) {
> > 288 case ATM_GETTYPE:
> > 289 size = strlen(dev->type) + 1;
> > 290 if (copy_to_user(buf, dev->type, size)) {
> > 291 error = -EFAULT;
> > 292 goto done;
> > 293 }
> > 294 break;
> > 295 case ATM_GETESI:
> > 296 size = ESI_LEN;
> > 297 if (copy_to_user(buf, dev->esi, size)) {
> > 298 error = -EFAULT;
> > 299 goto done;
> > 300 }
> > 301 break;
> > 302 case ATM_SETESI:
> > 303 {
> > 304 int i;
> > 305
> > 306 for (i = 0; i < ESI_LEN; i++)
> > 307 if (dev->esi[i]) {
> > 308 error = -EEXIST;
> > 309 goto done;
> > 310 }
> > 311 }
> > 312 /* fall through */
> > 313 case ATM_SETESIF:
> > 314 {
> > 315 unsigned char esi[ESI_LEN];
> > 316
> > 317 if (!capable(CAP_NET_ADMIN)) {
> > 318 error = -EPERM;
> > 319 goto done;
> > 320 }
> > 321 if (copy_from_user(esi, buf, ESI_LEN)) {
> > 322 error = -EFAULT;
> > 323 goto done;
> > 324 }
> > 325 memcpy(dev->esi, esi, ESI_LEN);
> > 326 error = ESI_LEN;
> > 327 goto done;
> > 328 }
> > 329 case ATM_GETSTATZ:
> > 330 if (!capable(CAP_NET_ADMIN)) {
> > 331 error = -EPERM;
> > 332 goto done;
> > 333 }
> > 334 /* fall through */
> > 335 case ATM_GETSTAT:
> > 336 size = sizeof(struct atm_dev_stats);
> > 337 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ);
> > 338 if (error)
> > 339 goto done;
> > 340 break;
> > 341 case ATM_GETCIRANGE:
> > 342 size = sizeof(struct atm_cirange);
> > 343 if (copy_to_user(buf, &dev->ci_range, size)) {
> > 344 error = -EFAULT;
> > 345 goto done;
> > 346 }
> > 347 break;
> > 348 case ATM_GETLINKRATE:
> > 349 size = sizeof(int);
> > 350 if (copy_to_user(buf, &dev->link_rate, size)) {
> > 351 error = -EFAULT;
> > 352 goto done;
> > 353 }
> > 354 break;
> > 355 case ATM_RSTADDR:
> > 356 if (!capable(CAP_NET_ADMIN)) {
> > 357 error = -EPERM;
> > 358 goto done;
> > 359 }
> > 360 atm_reset_addr(dev, ATM_ADDR_LOCAL);
> > 361 break;
> > 362 case ATM_ADDADDR:
> > 363 case ATM_DELADDR:
> > 364 case ATM_ADDLECSADDR:
> > 365 case ATM_DELLECSADDR:
> > 366 {
> > 367 struct sockaddr_atmsvc addr;
> > 368
> > 369 if (!capable(CAP_NET_ADMIN)) {
> > 370 error = -EPERM;
> > 371 goto done;
> > 372 }
> > 373
> > 374 if (copy_from_user(&addr, buf, sizeof(addr))) {
> > 375 error = -EFAULT;
> > 376 goto done;
> > 377 }
> > 378 if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR)
> > 379 error = atm_add_addr(dev, &addr,
> > 380 (cmd == ATM_ADDADDR ?
> > 381 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
> > 382 else
> > 383 error = atm_del_addr(dev, &addr,
> > 384 (cmd == ATM_DELADDR ?
> > 385 ATM_ADDR_LOCAL : ATM_ADDR_LECS));
> > 386 goto done;
> > 387 }
> > ... ...
> > ... ...
> >
> >
> >
>
>
^ permalink raw reply
* Re: [PATCH net-next] bridge: implement multicast fast leave
From: Stephen Hemminger @ 2012-12-03 15:53 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, bridge, David S. Miller, Herbert Xu
In-Reply-To: <1354545363-11953-1-git-send-email-amwang@redhat.com>
On Mon, 3 Dec 2012 22:36:03 +0800
Cong Wang <amwang@redhat.com> wrote:
> Fast leave allows bridge to immediately stops the multicast
> traffic on the port receives IGMP Leave when IGMP snooping is enabled,
> no timeouts are observed.
>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: Stephen Hemminger <shemminger@vyatta.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Signed-off-by: Cong Wang <amwang@redhat.com>
I like the feature, and it looks like an oversight in the initial design.
Why is this not the default, adding more options obscures it.
^ permalink raw reply
* Re: [net-next RFC] pktgen: don't wait for the device who doesn't free skb immediately after sent
From: Stephen Hemminger @ 2012-12-03 16:01 UTC (permalink / raw)
To: Jason Wang; +Cc: mst, netdev, linux-kernel, virtualization, davem
In-Reply-To: <2663254.1vRFru9xhh@jason-thinkpad-t430s>
On Mon, 03 Dec 2012 14:45:46 +0800
Jason Wang <jasowang@redhat.com> wrote:
> On Tuesday, November 27, 2012 08:49:19 AM Stephen Hemminger wrote:
> > On Tue, 27 Nov 2012 14:45:13 +0800
> >
> > Jason Wang <jasowang@redhat.com> wrote:
> > > On 11/27/2012 01:37 AM, Stephen Hemminger wrote:
> > > > On Mon, 26 Nov 2012 15:56:52 +0800
> > > >
> > > > Jason Wang <jasowang@redhat.com> wrote:
> > > >> Some deivces do not free the old tx skbs immediately after it has been
> > > >> sent
> > > >> (usually in tx interrupt). One such example is virtio-net which
> > > >> optimizes for virt and only free the possible old tx skbs during the
> > > >> next packet sending. This would lead the pktgen to wait forever in the
> > > >> refcount of the skb if no other pakcet will be sent afterwards.
> > > >>
> > > >> Solving this issue by introducing a new flag IFF_TX_SKB_FREE_DELAY
> > > >> which could notify the pktgen that the device does not free skb
> > > >> immediately after it has been sent and let it not to wait for the
> > > >> refcount to be one.
> > > >>
> > > >> Signed-off-by: Jason Wang <jasowang@redhat.com>
> > > >
> > > > Another alternative would be using skb_orphan() and skb->destructor.
> > > > There are other cases where skb's are not freed right away.
> > > > --
> > > > To unsubscribe from this list: send the line "unsubscribe netdev" in
> > > > the body of a message to majordomo@vger.kernel.org
> > > > More majordomo info at http://vger.kernel.org/majordomo-info.html
> > >
> > > Hi Stephen:
> > >
> > > Do you mean registering a skb->destructor for pktgen then set and check
> > > bits in skb->tx_flag?
> >
> > Yes. Register a destructor that does something like update a counter (number
> > of packets pending), then just spin while number of packets pending is over
> > threshold.
>
> Have some experiments on this, looks like it does not work weel when clone_skb
> is used. For driver that call skb_orphan() in ndo_start_xmit, the destructor
> is only called when the first packet were sent, but what we need to know is
> when the last were sent. Any thoughts on this or we can just introduce another
> flag (anyway we have something like IFF_TX_SKB_SHARING) ?
>
The SKB_SHARING flag looks like the best solution then.
Surprisingly, transmit buffer completion is a major bottleneck for 10G
devices, and I suspect more changes will come.
^ permalink raw reply
* [RFT PATCH] 8139cp: properly support change of MTU values [v2]
From: John Greene @ 2012-12-03 16:19 UTC (permalink / raw)
To: netdev; +Cc: John Greene, David S. Miller
The 8139cp driver has a change_mtu function that has not been
enabled since the dawn of the git repository. However, the
generic eth_change_mtu is not used in its place, so that
invalid MTU values can be set on the interface.
Original patch salvages the broken code for the single case of
setting the MTU while the interface is down, which is safe
and also includes the range check. Now enhanced to support up
or down interface.
v2: fix case where rxbufsz isn't changed in the up state case
Original patch from
http://lkml.indiana.edu/hypermail/linux/kernel/1202.2/00770.html
Testing: has been test on virtual 8139cp setup without issue,
have no access real hardware 8139cp, need testing help.
Signed-off-by: "John Greene" <jogreene@redhat.com>
CC: "David S. Miller" <davem@davemloft.net>
---
drivers/net/ethernet/realtek/8139cp.c | 23 ++++-------------------
1 file changed, 4 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 6cb96b4..0da3f5e 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1226,12 +1226,9 @@ static void cp_tx_timeout(struct net_device *dev)
spin_unlock_irqrestore(&cp->lock, flags);
}
-#ifdef BROKEN
static int cp_change_mtu(struct net_device *dev, int new_mtu)
{
struct cp_private *cp = netdev_priv(dev);
- int rc;
- unsigned long flags;
/* check for invalid MTU, according to hardware limits */
if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
@@ -1244,22 +1241,12 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
- spin_lock_irqsave(&cp->lock, flags);
-
- cp_stop_hw(cp); /* stop h/w and free rings */
- cp_clean_rings(cp);
-
+ /* network IS up, close it, reset MTU, and come up again. */
+ cp_close(dev);
dev->mtu = new_mtu;
- cp_set_rxbufsize(cp); /* set new rx buf size */
-
- rc = cp_init_rings(cp); /* realloc and restart h/w */
- cp_start_hw(cp);
-
- spin_unlock_irqrestore(&cp->lock, flags);
-
- return rc;
+ cp_set_rxbufsize(cp);
+ return cp_open(dev);
}
-#endif /* BROKEN */
static const char mii_2_8139_map[8] = {
BasicModeCtrl,
@@ -1835,9 +1822,7 @@ static const struct net_device_ops cp_netdev_ops = {
.ndo_start_xmit = cp_start_xmit,
.ndo_tx_timeout = cp_tx_timeout,
.ndo_set_features = cp_set_features,
-#ifdef BROKEN
.ndo_change_mtu = cp_change_mtu,
-#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cp_poll_controller,
--
1.7.11.7
^ permalink raw reply related
* Re: [RFC PATCH 2/2] tun: fix LSM/SELinux labeling of tun/tap devices
From: Paul Moore @ 2012-12-03 16:22 UTC (permalink / raw)
To: Jason Wang; +Cc: netdev, linux-security-module, selinux
In-Reply-To: <50BC7BCE.7000502@redhat.com>
On Monday, December 03, 2012 06:15:42 PM Jason Wang wrote:
> On 11/30/2012 06:06 AM, Paul Moore wrote:
> > This patch corrects some problems with LSM/SELinux that were introduced
> > with the multiqueue patchset. The problem stems from the fact that the
> > multiqueue work changed the relationship between the tun device and its
> > associated socket; before the socket persisted for the life of the
> > device, however after the multiqueue changes the socket only persisted
> > for the life of the userspace connection (fd open). For non-persistent
> > devices this is not an issue, but for persistent devices this can cause
> > the tun device to lose its SELinux label.
> >
> > We correct this problem by adding an opaque LSM security blob to the
> > tun device struct which allows us to have the LSM security state, e.g.
> > SELinux labeling information, persist for the lifetime of the tun
> > device.
...
> > -static int selinux_tun_dev_attach(struct sock *sk)
> > +static int selinux_tun_dev_attach(struct sock *sk, void *security)
> >
> > {
> >
> > + struct tun_security_struct *tunsec = security;
> >
> > struct sk_security_struct *sksec = sk->sk_security;
> > u32 sid = current_sid();
> > int err;
> >
> > + /* we don't currently perform any NetLabel based labeling here ...
> >
> > err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
> >
> > TUN_SOCKET__RELABELFROM, NULL);
> >
> > if (err)
> >
> > return err;
> >
> > - err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
> > + err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
> >
> > TUN_SOCKET__RELABELTO, NULL);
> >
> > if (err)
> >
> > return err;
> >
> > - sksec->sid = sid;
> > + sksec->sid = tunsec->sid;
> > + sksec->sclass = SECCLASS_TUN_SOCKET;
>
> I'm not sure whether this is correct, looks like we need to differ between
> TUNSETQUEUE and TUNSETIFF. When userspace call TUNSETIFF for persistent
> device, looks like we need change the sid of tunsec like in the past.
It may be that I'm misunderstanding TUNSETQUEUE and/or TUNSETIFF. Can you
elaborate as to why they should be different?
One thing that I think we probably should change is the relabelto/from
permissions in the function above (selinux_tun_dev_attach()); in the case
where the socket does not yet have a label, e.g. 'sksec->sid == 0', we should
probably skip the relabel permissions since we want to assign the TUN device
label regardless in this case.
--
paul moore
security and virtualization @ redhat
^ permalink raw reply
* Re: [PATCH v4 net-next] sctp: Add support to per-association statistics via a new SCTP_GET_ASSOC_STATS call
From: Vlad Yasevich @ 2012-12-03 16:54 UTC (permalink / raw)
To: Michele Baldessari
Cc: linux-sctp, Neil Horman, Thomas Graf, netdev, David S. Miller
In-Reply-To: <1354373382-15230-1-git-send-email-michele@acksyn.org>
On 12/01/2012 09:49 AM, Michele Baldessari wrote:
> The current SCTP stack is lacking a mechanism to have per association
> statistics. This is an implementation modeled after OpenSolaris'
> SCTP_GET_ASSOC_STATS.
>
> Userspace part will follow on lksctp if/when there is a general ACK on
> this.
> V4:
> - Move ipackets++ before q->immediate.func() for consistency reasons
> - Move sctp_max_rto() at the end of sctp_transport_update_rto() to avoid
> returning bogus RTO values
> - return asoc->rto_min when max_obs_rto value has not changed
>
> V3:
> - Increase ictrlchunks in sctp_assoc_bh_rcv() as well
> - Move ipackets++ to sctp_inq_push()
> - return 0 when no rto updates took place since the last call
>
> V2:
> - Implement partial retrieval of stat struct to cope for future expansion
> - Kill the rtxpackets counter as it cannot be precise anyway
> - Rename outseqtsns to outofseqtsns to make it clearer that these are out
> of sequence unexpected TSNs
> - Move asoc->ipackets++ under a lock to avoid potential miscounts
> - Fold asoc->opackets++ into the already existing asoc check
> - Kill unneeded (q->asoc) test when increasing rtxchunks
> - Do not count octrlchunks if sending failed (SCTP_XMIT_OK != 0)
> - Don't count SHUTDOWNs as SACKs
> - Move SCTP_GET_ASSOC_STATS to the private space API
> - Adjust the len check in sctp_getsockopt_assoc_stats() to allow for
> future struct growth
> - Move association statistics in their own struct
> - Update idupchunks when we send a SACK with dup TSNs
> - return min_rto in max_rto when RTO has not changed. Also return the
> transport when max_rto last changed.
>
> Signed-off: Michele Baldessari <michele@acksyn.org>
Looks good
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
-vlad
> ---
> include/net/sctp/sctp.h | 12 ++++++++
> include/net/sctp/structs.h | 36 ++++++++++++++++++++++++
> include/net/sctp/user.h | 27 ++++++++++++++++++
> net/sctp/associola.c | 10 ++++++-
> net/sctp/endpointola.c | 5 +++-
> net/sctp/inqueue.c | 2 ++
> net/sctp/output.c | 14 ++++++----
> net/sctp/outqueue.c | 12 ++++++--
> net/sctp/sm_make_chunk.c | 5 ++--
> net/sctp/sm_sideeffect.c | 1 +
> net/sctp/sm_statefuns.c | 10 +++++--
> net/sctp/socket.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++
> net/sctp/transport.c | 2 ++
> 13 files changed, 192 insertions(+), 13 deletions(-)
>
> diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
> index 9c6414f..7fdf298 100644
> --- a/include/net/sctp/sctp.h
> +++ b/include/net/sctp/sctp.h
> @@ -272,6 +272,18 @@ struct sctp_mib {
> unsigned long mibs[SCTP_MIB_MAX];
> };
>
> +/* helper function to track stats about max rto and related transport */
> +static inline void sctp_max_rto(struct sctp_association *asoc,
> + struct sctp_transport *trans)
> +{
> + if (asoc->stats.max_obs_rto < (__u64)trans->rto) {
> + asoc->stats.max_obs_rto = trans->rto;
> + memset(&asoc->stats.obs_rto_ipaddr, 0,
> + sizeof(struct sockaddr_storage));
> + memcpy(&asoc->stats.obs_rto_ipaddr, &trans->ipaddr,
> + trans->af_specific->sockaddr_len);
> + }
> +}
>
> /* Print debugging messages. */
> #if SCTP_DEBUG
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 2b2f61d..c252101 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -1312,6 +1312,40 @@ struct sctp_inithdr_host {
> __u32 initial_tsn;
> };
>
> +/* SCTP_GET_ASSOC_STATS counters */
> +struct sctp_priv_assoc_stats {
> + /* Maximum observed rto in the association during subsequent
> + * observations. Value is set to 0 if no RTO measurement took place
> + * The transport where the max_rto was observed is returned in
> + * obs_rto_ipaddr
> + */
> + struct sockaddr_storage obs_rto_ipaddr;
> + __u64 max_obs_rto;
> + /* Total In and Out SACKs received and sent */
> + __u64 isacks;
> + __u64 osacks;
> + /* Total In and Out packets received and sent */
> + __u64 opackets;
> + __u64 ipackets;
> + /* Total retransmitted chunks */
> + __u64 rtxchunks;
> + /* TSN received > next expected */
> + __u64 outofseqtsns;
> + /* Duplicate Chunks received */
> + __u64 idupchunks;
> + /* Gap Ack Blocks received */
> + __u64 gapcnt;
> + /* Unordered data chunks sent and received */
> + __u64 ouodchunks;
> + __u64 iuodchunks;
> + /* Ordered data chunks sent and received */
> + __u64 oodchunks;
> + __u64 iodchunks;
> + /* Control chunks sent and received */
> + __u64 octrlchunks;
> + __u64 ictrlchunks;
> +};
> +
> /* RFC2960
> *
> * 12. Recommended Transmission Control Block (TCB) Parameters
> @@ -1830,6 +1864,8 @@ struct sctp_association {
>
> __u8 need_ecne:1, /* Need to send an ECNE Chunk? */
> temp:1; /* Is it a temporary association? */
> +
> + struct sctp_priv_assoc_stats stats;
> };
>
>
> diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
> index 1b02d7a..9a0ae09 100644
> --- a/include/net/sctp/user.h
> +++ b/include/net/sctp/user.h
> @@ -107,6 +107,7 @@ typedef __s32 sctp_assoc_t;
> #define SCTP_GET_LOCAL_ADDRS 109 /* Get all local address. */
> #define SCTP_SOCKOPT_CONNECTX 110 /* CONNECTX requests. */
> #define SCTP_SOCKOPT_CONNECTX3 111 /* CONNECTX requests (updated) */
> +#define SCTP_GET_ASSOC_STATS 112 /* Read only */
>
> /*
> * 5.2.1 SCTP Initiation Structure (SCTP_INIT)
> @@ -719,6 +720,32 @@ struct sctp_getaddrs {
> __u8 addrs[0]; /*output, variable size*/
> };
>
> +/* A socket user request obtained via SCTP_GET_ASSOC_STATS that retrieves
> + * association stats. All stats are counts except sas_maxrto and
> + * sas_obs_rto_ipaddr. maxrto is the max observed rto + transport since
> + * the last call. Will return 0 when RTO was not update since last call
> + */
> +struct sctp_assoc_stats {
> + sctp_assoc_t sas_assoc_id; /* Input */
> + /* Transport of observed max RTO */
> + struct sockaddr_storage sas_obs_rto_ipaddr;
> + __u64 sas_maxrto; /* Maximum Observed RTO for period */
> + __u64 sas_isacks; /* SACKs received */
> + __u64 sas_osacks; /* SACKs sent */
> + __u64 sas_opackets; /* Packets sent */
> + __u64 sas_ipackets; /* Packets received */
> + __u64 sas_rtxchunks; /* Retransmitted Chunks */
> + __u64 sas_outofseqtsns;/* TSN received > next expected */
> + __u64 sas_idupchunks; /* Dups received (ordered+unordered) */
> + __u64 sas_gapcnt; /* Gap Acknowledgements Received */
> + __u64 sas_ouodchunks; /* Unordered data chunks sent */
> + __u64 sas_iuodchunks; /* Unordered data chunks received */
> + __u64 sas_oodchunks; /* Ordered data chunks sent */
> + __u64 sas_iodchunks; /* Ordered data chunks received */
> + __u64 sas_octrlchunks; /* Control chunks sent */
> + __u64 sas_ictrlchunks; /* Control chunks received */
> +};
> +
> /* These are bit fields for msghdr->msg_flags. See section 5.1. */
> /* On user space Linux, these live in <bits/socket.h> as an enum. */
> enum sctp_msg_flags {
> diff --git a/net/sctp/associola.c b/net/sctp/associola.c
> index b1ef3bc..ba3f9cc 100644
> --- a/net/sctp/associola.c
> +++ b/net/sctp/associola.c
> @@ -321,6 +321,9 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
> asoc->default_timetolive = sp->default_timetolive;
> asoc->default_rcv_context = sp->default_rcv_context;
>
> + /* SCTP_GET_ASSOC_STATS COUNTERS */
> + memset(&asoc->stats, 0, sizeof(struct sctp_priv_assoc_stats));
> +
> /* AUTH related initializations */
> INIT_LIST_HEAD(&asoc->endpoint_shared_keys);
> err = sctp_auth_asoc_copy_shkeys(ep, asoc, gfp);
> @@ -760,6 +763,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
>
> /* Set the transport's RTO.initial value */
> peer->rto = asoc->rto_initial;
> + sctp_max_rto(asoc, peer);
>
> /* Set the peer's active state. */
> peer->state = peer_state;
> @@ -1152,8 +1156,12 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
> */
> if (sctp_chunk_is_data(chunk))
> asoc->peer.last_data_from = chunk->transport;
> - else
> + else {
> SCTP_INC_STATS(net, SCTP_MIB_INCTRLCHUNKS);
> + asoc->stats.ictrlchunks++;
> + if (chunk->chunk_hdr->type == SCTP_CID_SACK)
> + asoc->stats.isacks++;
> + }
>
> if (chunk->transport)
> chunk->transport->last_time_heard = jiffies;
> diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
> index 1859e2b..32ab55b 100644
> --- a/net/sctp/endpointola.c
> +++ b/net/sctp/endpointola.c
> @@ -480,8 +480,11 @@ normal:
> */
> if (asoc && sctp_chunk_is_data(chunk))
> asoc->peer.last_data_from = chunk->transport;
> - else
> + else {
> SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS);
> + if (asoc)
> + asoc->stats.ictrlchunks++;
> + }
>
> if (chunk->transport)
> chunk->transport->last_time_heard = jiffies;
> diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
> index 397296f..2d5ad28 100644
> --- a/net/sctp/inqueue.c
> +++ b/net/sctp/inqueue.c
> @@ -104,6 +104,8 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
> * on the BH related data structures.
> */
> list_add_tail(&chunk->list, &q->in_chunk_list);
> + if (chunk->asoc)
> + chunk->asoc->stats.ipackets++;
> q->immediate.func(&q->immediate);
> }
>
> diff --git a/net/sctp/output.c b/net/sctp/output.c
> index 4e90188bf..f5200a2 100644
> --- a/net/sctp/output.c
> +++ b/net/sctp/output.c
> @@ -311,6 +311,8 @@ static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet,
>
> case SCTP_CID_SACK:
> packet->has_sack = 1;
> + if (chunk->asoc)
> + chunk->asoc->stats.osacks++;
> break;
>
> case SCTP_CID_AUTH:
> @@ -584,11 +586,13 @@ int sctp_packet_transmit(struct sctp_packet *packet)
> */
>
> /* Dump that on IP! */
> - if (asoc && asoc->peer.last_sent_to != tp) {
> - /* Considering the multiple CPU scenario, this is a
> - * "correcter" place for last_sent_to. --xguo
> - */
> - asoc->peer.last_sent_to = tp;
> + if (asoc) {
> + asoc->stats.opackets++;
> + if (asoc->peer.last_sent_to != tp)
> + /* Considering the multiple CPU scenario, this is a
> + * "correcter" place for last_sent_to. --xguo
> + */
> + asoc->peer.last_sent_to = tp;
> }
>
> if (has_data) {
> diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
> index 1b4a7f8..379c81d 100644
> --- a/net/sctp/outqueue.c
> +++ b/net/sctp/outqueue.c
> @@ -667,6 +667,7 @@ redo:
> chunk->fast_retransmit = SCTP_DONT_FRTX;
>
> q->empty = 0;
> + q->asoc->stats.rtxchunks++;
> break;
> }
>
> @@ -876,12 +877,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
> if (status != SCTP_XMIT_OK) {
> /* put the chunk back */
> list_add(&chunk->list, &q->control_chunk_list);
> - } else if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) {
> + } else {
> + asoc->stats.octrlchunks++;
> /* PR-SCTP C5) If a FORWARD TSN is sent, the
> * sender MUST assure that at least one T3-rtx
> * timer is running.
> */
> - sctp_transport_reset_timers(transport);
> + if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN)
> + sctp_transport_reset_timers(transport);
> }
> break;
>
> @@ -1055,6 +1058,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
> */
> if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING)
> chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM;
> + if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
> + asoc->stats.ouodchunks++;
> + else
> + asoc->stats.oodchunks++;
>
> break;
>
> @@ -1162,6 +1169,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
>
> sack_ctsn = ntohl(sack->cum_tsn_ack);
> gap_ack_blocks = ntohs(sack->num_gap_ack_blocks);
> + asoc->stats.gapcnt += gap_ack_blocks;
> /*
> * SFR-CACC algorithm:
> * On receipt of a SACK the sender SHOULD execute the
> diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
> index e0f01a4..e1c5fc2 100644
> --- a/net/sctp/sm_make_chunk.c
> +++ b/net/sctp/sm_make_chunk.c
> @@ -804,10 +804,11 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
> gabs);
>
> /* Add the duplicate TSN information. */
> - if (num_dup_tsns)
> + if (num_dup_tsns) {
> + aptr->stats.idupchunks += num_dup_tsns;
> sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
> sctp_tsnmap_get_dups(map));
> -
> + }
> /* Once we have a sack generated, check to see what our sack
> * generation is, if its 0, reset the transports to 0, and reset
> * the association generation to 1
> diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
> index c076956..c957775 100644
> --- a/net/sctp/sm_sideeffect.c
> +++ b/net/sctp/sm_sideeffect.c
> @@ -542,6 +542,7 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
> */
> if (!is_hb || transport->hb_sent) {
> transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
> + sctp_max_rto(asoc, transport);
> }
> }
>
> diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
> index b6adef8..ecf7a17 100644
> --- a/net/sctp/sm_statefuns.c
> +++ b/net/sctp/sm_statefuns.c
> @@ -6127,6 +6127,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
> /* The TSN is too high--silently discard the chunk and
> * count on it getting retransmitted later.
> */
> + if (chunk->asoc)
> + chunk->asoc->stats.outofseqtsns++;
> return SCTP_IERROR_HIGH_TSN;
> } else if (tmp > 0) {
> /* This is a duplicate. Record it. */
> @@ -6226,10 +6228,14 @@ static int sctp_eat_data(const struct sctp_association *asoc,
> /* Note: Some chunks may get overcounted (if we drop) or overcounted
> * if we renege and the chunk arrives again.
> */
> - if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
> + if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
> SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS);
> - else {
> + if (chunk->asoc)
> + chunk->asoc->stats.iuodchunks++;
> + } else {
> SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS);
> + if (chunk->asoc)
> + chunk->asoc->stats.iodchunks++;
> ordered = 1;
> }
>
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 2e89706..7b8d01a 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -611,6 +611,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
> 2*asoc->pathmtu, 4380));
> trans->ssthresh = asoc->peer.i.a_rwnd;
> trans->rto = asoc->rto_initial;
> + sctp_max_rto(asoc, trans);
> trans->rtt = trans->srtt = trans->rttvar = 0;
> sctp_transport_route(trans, NULL,
> sctp_sk(asoc->base.sk));
> @@ -5635,6 +5636,71 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
> return 0;
> }
>
> +/*
> + * SCTP_GET_ASSOC_STATS
> + *
> + * This option retrieves local per endpoint statistics. It is modeled
> + * after OpenSolaris' implementation
> + */
> +static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
> + char __user *optval,
> + int __user *optlen)
> +{
> + struct sctp_assoc_stats sas;
> + struct sctp_association *asoc = NULL;
> +
> + /* User must provide at least the assoc id */
> + if (len < sizeof(sctp_assoc_t))
> + return -EINVAL;
> +
> + if (copy_from_user(&sas, optval, len))
> + return -EFAULT;
> +
> + asoc = sctp_id2assoc(sk, sas.sas_assoc_id);
> + if (!asoc)
> + return -EINVAL;
> +
> + sas.sas_rtxchunks = asoc->stats.rtxchunks;
> + sas.sas_gapcnt = asoc->stats.gapcnt;
> + sas.sas_outofseqtsns = asoc->stats.outofseqtsns;
> + sas.sas_osacks = asoc->stats.osacks;
> + sas.sas_isacks = asoc->stats.isacks;
> + sas.sas_octrlchunks = asoc->stats.octrlchunks;
> + sas.sas_ictrlchunks = asoc->stats.ictrlchunks;
> + sas.sas_oodchunks = asoc->stats.oodchunks;
> + sas.sas_iodchunks = asoc->stats.iodchunks;
> + sas.sas_ouodchunks = asoc->stats.ouodchunks;
> + sas.sas_iuodchunks = asoc->stats.iuodchunks;
> + sas.sas_idupchunks = asoc->stats.idupchunks;
> + sas.sas_opackets = asoc->stats.opackets;
> + sas.sas_ipackets = asoc->stats.ipackets;
> +
> + /* New high max rto observed, will return 0 if not a single
> + * RTO update took place. obs_rto_ipaddr will be bogus
> + * in such a case
> + */
> + sas.sas_maxrto = asoc->stats.max_obs_rto;
> + memcpy(&sas.sas_obs_rto_ipaddr, &asoc->stats.obs_rto_ipaddr,
> + sizeof(struct sockaddr_storage));
> +
> + /* Mark beginning of a new observation period */
> + asoc->stats.max_obs_rto = asoc->rto_min;
> +
> + /* Allow the struct to grow and fill in as much as possible */
> + len = min_t(size_t, len, sizeof(sas));
> +
> + if (put_user(len, optlen))
> + return -EFAULT;
> +
> + SCTP_DEBUG_PRINTK("sctp_getsockopt_assoc_stat(%d): %d\n",
> + len, sas.sas_assoc_id);
> +
> + if (copy_to_user(optval, &sas, len))
> + return -EFAULT;
> +
> + return 0;
> +}
> +
> SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
> char __user *optval, int __user *optlen)
> {
> @@ -5776,6 +5842,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
> case SCTP_PEER_ADDR_THLDS:
> retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen);
> break;
> + case SCTP_GET_ASSOC_STATS:
> + retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen);
> + break;
> default:
> retval = -ENOPROTOOPT;
> break;
> diff --git a/net/sctp/transport.c b/net/sctp/transport.c
> index 953c21e..40574ad 100644
> --- a/net/sctp/transport.c
> +++ b/net/sctp/transport.c
> @@ -363,6 +363,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
> if (tp->rto > tp->asoc->rto_max)
> tp->rto = tp->asoc->rto_max;
>
> + sctp_max_rto(tp->asoc, tp);
> tp->rtt = rtt;
>
> /* Reset rto_pending so that a new RTT measurement is started when a
> @@ -620,6 +621,7 @@ void sctp_transport_reset(struct sctp_transport *t)
> t->burst_limited = 0;
> t->ssthresh = asoc->peer.i.a_rwnd;
> t->rto = asoc->rto_initial;
> + sctp_max_rto(asoc, t);
> t->rtt = 0;
> t->srtt = 0;
> t->rttvar = 0;
>
^ permalink raw reply
* Re: [PATCH 2/3] net: cpsw: verify correct number of slaves in DT
From: Mugunthan V N @ 2012-12-03 17:00 UTC (permalink / raw)
To: Jan Luebbe
Cc: netdev, David S. Miller, Vaibhav Hiremath, linux-arm-kernel,
linux-omap
In-Reply-To: <1354542569-6165-2-git-send-email-jlu@pengutronix.de>
On 12/3/2012 7:19 PM, Jan Luebbe wrote:
> Check that the number of available slaves passed from DT matches the
> value of the "slaves" property in the cpsw node. Otherwise, priv->slaves
> would be the wrong size.
>
> Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
> ---
> drivers/net/ethernet/ti/cpsw.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index c0e676a..8de3e92 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -832,6 +832,16 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> const char *phy_id = NULL;
> const void *mac_addr = NULL;
>
> + if (!of_device_is_available(slave_node))
> + continue;
> +
> + if (i >= data->slaves) {
> + dev_err(&pdev->dev, "Too many slaves in the DT (> %d).\n",
> + data->slaves);
> + ret = -EINVAL;
> + goto error_ret;
> + }
> +
> if (of_property_read_string(slave_node, "phy_id", &phy_id)) {
> dev_err(&pdev->dev, "Missing slave[%d] phy_id property.\n", i);
> ret = -EINVAL;
> @@ -861,6 +871,13 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> i++;
> }
>
> + if (i < data->slaves) {
> + dev_err(&pdev->dev, "Not enough slaves in the DT (< %d).\n",
> + data->slaves);
> + ret = -EINVAL;
> + goto error_ret;
> + }
> +
> /*
> * Populate all the child nodes here...
> */
The patches look good to me.
Acked-by: Mugunthan V N<mugunthanvnm@ti.com>
Regards
Mugunthan V N
^ permalink raw reply
* Re: [PATCH 1/3] net: cpsw: replace pr_xxx with dev_xxx functions
From: Mugunthan V N @ 2012-12-03 16:59 UTC (permalink / raw)
To: Jan Luebbe
Cc: netdev, David S. Miller, Vaibhav Hiremath, linux-arm-kernel,
linux-omap
In-Reply-To: <1354542569-6165-1-git-send-email-jlu@pengutronix.de>
On 12/3/2012 7:19 PM, Jan Luebbe wrote:
> Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
> ---
> drivers/net/ethernet/ti/cpsw.c | 47 ++++++++++++++++++++--------------------
> 1 file changed, 23 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index fb1a692..c0e676a 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -729,7 +729,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> return -EINVAL;
>
> if (of_property_read_u32(node, "slaves", &prop)) {
> - pr_err("Missing slaves property in the DT.\n");
> + dev_err(&pdev->dev, "Missing slaves property in the DT.\n");
> return -EINVAL;
> }
> data->slaves = prop;
> @@ -737,91 +737,91 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
> data->slaves, GFP_KERNEL);
> if (!data->slave_data) {
> - pr_err("Could not allocate slave memory.\n");
> + dev_err(&pdev->dev, "Could not allocate slave memory.\n");
> return -EINVAL;
> }
>
> data->no_bd_ram = of_property_read_bool(node, "no_bd_ram");
>
> if (of_property_read_u32(node, "cpdma_channels", &prop)) {
> - pr_err("Missing cpdma_channels property in the DT.\n");
> + dev_err(&pdev->dev, "Missing cpdma_channels property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->channels = prop;
>
> if (of_property_read_u32(node, "host_port_no", &prop)) {
> - pr_err("Missing host_port_no property in the DT.\n");
> + dev_err(&pdev->dev, "Missing host_port_no property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->host_port_num = prop;
>
> if (of_property_read_u32(node, "cpdma_reg_ofs", &prop)) {
> - pr_err("Missing cpdma_reg_ofs property in the DT.\n");
> + dev_err(&pdev->dev, "Missing cpdma_reg_ofs property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->cpdma_reg_ofs = prop;
>
> if (of_property_read_u32(node, "cpdma_sram_ofs", &prop)) {
> - pr_err("Missing cpdma_sram_ofs property in the DT.\n");
> + dev_err(&pdev->dev, "Missing cpdma_sram_ofs property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->cpdma_sram_ofs = prop;
>
> if (of_property_read_u32(node, "ale_reg_ofs", &prop)) {
> - pr_err("Missing ale_reg_ofs property in the DT.\n");
> + dev_err(&pdev->dev, "Missing ale_reg_ofs property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->ale_reg_ofs = prop;
>
> if (of_property_read_u32(node, "ale_entries", &prop)) {
> - pr_err("Missing ale_entries property in the DT.\n");
> + dev_err(&pdev->dev, "Missing ale_entries property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->ale_entries = prop;
>
> if (of_property_read_u32(node, "host_port_reg_ofs", &prop)) {
> - pr_err("Missing host_port_reg_ofs property in the DT.\n");
> + dev_err(&pdev->dev, "Missing host_port_reg_ofs property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->host_port_reg_ofs = prop;
>
> if (of_property_read_u32(node, "hw_stats_reg_ofs", &prop)) {
> - pr_err("Missing hw_stats_reg_ofs property in the DT.\n");
> + dev_err(&pdev->dev, "Missing hw_stats_reg_ofs property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->hw_stats_reg_ofs = prop;
>
> if (of_property_read_u32(node, "bd_ram_ofs", &prop)) {
> - pr_err("Missing bd_ram_ofs property in the DT.\n");
> + dev_err(&pdev->dev, "Missing bd_ram_ofs property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->bd_ram_ofs = prop;
>
> if (of_property_read_u32(node, "bd_ram_size", &prop)) {
> - pr_err("Missing bd_ram_size property in the DT.\n");
> + dev_err(&pdev->dev, "Missing bd_ram_size property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->bd_ram_size = prop;
>
> if (of_property_read_u32(node, "rx_descs", &prop)) {
> - pr_err("Missing rx_descs property in the DT.\n");
> + dev_err(&pdev->dev, "Missing rx_descs property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> data->rx_descs = prop;
>
> if (of_property_read_u32(node, "mac_control", &prop)) {
> - pr_err("Missing mac_control property in the DT.\n");
> + dev_err(&pdev->dev, "Missing mac_control property in the DT.\n");
> ret = -EINVAL;
> goto error_ret;
> }
> @@ -833,14 +833,14 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> const void *mac_addr = NULL;
>
> if (of_property_read_string(slave_node, "phy_id", &phy_id)) {
> - pr_err("Missing slave[%d] phy_id property\n", i);
> + dev_err(&pdev->dev, "Missing slave[%d] phy_id property.\n", i);
> ret = -EINVAL;
> goto error_ret;
> }
> slave_data->phy_id = phy_id;
>
> if (of_property_read_u32(slave_node, "slave_reg_ofs", &prop)) {
> - pr_err("Missing slave[%d] slave_reg_ofs property\n", i);
> + dev_err(&pdev->dev, "Missing slave[%d] slave_reg_ofs property.\n", i);
> ret = -EINVAL;
> goto error_ret;
> }
> @@ -848,8 +848,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
>
> if (of_property_read_u32(slave_node, "sliver_reg_ofs",
> &prop)) {
> - pr_err("Missing slave[%d] sliver_reg_ofs property\n",
> - i);
> + dev_err(&pdev->dev, "Missing slave[%d] sliver_reg_ofs property.\n", i);
> ret = -EINVAL;
> goto error_ret;
> }
> @@ -868,7 +867,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
> ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
> /* We do not want to force this, as in some cases may not have child */
> if (ret)
> - pr_warn("Doesn't have any child node\n");
> + dev_warn(&pdev->dev, "Doesn't have any child node\n");
>
> return 0;
>
> @@ -890,7 +889,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
>
> ndev = alloc_etherdev(sizeof(struct cpsw_priv));
> if (!ndev) {
> - pr_err("error allocating net_device\n");
> + pr_err("cpsw: error allocating net_device\n");
> return -ENOMEM;
> }
>
> @@ -909,7 +908,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
> pm_runtime_enable(&pdev->dev);
>
> if (cpsw_probe_dt(&priv->data, pdev)) {
> - pr_err("cpsw: platform data missing\n");
> + dev_err(&pdev->dev, "platform data missing\n");
> ret = -ENODEV;
> goto clean_ndev_ret;
> }
> @@ -917,10 +916,10 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
>
> if (is_valid_ether_addr(data->slave_data[0].mac_addr)) {
> memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN);
> - pr_info("Detected MACID = %pM", priv->mac_addr);
> + dev_info(&pdev->dev, "Detected MACID = %pM", priv->mac_addr);
> } else {
> eth_random_addr(priv->mac_addr);
> - pr_info("Random MACID = %pM", priv->mac_addr);
> + dev_info(&pdev->dev, "Random MACID = %pM", priv->mac_addr);
> }
>
> memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
> @@ -1120,7 +1119,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
> struct net_device *ndev = platform_get_drvdata(pdev);
> struct cpsw_priv *priv = netdev_priv(ndev);
>
> - pr_info("removing device");
> + dev_info(&pdev->dev, "removing device");
> platform_set_drvdata(pdev, NULL);
>
> free_irq(ndev->irq, priv);
The patches look good to me.
Acked-by: Mugunthan V N<mugunthanvnm@ti.com>
^ permalink raw reply
* Re: [PATCH 3/3] net: cpsw: implement ioctl for MII
From: Mugunthan V N @ 2012-12-03 17:04 UTC (permalink / raw)
To: Jan Luebbe
Cc: netdev, David S. Miller, Vaibhav Hiremath, linux-arm-kernel,
linux-omap
In-Reply-To: <1354542569-6165-3-git-send-email-jlu@pengutronix.de>
On 12/3/2012 7:19 PM, Jan Luebbe wrote:
> This allows using tools like mii-diag on CPSW.
>
> Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
> ---
> drivers/net/ethernet/ti/cpsw.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index 8de3e92..f476c03 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -629,6 +629,20 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)
> dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n");
> }
>
> +static int cpsw_ndo_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
> +{
> + struct cpsw_priv *priv = netdev_priv(ndev);
> + struct phy_device *phy = priv->slaves[0].phy;
> +
> + if (!netif_running(ndev))
> + return -EINVAL;
> +
> + if (!phy)
> + return -ENODEV;
> +
> + return phy_mii_ioctl(phy, rq, cmd);
> +}
> +
> static void cpsw_ndo_tx_timeout(struct net_device *ndev)
> {
> struct cpsw_priv *priv = netdev_priv(ndev);
> @@ -670,6 +684,7 @@ static const struct net_device_ops cpsw_netdev_ops = {
> .ndo_start_xmit = cpsw_ndo_start_xmit,
> .ndo_change_rx_flags = cpsw_ndo_change_rx_flags,
> .ndo_validate_addr = eth_validate_addr,
> + .ndo_do_ioctl = cpsw_ndo_do_ioctl,
> .ndo_change_mtu = eth_change_mtu,
> .ndo_tx_timeout = cpsw_ndo_tx_timeout,
> .ndo_get_stats = cpsw_ndo_get_stats,
Already ndo_do_ioctl is already implemented. Can you rebase the patch
with latest git repo
and resubmit the patch
Regards
Mugunthan V N
^ permalink raw reply
* Re: [net-next PATCH V2 5/9] net: frag, per CPU resource, mem limit and LRU list accounting
From: David Miller @ 2012-12-03 17:25 UTC (permalink / raw)
To: brouer
Cc: eric.dumazet, fw, netdev, pablo, tgraf, amwang, kaber, paulmck,
herbert
In-Reply-To: <1354543361.20888.10.camel@localhost>
From: Jesper Dangaard Brouer <brouer@redhat.com>
Date: Mon, 03 Dec 2012 15:02:41 +0100
> On Thu, 2012-11-29 at 09:06 -0800, Eric Dumazet wrote:
>> On Thu, 2012-11-29 at 17:13 +0100, Jesper Dangaard Brouer wrote:
>> > The major performance bottleneck on NUMA systems, is the mem limit
>> > counter which is based an atomic counter. This patch removes the
>> > cache-bouncing of the atomic counter, by moving this accounting to be
>> > bound to each CPU. The LRU list also need to be done per CPU,
>> > in-order to keep the accounting straight.
>> >
>> > If fragments belonging together is "sprayed" across CPUs, performance
>> > will still suffer, but due to NIC rxhashing this is not very common.
>> > Correct accounting in this situation is maintained by recording and
>> > "assigning" a CPU to a frag queue when its allocated (caused by the
>> > first packet associated packet).
>> >
> [...]
>> > +/* Need to maintain these resource limits per CPU, else we will kill
>> > + * performance due to cache-line bouncing
>> > + */
>> > +struct frag_cpu_limit {
>> > + atomic_t mem;
>> > + struct list_head lru_list;
>> > + spinlock_t lru_lock;
>> > +} ____cacheline_aligned_in_smp;
>> > +
>>
>> This looks like a big patch introducing a specific infrastructure, while
>> we already have lib/percpu_counter.c
>
> For the record, I cannot use the lib/percpu_counter, because this
> accounting is not kept strictly per CPU, if the fragments are "sprayed"
> across CPUs (as described in the commit message above).
The percpu infrastructure allows precise counts and comparisons even
in that case. It uses the cheap test when possible, and defers to a
more expensive test when necessary.
^ permalink raw reply
* Re: [PATCH net-next 3/7] ipv6: improve ipv6_find_hdr() to skip empty routing headers
From: Jesse Gross @ 2012-12-03 17:28 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA,
David Miller, Ansis Atteka
In-Reply-To: <20121203140458.GA1596@1984>
On Mon, Dec 3, 2012 at 6:04 AM, Pablo Neira Ayuso <pablo-Cap9r6Oaw4JrovVCs/uTlw@public.gmane.org> wrote:
> On Thu, Nov 29, 2012 at 10:35:45AM -0800, Jesse Gross wrote:
>> @@ -159,9 +162,10 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
>> }
>> len = skb->len - start;
>>
>> - while (nexthdr != target) {
>
> If the offset is set as parameter via ipv6_find_hdr, we now are always
> entering the loop even if we found the target header we're looking
> for, before that didn't happen.
>
> Something seems wrong here to me.
If the target header is a routing header then you might still need to
continue searching because the first one that you see could be empty.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox