* Re: [PATCH] ServerEngines, benet: Avoid potential null deref in be_cmd_get_seeprom_data()
From: Ajit Khaparde @ 2011-02-05 3:18 UTC (permalink / raw)
To: netdev, jj; +Cc: linux-kernel
> From: Jesper Juhl [jj@chaosbits.net]
> ent: Thursday, February 03, 2011 3:27 PM
> To: netdev@vger.kernel.org
> Cc: linux-drivers; linux-kernel@vger.kernel.org; Khaparde, Ajit; Bandi, Sarveshwar; Seetharaman, Subramanian; Perla, Sathya
> Subject: [PATCH] ServerEngines, benet: Avoid potential null deref in be_cmd_get_seeprom_data()
> wrb_from_mccq() may return null, so we may crash on a null deref in
> be_cmd_get_seeprom_data().
> This avoids that potential crash.
> Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Thanks Jesper.
But because we have acquired a lock, we need to release it.
I would suggest considering the following patch.
---
[PATCH] ServerEngines, benet: Avoid potential null deref in be_cmd_get_seeprom_data()
Found by: Jesper Juhl <jj@chaosbits.net>
Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
---
drivers/net/benet/be_cmds.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 0c7811f..a179cc6 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1786,6 +1786,10 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter,
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
+ if (!wrb) {
+ status = -EBUSY;
+ goto err;
+ }
req = nonemb_cmd->va;
sge = nonembedded_sgl(wrb);
@@ -1801,6 +1805,7 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter,
status = be_mcc_notify_wait(adapter);
+err:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] tcp: Increase the initial congestion window to 10.
From: Jerry Chu @ 2011-02-05 3:39 UTC (permalink / raw)
To: Ilpo Järvinen; +Cc: David Miller, Netdev, therbert
In-Reply-To: <alpine.DEB.2.00.1102042126440.28937@melkinpaasi.cs.helsinki.fi>
On Fri, Feb 4, 2011 at 11:43 AM, Ilpo Järvinen
<ilpo.jarvinen@helsinki.fi> wrote:
>
> On Thu, 3 Feb 2011, H.K. Jerry Chu wrote:
>
> > On Thu, Feb 3, 2011 at 2:43 PM, Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> wrote:
> > > It would perhaps be useful to change receiver advertized window to include
> > > some extra segs initially. It should be >= IW + peer's dupThresh-1 as
> > > otherwise limited transmit won't work for the initial window because we
> > > won't open more receiver window with dupacks (IIRC, I suppose Jerry might
> > > be able to correct me right away if I'm wrong and we open window with
> > > dupacks too?).
> >
> > Sorry I don't know how the receive window is updated in Linux,
> > autotuning or not.
> > But I just wonder why would it have to do with dupacks, i.e., why would
> > it not slide forward as long as the left edge of the window slides
> > forward, regardless of OOO pkt arrival?
>
> ?? DupACK by defination does not slide the left edge?!? :-) ...It
> certainly makes a difference whether the ACK is cumulative or not.
> Anyway, I tcpdumped it now and confirmed that advertized window is not
> advanced if OOO packet arrives.
Cwnd discounts packets that have left the network but rwnd won't discharge
packets until they are consumed by ULP so you are right that in case
the packets from or near the head of the retransmission queue get
dropped rwnd won't
open up room for more packets even though cwnd will. To cover that case initrwnd
needs to be larger than initcwnd.
Jerry
>
> > I am of the opinion that rwnd is for flow control purpose only thus should be
> > fully decoupled from the cwnd of the other (sender) side. Therefore
> > initrwnd should
> > normally be based on projected BDP and local memory pressure, e.g., 64KB, not
> > bearing any relation with IW of the other side. Only under special
> > circumstances should it be used to constrain the sender, e.g., for
> > devices behind slow links with
> > very small buffer.
>
> I also think along the lines that the advertized window autotuning code
> is just unnecessarily preventive (besides the IW change, also Quickstart
> couldn't be used that efficiently because of it).
>
> --
> i.
^ permalink raw reply
* Re: [PATCH v5] Gemini: Gigabit ethernet driver
From: Michał Mirosław @ 2011-02-05 13:19 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: David Miller
In-Reply-To: <20110202171814.GA10458@rere.qmqm.pl>
On Wed, Feb 02, 2011 at 06:18:14PM +0100, Michał Mirosław wrote:
> If I make it buildable (NOT working) on other archs is it enough I add
> Kconfig dependency on (ARCH_GEMINI || BROKEN) to allow it to be
> build-tested there?
Hmm. CONFIG_BROKEN is not easily selectable anymore, so it's unlikely
that many people will even know about it. What's the correct way to
make a driver be built but not installed by default? I can use:
default m if ARCH_GEMINI
default n
But that will make it get installed on x86 allmodconfig even if it
won't ever work there - so will pollute modules for other arches
unless distribution managers remember that not every driver built
needs to be included.
Best Regards,
Michał Mirosław
^ permalink raw reply
* Re: [PATCH] tcp: Increase the initial congestion window to 10.
From: Gerrit Renker @ 2011-02-05 13:57 UTC (permalink / raw)
To: David Miller; +Cc: netdev, dccp, therbert
In-Reply-To: <20110202.170750.229739784.davem@davemloft.net>
| I've left the DCCP code to keep using RFC3390 logic, if they
| wish to adopt this change in their code they can do so by
| simply deleting the rfc33390_bytes_to_packets() function and
| using TCP_INIT_CWND in their assignment.
|
| include/net/tcp.h | 12 +++---------
| net/dccp/ccids/ccid2.c | 9 +++++++++
Thank you for keeping the compatility, this seems an excellent way forward.
The change only affects CCID-2, TCP-like congestion control. This still has
some unresolved issues (related to cwnd) in its implementation.
Once these have been resolved, we can return to tracking the state of the
art in TCP, for the moment your patch works best.
^ permalink raw reply
* Re: [PATCH] tcp: Increase the initial congestion window to 10.
From: Gerrit Renker @ 2011-02-05 13:58 UTC (permalink / raw)
To: Leandro Melo de Sales; +Cc: netdev, dccp
In-Reply-To: <AANLkTimuYxHd5AtGSB2+wg2JE7LEKPjGssoQZuOWYrw-@mail.gmail.com>
Leandro,
| > include/net/tcp.h | 12 +++---------
| > net/dccp/ccids/ccid2.c | 9 +++++++++
|
David's change only affects CCID-2, CCID-3/4 remain unaffected,
they use rfc3390_initial_rate() (which does almost the same).
| I don't think this change will make sense for DCCP, once IW10 is
| for the cases of short-lived flows. DCCP is used on scenarios for
| multimedia flows, which are, in general, long-lived flows. So, IMO the
| way how we calculate IW for DCCP is appropriate, at least considering
| a quick answer.
I agree with you, and also vote to eventually bring CCID-2 on a par with
the state of art in TCP. Before we can do this, the CCID-2 implementation
needs some work (as per separate thread with Samuel Jero).
| In fact, nowadays we need better congestion control algorithms for DCCP,
| and in this sense we are working on adapt TCP Cubic for DCCP as a CCID,
| and also we started some work to make DCCP support TCP pluggable
| mechanism , which will allow us to use TCP congestion control
| algorithms in DCCP.
This is very good news and am very much looking forward to the new approach.
| DCCP should calculate its IW as specified in RFC3390 rather than set
| it to IW10. For the moment, I understand that for DCCP, we have to
| discuss more about this in a separated thread.
Agree that we should keep an eye on this - perhaps too early to turn it into a
should. Networking speeds are growing, and many of the simulations were based
on TCP Reno which stems from the 10 Mbit ethernet era.
^ permalink raw reply
* Re: [PATCH 0/5] net: sysctl: share ipv4/ipv6 sysctl tables
From: Alexey Dobriyan @ 2011-02-05 14:26 UTC (permalink / raw)
To: Lucian Adrian Grijincu
Cc: linux-kernel, netdev, Eric W. Biederman, Eric Dumazet,
David S. Miller, Octavian Purdila
In-Reply-To: <AANLkTik=a3NmibvYM6NxvqCiSiaE0oUFNtRaqn4+g_+D@mail.gmail.com>
On Fri, Feb 04, 2011 at 05:59:24PM +0200, Lucian Adrian Grijincu wrote:
> On Fri, Feb 4, 2011 at 12:49 PM, Alexey Dobriyan <adobriyan@gmail.com> wrote:
> >> Finally share the leaf sysctl tables for ipv4/ipv6:
> >>
> >> [PATCH 4/5] ipv4: share sysctl net/ipv4/conf/DEVNAME/ tables
> >> [PATCH 5/5] ipv6: share sysctl net/ipv6/conf/DEVNAME/ tables
> >
> > Meh.
> >
> > First you remove ->parent, then heroically pass "struct file *"
> > to sysctl handlers which duplicates all information already passed
> > and brings dcache into picture.
> >
> > Binary sysctl rewrite confused you into thinking that d_name.name
> > is the way, but it isn't.
> > For binary sysctl(2) you wouldn't get d_name.name.
>
>
> Are you really sure?
>
> I ran this code on a machine with and without these patches. It seems
> to work fine.
>
> It reads the value from /proc/sys/net/ipv4/conf/default/tag and writes 42 back.
>
> I'm not sure what I have to do to pass the name of a device (e.g.
> "eth0") instead of "default" but at least "default" and "all" work and
> have valid dentries.
You do ->parent->procname.
But, but you removed parent.
^ permalink raw reply
* Re: [PATCH 0/5] net: sysctl: share ipv4/ipv6 sysctl tables
From: Lucian Adrian Grijincu @ 2011-02-05 14:59 UTC (permalink / raw)
To: Alexey Dobriyan
Cc: linux-kernel, netdev, Eric W. Biederman, Eric Dumazet,
David S. Miller, Octavian Purdila
In-Reply-To: <20110205142648.GA9814@p183.telecom.by>
On Sat, Feb 5, 2011 at 4:26 PM, Alexey Dobriyan <adobriyan@gmail.com> wrote:
>> I'm not sure what I have to do to pass the name of a device (e.g.
>> "eth0") instead of "default" but at least "default" and "all" work and
>> have valid dentries.
>
> You do ->parent->procname.
>
> But, but you removed parent.
To be more exact I do:
const char *dev_name = filp->f_path.dentry->d_parent->d_name.name;
If the sysctl table is shared between all network devices, the last
registered node will set the ->parent.
So accessing /proc/sys/net/ipv4/conf/$DEVNAME/$CTL will access $CTL
for the last network device registered not for $DEVNAME.
--
.
..: Lucian
^ permalink raw reply
* Re: 2.6.37 regression: adding main interface to a bridge breaks vlan interface RX
From: chriss @ 2011-02-05 15:34 UTC (permalink / raw)
To: netdev
In-Reply-To: <201101241625.45367.maciej.rutecki@gmail.com>
Maciej Rutecki <maciej.rutecki <at> gmail.com> writes:
>
> On niedziela, 23 stycznia 2011 o 22:29:02 Jesse Gross wrote:
> > On Sun, Jan 23, 2011 at 9:45 AM, Maciej Rutecki
> >
> > <maciej.rutecki <at> gmail.com> wrote:
> > > I created a Bugzilla entry at
> > > https://bugzilla.kernel.org/show_bug.cgi?id=27432
> > > for your bug report, please add your address to the CC list in there,
> > > thanks!
> >
> > This isn't a bug - the change resolved behavior that varied depending
> > on what NIC was in use.
>
> Thanks for the update. Closing.
>
> Regards
Hi
How am i supposed to put my eth to a bridge and have a seprate vlan besides that
bridge?
regards
^ permalink raw reply
* Re: [net-2.6 PATCH 1/3] net: dcb: match dcb_app protocol field with 802.1Qaz spec
From: John Fastabend @ 2011-02-05 19:39 UTC (permalink / raw)
To: David Miller; +Cc: netdev@vger.kernel.org
In-Reply-To: <20110131.204104.226756946.davem@davemloft.net>
On 1/31/2011 8:41 PM, David Miller wrote:
> From: John Fastabend <john.r.fastabend@intel.com>
> Date: Mon, 31 Jan 2011 14:00:49 -0800
>
>> The dcb_app protocol field is a __u32 however the 802.1Qaz
>> specification defines it as a 16 bit field. This patch brings
>> the structure inline with the spec making it a __u16.
>>
>> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
> ...
>> @@ -101,7 +101,7 @@ struct ieee_pfc {
>> */
>> struct dcb_app {
>> __u8 selector;
>> - __u32 protocol;
>> + __u16 protocol;
>> __u8 priority;
>> };
>>
>
> If we're going to do this, please fix this wasteful structure
> layout. Put the "protocol" either first, or last, so that the
> structure size is 4 bytes, rather than something like 8.
OK I will fix this. Thanks
^ permalink raw reply
* Re: [net-2.6 PATCH 2/3] net: dcb: use _safe() version of list iterators
From: John Fastabend @ 2011-02-05 19:40 UTC (permalink / raw)
To: David Miller; +Cc: netdev@vger.kernel.org
In-Reply-To: <20110131.204214.71133534.davem@davemloft.net>
On 1/31/2011 8:42 PM, David Miller wrote:
> From: John Fastabend <john.r.fastabend@intel.com>
> Date: Mon, 31 Jan 2011 14:00:54 -0800
>
>> Use _safe() version of list iterator macros in dcb_setapp().
>>
>> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
>
> Why? It's unnecessary overhead, since we always branch to "out", and
> therefore out of the list traversal loop, any time we list_del()
> something on the list.
Of course you are right there is no reason for this. Thanks.
^ permalink raw reply
* [PATCH] sis900: Fix mem leak in sis900_rx error path
From: Jesper Juhl @ 2011-02-05 20:41 UTC (permalink / raw)
To: Daniele Venzano; +Cc: netdev, linux-kernel
Fix memory leak in error path of sis900_rx(). If we don't do this we'll
leak the skb we dev_alloc_skb()'ed just a few lines above when the
variable goes out of scope.
Signed-off-by: Jesper Juhl <jj@chaosbits.net>
---
sis900.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 5976d1d..640e368 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1777,6 +1777,7 @@ static int sis900_rx(struct net_device *net_dev)
"cur_rx:%4.4d, dirty_rx:%4.4d\n",
net_dev->name, sis_priv->cur_rx,
sis_priv->dirty_rx);
+ dev_kfree_skb(skb);
break;
}
--
Jesper Juhl <jj@chaosbits.net> http://www.chaosbits.net/
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please.
^ permalink raw reply related
* Re: [PATCH 4/5] ipv4: share sysctl net/ipv4/conf/DEVNAME/ tables
From: Eric W. Biederman @ 2011-02-05 21:16 UTC (permalink / raw)
To: Lucian Adrian Grijincu
Cc: linux-kernel, netdev, Eric Dumazet, David S. Miller,
Octavian Purdila
In-Reply-To: <cf6a4b19f6b0264f58367afb659586efb84d2a69.1296793770.git.lucian.grijincu@gmail.com>
Lucian Adrian Grijincu <lucian.grijincu@gmail.com> writes:
> Before this, for each network device DEVNAME that supports ipv4 a new
> sysctl table was registered in $PROC/sys/net/ipv4/conf/DEVNAME/.
>
> The sysctl table was identical for all network devices, except for:
> * data: pointer to the data to be accessed in the sysctl
> * extra1: the 'struct ipv4_devconf*' of the network device
> * extra2: the 'struct net*' of the network namespace
>
> Assuming we have a device name and a 'struct net*', we can get the
> 'struct net_device*'. From there we can compute:
> * data: each entry corresponds to a position in 'struct ipv4_devconf*'
> * extra1: 'struct ipv4_devconf*' can be reached from 'struct net_device*'
> * extra2: the 'struct net*' that we assumed to have
>
> The device name is determined from the path to the file (the name of
> the parent dentry).
>
> The 'struct net*' is stored in the parent 'struct ctl_table*' path by
> register_net_sysctl_table_pathdata().
I don't like this direction. This makes the code more complicated and
probably racy (think what happens when you are running this sysctl when
someone is renaming the network device) for a questionable gain in space
efficiency.
Size of the sysctl data structures is interesting especially when we
have a lot of instances of this data structure but so is algorithmic
complexity. The ugly problem is right now inserts of N network devices
is O(N^2) where it could/should be O(Nlog(N)).
I think these last three patches increase reliance on slightly dubious
properties of the sysctl interface and are likely to make it hard to fix
the O(N^2) complexity that increases rtnl_lock hold times and is
otherwise a real pain when adding and deleting network devices.
Eric
> Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
> ---
> fs/proc/proc_sysctl.c | 16 +++-
> include/linux/inetdevice.h | 12 +++-
> net/ipv4/devinet.c | 203 +++++++++++++++++++++++++++++---------------
> 3 files changed, 161 insertions(+), 70 deletions(-)
>
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index fb707e0..fe392f1 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -128,6 +128,11 @@ out:
> return err;
> }
>
> +
> +typedef int proc_handler_extended(struct ctl_table *ctl, int write,
> + void __user *buffer, size_t *lenp, loff_t *ppos,
> + struct file *filp);
> +
> static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
> size_t count, loff_t *ppos, int write)
> {
> @@ -136,6 +141,7 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
> struct ctl_table *table = PROC_I(inode)->sysctl_entry;
> ssize_t error;
> size_t res;
> + proc_handler_extended *phx = (proc_handler_extended *) table->proc_handler;
>
> if (IS_ERR(head))
> return PTR_ERR(head);
> @@ -155,7 +161,15 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
>
> /* careful: calling conventions are nasty here */
> res = count;
> - error = table->proc_handler(table, write, buf, &res, ppos);
> + /* Most handlers only use the first 5 arguments (without @filp).
> + * Changing all is too much of work, as, at the time of writting only
> + * the devinet.c proc_handlers know about and use the @filp.
> + *
> + * This is just a HACK for now, I did this this way to not
> + * waste time changing all the handlers, in the final version
> + * I'll change all the handlers if there's not other solution.
> + */
> + error = phx(table, write, buf, &res, ppos, filp);
> if (!error)
> error = res;
> out:
> diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
> index ae8fdc5..caf06b3 100644
> --- a/include/linux/inetdevice.h
> +++ b/include/linux/inetdevice.h
> @@ -43,8 +43,18 @@ enum
>
> #define IPV4_DEVCONF_MAX (__IPV4_DEVCONF_MAX - 1)
>
> +
> +struct devinet_sysctl {
> + /* dev_name holds a copy of dev_name, because '.procname' is
> + * regarded as const by sysctl and we wouldn't want anyone to
> + * change it under our feet (see SIOCSIFNAME). */
> + char *dev_name;
> + struct ctl_table_header *sysctl_header;
> +};
> +
> +
> struct ipv4_devconf {
> - void *sysctl;
> + struct devinet_sysctl devinet_sysctl;
> int data[IPV4_DEVCONF_MAX];
> DECLARE_BITMAP(state, IPV4_DEVCONF_MAX);
> };
> diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
> index 748cb5b..774d347 100644
> --- a/net/ipv4/devinet.c
> +++ b/net/ipv4/devinet.c
> @@ -147,7 +147,7 @@ void in_dev_finish_destroy(struct in_device *idev)
> }
> EXPORT_SYMBOL(in_dev_finish_destroy);
>
> -static struct in_device *inetdev_init(struct net_device *dev)
> +struct in_device *inetdev_init(struct net_device *dev)
> {
> struct in_device *in_dev;
>
> @@ -158,7 +158,8 @@ static struct in_device *inetdev_init(struct net_device *dev)
> goto out;
> memcpy(&in_dev->cnf, dev_net(dev)->ipv4.devconf_dflt,
> sizeof(in_dev->cnf));
> - in_dev->cnf.sysctl = NULL;
> + in_dev->cnf.devinet_sysctl.dev_name = NULL;
> + in_dev->cnf.devinet_sysctl.sysctl_header = NULL;
> in_dev->dev = dev;
> in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl);
> if (!in_dev->arp_parms)
> @@ -1375,6 +1376,67 @@ static void inet_forward_change(struct net *net)
> }
> }
>
> +
> +
> +static int devinet_conf_handler(ctl_table *ctl, int write,
> + void __user *buffer,
> + size_t *lenp, loff_t *ppos,
> + struct file *filp,
> + proc_handler *proc_handler)
> +{
> + /* The path to this file is of the form:
> + * $PROC_MOUNT/sys/net/ipv4/conf/$DEVNAME/$CTL
> + *
> + * The array of 'struct ctl_table' of devinet entries is
> + * shared between all ipv4 network devices and the 'data'
> + * field of each structure only hold the offset into the
> + * 'data' field of 'struct ipv4_devconf'.
> + *
> + * To find the propper location of the data that must be
> + * accessed by this handler we need the device name and the
> + * network namespace in which it belongs.
> + */
> +
> + /* We store the network namespace in the parent table's ->extra2 */
> + struct inode *parent_inode = filp->f_path.dentry->d_parent->d_inode;
> + struct ctl_table *parent_table = PROC_I(parent_inode)->sysctl_entry;
> + struct net *net = parent_table->extra2;
> +
> + const char *dev_name = filp->f_path.dentry->d_parent->d_name.name;
> + struct ctl_table tmp_ctl;
> + struct net_device *dev = NULL;
> + struct in_device *in_dev = NULL;
> + struct ipv4_devconf *cnf;
> + int ret;
> +
> + if (strcmp(dev_name, "all") == 0) {
> + cnf = net->ipv4.devconf_all;
> + } else if (strcmp(dev_name, "default") == 0) {
> + cnf = net->ipv4.devconf_dflt;
> + } else {
> + /* the device could have been renamed (SIOCSIFADDR) or
> + * deleted since we started accessing it's proc sysctl */
> + dev = dev_get_by_name(net, dev_name);
> + if (dev == NULL)
> + return -ENOENT;
> + in_dev = in_dev_get(dev);
> + cnf = &in_dev->cnf;
> + }
> +
> + tmp_ctl = *ctl;
> + tmp_ctl.data += (char *)cnf - (char *)&ipv4_devconf;
> + tmp_ctl.extra1 = cnf;
> + tmp_ctl.extra2 = net;
> +
> + ret = proc_handler(&tmp_ctl, write, buffer, lenp, ppos);
> +
> + if (in_dev)
> + in_dev_put(in_dev);
> + if (dev)
> + dev_put(dev);
> + return ret;
> +}
> +
> static int devinet_conf_proc(ctl_table *ctl, int write,
> void __user *buffer,
> size_t *lenp, loff_t *ppos)
> @@ -1445,6 +1507,33 @@ static int ipv4_doint_and_flush(ctl_table *ctl, int write,
> return ret;
> }
>
> +static int devinet_conf_proc__(ctl_table *ctl, int write,
> + void __user *buffer,
> + size_t *lenp, loff_t *ppos,
> + struct file *filp)
> +{
> + return devinet_conf_handler(ctl, write, buffer, lenp, ppos, filp,
> + devinet_conf_proc);
> +}
> +
> +static int devinet_sysctl_forward__(ctl_table *ctl, int write,
> + void __user *buffer,
> + size_t *lenp, loff_t *ppos,
> + struct file *filp)
> +{
> + return devinet_conf_handler(ctl, write, buffer, lenp, ppos, filp,
> + devinet_sysctl_forward);
> +}
> +
> +static int ipv4_doint_and_flush__(ctl_table *ctl, int write,
> + void __user *buffer,
> + size_t *lenp, loff_t *ppos,
> + struct file *filp)
> +{
> + return devinet_conf_handler(ctl, write, buffer, lenp, ppos, filp,
> + ipv4_doint_and_flush);
> +}
> +
> #define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc) \
> { \
> .procname = name, \
> @@ -1452,67 +1541,60 @@ static int ipv4_doint_and_flush(ctl_table *ctl, int write,
> IPV4_DEVCONF_ ## attr - 1, \
> .maxlen = sizeof(int), \
> .mode = mval, \
> - .proc_handler = proc, \
> - .extra1 = &ipv4_devconf, \
> + .proc_handler = (proc_handler *) proc, \
> }
>
> #define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
> - DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc)
> + DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc__)
>
> #define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
> - DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc)
> + DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc__)
>
> #define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc) \
> DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc)
>
> #define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \
> - DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush)
> -
> -static struct devinet_sysctl_table {
> - struct ctl_table_header *sysctl_header;
> - struct ctl_table devinet_vars[__IPV4_DEVCONF_MAX];
> - char *dev_name;
> -} devinet_sysctl = {
> - .devinet_vars = {
> - DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
> - devinet_sysctl_forward),
> - DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
> -
> - DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
> - DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
> - DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"),
> - DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"),
> - DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
> - DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
> - "accept_source_route"),
> - DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"),
> - DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"),
> - DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
> - DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
> - DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
> - DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
> - DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
> - DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
> - DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
> - DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
> - DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
> - DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"),
> - DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP_PVLAN, "proxy_arp_pvlan"),
> -
> - DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
> - DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
> - DEVINET_SYSCTL_FLUSHING_ENTRY(FORCE_IGMP_VERSION,
> - "force_igmp_version"),
> - DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
> - "promote_secondaries"),
> - },
> + DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush__)
> +
> +const struct ctl_table ipv4_devinet_sysctl_table[__IPV4_DEVCONF_MAX] = {
> + DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
> + devinet_sysctl_forward__),
> + DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
> +
> + DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
> + DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
> + DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"),
> + DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"),
> + DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
> + DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
> + "accept_source_route"),
> + DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"),
> + DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"),
> + DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
> + DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
> + DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
> + DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
> + DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
> + DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
> + DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
> + DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
> + DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
> + DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"),
> + DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP_PVLAN, "proxy_arp_pvlan"),
> +
> + DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
> + DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
> + DEVINET_SYSCTL_FLUSHING_ENTRY(FORCE_IGMP_VERSION,
> + "force_igmp_version"),
> + DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
> + "promote_secondaries"),
> + { }
> };
>
> static int __devinet_sysctl_register(struct net *net, char *dev_name,
> - struct ipv4_devconf *p)
> + struct ipv4_devconf *cnf)
> {
> - int i;
> - struct devinet_sysctl_table *t;
> + struct devinet_sysctl *t = &cnf->devinet_sysctl;
>
> #define DEVINET_CTL_PATH_DEV 3
>
> @@ -1524,16 +1606,6 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
> { },
> };
>
> - t = kmemdup(&devinet_sysctl, sizeof(*t), GFP_KERNEL);
> - if (!t)
> - goto out;
> -
> - for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
> - t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
> - t->devinet_vars[i].extra1 = p;
> - t->devinet_vars[i].extra2 = net;
> - }
> -
> /*
> * Make a copy of dev_name, because '.procname' is regarded as const
> * by sysctl and we wouldn't want anyone to change it under our feet
> @@ -1541,37 +1613,32 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
> */
> t->dev_name = kstrdup(dev_name, GFP_KERNEL);
> if (!t->dev_name)
> - goto free;
> + goto out;
>
> devinet_ctl_path[DEVINET_CTL_PATH_DEV].procname = t->dev_name;
>
> - t->sysctl_header = register_net_sysctl_table(net, devinet_ctl_path,
> - t->devinet_vars);
> + t->sysctl_header = register_net_sysctl_table_pathdata(net,
> + devinet_ctl_path, ipv4_devinet_sysctl_table, net);
> if (!t->sysctl_header)
> goto free_procname;
>
> - p->sysctl = t;
> return 0;
>
> free_procname:
> kfree(t->dev_name);
> -free:
> - kfree(t);
> out:
> return -ENOBUFS;
> }
>
> static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf)
> {
> - struct devinet_sysctl_table *t = cnf->sysctl;
> + struct devinet_sysctl *t = &cnf->devinet_sysctl;
>
> if (t == NULL)
> return;
>
> - cnf->sysctl = NULL;
> unregister_sysctl_table(t->sysctl_header);
> kfree(t->dev_name);
> - kfree(t);
> }
>
> static void devinet_sysctl_register(struct in_device *idev)
^ permalink raw reply
* Re: [net-next-2.6 4/5] enic: Clean up: Remove support for an older version of hardware
From: David Miller @ 2011-02-06 1:57 UTC (permalink / raw)
To: vkolluri; +Cc: netdev
If this hardware ever shipped to any customers, you cannot
simply remove support for it.
Such code must be retained.
^ permalink raw reply
* Re: [PATCH] ServerEngines, benet: Avoid potential null deref in be_cmd_get_seeprom_data()
From: David Miller @ 2011-02-06 1:58 UTC (permalink / raw)
To: ajit.khaparde; +Cc: netdev, jj, linux-kernel
In-Reply-To: <20110205031828.GA12772@akhaparde-VBox>
From: Ajit Khaparde <ajit.khaparde@emulex.com>
Date: Fri, 4 Feb 2011 21:18:28 -0600
> [PATCH] ServerEngines, benet: Avoid potential null deref in be_cmd_get_seeprom_data()
>
> Found by: Jesper Juhl <jj@chaosbits.net>
>
> Signed-off-by: Ajit Khaparde <ajit.khaparde@emulex.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH] sis900: Fix mem leak in sis900_rx error path
From: David Miller @ 2011-02-06 2:09 UTC (permalink / raw)
To: jj; +Cc: venza, netdev, linux-kernel
In-Reply-To: <alpine.LNX.2.00.1102052139150.12305@swampdragon.chaosbits.net>
From: Jesper Juhl <jj@chaosbits.net>
Date: Sat, 5 Feb 2011 21:41:53 +0100 (CET)
> Fix memory leak in error path of sis900_rx(). If we don't do this we'll
> leak the skb we dev_alloc_skb()'ed just a few lines above when the
> variable goes out of scope.
>
> Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Applied, thanks Jesper.
^ permalink raw reply
* Re: [PATCH] tcp: Increase the initial congestion window to 10.
From: David Miller @ 2011-02-06 2:14 UTC (permalink / raw)
To: alexander.zimmermann; +Cc: netdev, dccp, therbert
In-Reply-To: <C9A0E70E-D1DB-45CF-ABB1-8CF9A9D03144@comsys.rwth-aachen.de>
From: Alexander Zimmermann <alexander.zimmermann@comsys.rwth-aachen.de>
Date: Fri, 04 Feb 2011 09:38:34 +0100
> Could you add a reference to draft?
>
>> +/* TCP initial congestion window */
>> +#define TCP_INIT_CWND 10
>> +
>> extern struct inet_timewait_death_row tcp_death_row;
Sure, done.
--------------------
tcp: Add reference to initial CWND ietf draft.
Suggested by Alexander Zimmermann
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/net/tcp.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 7118668..adfe6db 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -196,7 +196,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
/* TCP thin-stream limits */
#define TCP_THIN_LINEAR_RETRIES 6 /* After 6 linear retries, do exp. backoff */
-/* TCP initial congestion window */
+/* TCP initial congestion window as per draft-hkchu-tcpm-initcwnd-01 */
#define TCP_INIT_CWND 10
extern struct inet_timewait_death_row tcp_death_row;
--
1.7.4
^ permalink raw reply related
* RE: [net-next-2.6 4/5] enic: Clean up: Remove support for an older version of hardware
From: Vasanthy Kolluri (vkolluri) @ 2011-02-06 3:13 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20110205.175702.226777511.davem@davemloft.net>
This hardware was never shipped to customers. So we are safe removing
it.
Thanks
Vasanthy
-----Original Message-----
From: David Miller [mailto:davem@davemloft.net]
Sent: Saturday, February 05, 2011 5:57 PM
To: Vasanthy Kolluri (vkolluri)
Cc: netdev@vger.kernel.org
Subject: Re: [net-next-2.6 4/5] enic: Clean up: Remove support for an
older version of hardware
If this hardware ever shipped to any customers, you cannot
simply remove support for it.
Such code must be retained.
^ permalink raw reply
* re: tlan: Code cleanup: checkpatch.pl is relatively happy now.
From: Dan Carpenter @ 2011-02-06 10:43 UTC (permalink / raw)
To: Sakari Ailus; +Cc: netdev
Commit c659c38b279657 "tlan: Code cleanup: checkpatch.pl is relatively
happy now." includes the following change without explanation.
- if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
+ if (head_list->c_stat & TLAN_CSTAT_READY) {
Was this a bug fix or a bug introduce?
regards,
dan carpenter
^ permalink raw reply
* [PATCH 4/4] m68k/atari: ARAnyM - Add support for network access
From: Geert Uytterhoeven @ 2011-02-06 10:51 UTC (permalink / raw)
To: linux-m68k, linux-kernel, cz-bobek-lists-aranym
Cc: Michael Schmitz, Geert Uytterhoeven, Petr Stehlik, Milan Jurik,
netdev
In-Reply-To: <1296989469-7844-1-git-send-email-geert@linux-m68k.org>
From: Michael Schmitz <schmitz@opal.biophys.uni-duesseldorf.de>
Should be signed off by Milan and Petr, really.
[geert] Cleanups and updates
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Petr Stehlik <pstehlik@sophics.cz>
Cc: Milan Jurik <M.Jurik@sh.cvut.cz>
Cc: netdev@vger.kernel.org
---
Changelog:
- Convert to net_device_ops,
- nfeth doesn't need obsolete <net/ieee80211.h>,
- Convert print_mac to %pM,
- Break too long lines,
- Make needlessly global functions static,
- Make version[] const,
- Use pr_*(),
- Use net_device_stats from struct net_device instead of our own,
- Propagate error code from request_irq(),
- Remove unused variable "handled".
---
arch/m68k/Kconfig | 8 ++
arch/m68k/emu/Makefile | 1 +
arch/m68k/emu/nfeth.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 281 insertions(+), 0 deletions(-)
create mode 100644 arch/m68k/emu/nfeth.c
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 6719c56..80df6ee 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -263,6 +263,14 @@ config NFCON
which allows the console output to be redirected to the stderr
output of ARAnyM.
+config NFETH
+ tristate "NatFeat Ethernet support"
+ depends on NET_ETHERNET && NATFEAT
+ help
+ Say Y to include support for the ARAnyM NatFeat network device
+ which will emulate a regular ethernet device while presenting an
+ ethertap device to the host system.
+
comment "Processor type"
config M68020
diff --git a/arch/m68k/emu/Makefile b/arch/m68k/emu/Makefile
index a83ef1e..7dc2010 100644
--- a/arch/m68k/emu/Makefile
+++ b/arch/m68k/emu/Makefile
@@ -6,3 +6,4 @@ obj-y += natfeat.o
obj-$(CONFIG_NFBLOCK) += nfblock.o
obj-$(CONFIG_NFCON) += nfcon.o
+obj-$(CONFIG_NFETH) += nfeth.o
diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
new file mode 100644
index 0000000..5b2a33d
--- /dev/null
+++ b/arch/m68k/emu/nfeth.c
@@ -0,0 +1,272 @@
+/*
+ * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux
+ *
+ * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team
+ *
+ * Based on ARAnyM driver for FreeMiNT written by Standa Opichal
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <asm/natfeat.h>
+#include <asm/virtconvert.h>
+
+enum {
+ GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */
+ XIF_INTLEVEL, /* no parameters, return Interrupt Level in d0 */
+ XIF_IRQ, /* acknowledge interrupt from host */
+ XIF_START, /* (ethX), called on 'ifup', start receiver thread */
+ XIF_STOP, /* (ethX), called on 'ifdown', stop the thread */
+ XIF_READLENGTH, /* (ethX), return size of network data block to read */
+ XIF_READBLOCK, /* (ethX, buffer, size), read block of network data */
+ XIF_WRITEBLOCK, /* (ethX, buffer, size), write block of network data */
+ XIF_GET_MAC, /* (ethX, buffer, size), return MAC HW addr in buffer */
+ XIF_GET_IPHOST, /* (ethX, buffer, size), return IP address of host */
+ XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */
+ XIF_GET_NETMASK /* (ethX, buffer, size), return IP netmask */
+};
+
+#define DRV_NAME "nfeth"
+#define DRV_VERSION "0.3"
+#define DRV_RELDATE "10/12/2005"
+
+#define MAX_UNIT 8
+
+/* These identify the driver base version and may not be removed. */
+static const char version[] __devinitdata =
+ KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
+ " S.Opichal, M.Jurik, P.Stehlik\n"
+ KERN_INFO " http://aranym.atari.org/\n";
+
+MODULE_AUTHOR("Milan Jurik");
+MODULE_DESCRIPTION("Atari NFeth driver");
+MODULE_LICENSE("GPL");
+/*
+MODULE_PARM(nfeth_debug, "i");
+MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)");
+*/
+
+
+static long nfEtherID;
+static int nfEtherIRQ;
+
+struct nfeth_private {
+ int ethX;
+};
+
+static struct net_device *nfeth_dev[MAX_UNIT];
+
+static int nfeth_open(struct net_device *dev)
+{
+ struct nfeth_private *priv = netdev_priv(dev);
+ int res;
+
+ res = nf_call(nfEtherID + XIF_START, priv->ethX);
+
+ pr_debug(DRV_NAME ": open %d\n", res);
+
+ /* Ready for data */
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int nfeth_stop(struct net_device *dev)
+{
+ struct nfeth_private *priv = netdev_priv(dev);
+
+ /* No more data */
+ netif_stop_queue(dev);
+
+ nf_call(nfEtherID + XIF_STOP, priv->ethX);
+
+ return 0;
+}
+
+/*
+ * Read a packet out of the adapter and pass it to the upper layers
+ */
+static inline void recv_packet(struct net_device *dev)
+{
+ struct nfeth_private *priv = netdev_priv(dev);
+ unsigned short pktlen;
+ struct sk_buff *skb;
+
+ /* read packet length (excluding 32 bit crc) */
+ pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);
+
+ pr_debug(DRV_NAME ": recv_packet: %i\n", pktlen);
+
+ if (!pktlen) {
+ pr_debug(DRV_NAME ": recv_packet: pktlen == 0\n");
+ dev->stats.rx_errors++;
+ return;
+ }
+
+ skb = dev_alloc_skb(pktlen + 2);
+ if (!skb) {
+ pr_debug(DRV_NAME
+ ": recv_packet: out of mem (buf_alloc failed)\n");
+ dev->stats.rx_dropped++;
+ return;
+ }
+
+ skb->dev = dev;
+ skb_reserve(skb, 2); /* 16 Byte align */
+ skb_put(skb, pktlen); /* make room */
+ nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data),
+ pktlen);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pktlen;
+
+ /* and enqueue packet */
+ return;
+}
+
+static irqreturn_t nfeth_interrupt(int irq, void *dev_id)
+{
+ int i, m, mask;
+
+ mask = nf_call(nfEtherID + XIF_IRQ, 0);
+ for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) {
+ if (mask & m && nfeth_dev[i]) {
+ recv_packet(nfeth_dev[i]);
+ nf_call(nfEtherID + XIF_IRQ, m);
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ int len;
+ char *data, shortpkt[ETH_ZLEN];
+ struct nfeth_private *priv = netdev_priv(dev);
+
+ data = skb->data;
+ len = skb->len;
+ if (len < ETH_ZLEN) {
+ memset(shortpkt, 0, ETH_ZLEN);
+ memcpy(shortpkt, data, len);
+ data = shortpkt;
+ len = ETH_ZLEN;
+ }
+
+ dev->trans_start = jiffies;
+
+ pr_debug(DRV_NAME ": send %d bytes\n", len);
+ nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data),
+ len);
+
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += len;
+
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+static void nfeth_tx_timeout(struct net_device *dev)
+{
+ dev->stats.tx_errors++;
+ netif_wake_queue(dev);
+}
+
+static const struct net_device_ops nfeth_netdev_ops = {
+ .ndo_open = nfeth_open,
+ .ndo_stop = nfeth_stop,
+ .ndo_start_xmit = nfeth_xmit,
+ .ndo_tx_timeout = nfeth_tx_timeout,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+};
+
+static struct net_device * __init nfeth_probe(int unit)
+{
+ struct net_device *dev;
+ struct nfeth_private *priv;
+ char mac[ETH_ALEN], host_ip[32], local_ip[32];
+ int err;
+
+ if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN))
+ return NULL;
+
+ dev = alloc_etherdev(sizeof(struct nfeth_private));
+ if (!dev)
+ return NULL;
+
+ dev->irq = nfEtherIRQ;
+ dev->netdev_ops = &nfeth_netdev_ops;
+
+ dev->flags |= NETIF_F_NO_CSUM;
+ memcpy(dev->dev_addr, mac, ETH_ALEN);
+
+ priv = netdev_priv(dev);
+ priv->ethX = unit;
+
+ err = register_netdev(dev);
+ if (err) {
+ free_netdev(dev);
+ return NULL;
+ }
+
+ nf_call(nfEtherID + XIF_GET_IPHOST, unit,
+ host_ip, sizeof(host_ip));
+ nf_call(nfEtherID + XIF_GET_IPATARI, unit,
+ local_ip, sizeof(local_ip));
+
+ pr_info("%s: nfeth addr:%s (%s) HWaddr:%pM\n", dev->name, host_ip,
+ local_ip, mac);
+
+ return dev;
+}
+
+static int __init nfeth_init(void)
+{
+ long ver;
+ int error, i;
+
+ nfEtherID = nf_get_id("ETHERNET");
+ if (!nfEtherID)
+ return -ENODEV;
+
+ ver = nf_call(nfEtherID + GET_VERSION);
+ pr_info("nfeth API %lu\n", ver);
+
+ nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
+ error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
+ "eth emu", nfeth_interrupt);
+ if (error) {
+ pr_err("nfeth: request for irq %d failed", nfEtherIRQ);
+ return error;
+ }
+
+ for (i = 0; i < MAX_UNIT; i++)
+ nfeth_dev[i] = nfeth_probe(i);
+
+ return 0;
+}
+
+static void __exit nfeth_cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_UNIT; i++) {
+ if (nfeth_dev[i]) {
+ unregister_netdev(nfeth_dev[0]);
+ free_netdev(nfeth_dev[0]);
+ }
+ }
+ free_irq(nfEtherIRQ, nfeth_interrupt);
+}
+
+module_init(nfeth_init);
+module_exit(nfeth_cleanup);
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 4/4] m68k/atari: ARAnyM - Add support for network access
From: Petr Stehlik @ 2011-02-06 12:30 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: linux-m68k, linux-kernel, cz-bobek-lists-aranym, Michael Schmitz,
Milan Jurik, netdev
In-Reply-To: <1296989469-7844-5-git-send-email-geert@linux-m68k.org>
Geert Uytterhoeven píše v Ne 06. 02. 2011 v 11:51 +0100:
> From: Michael Schmitz <schmitz@opal.biophys.uni-duesseldorf.de>
>
> Should be signed off by Milan and Petr, really.
>
> [geert] Cleanups and updates
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: Petr Stehlik <pstehlik@sophics.cz>
Signed-off-by: Petr Stehlik <pstehlik@sophics.cz>
Petr
P.S. you might want to update the URL - ARAnyM got its own domain:
> + " S.Opichal, M.Jurik, P.Stehlik\n"
> + KERN_INFO " http://aranym.atari.org/\n";
+ KERN_INFO " http://aranym.org/\n";
^ permalink raw reply
* [PATCH net-next] bnx2x: MTU for FCoE L2 ring
From: Vladislav Zolotarov @ 2011-02-06 12:49 UTC (permalink / raw)
To: Dave Miller; +Cc: netdev list, Eilon Greenstein
Always configure an FCoE L2 ring with a mini-jumbo MTU size (2500).
To do that we had to move the rx_buf_size parameter from per
function level to a per ring level.
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x/bnx2x.h | 7 ++++-
drivers/net/bnx2x/bnx2x_cmn.c | 53 +++++++++++++++++++++++++++----------
drivers/net/bnx2x/bnx2x_cmn.h | 6 ++--
drivers/net/bnx2x/bnx2x_ethtool.c | 2 +-
drivers/net/bnx2x/bnx2x_main.c | 10 +++++-
5 files changed, 57 insertions(+), 21 deletions(-)
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index ff87ec3..c29b37e 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -341,6 +341,8 @@ struct bnx2x_fastpath {
/* chip independed shortcut into rx_prods_offset memory */
u32 ustorm_rx_prods_offset;
+ u32 rx_buf_size;
+
dma_addr_t status_blk_mapping;
struct sw_tx_bd *tx_buf_ring;
@@ -428,6 +430,10 @@ struct bnx2x_fastpath {
};
#define bnx2x_fp(bp, nr, var) (bp->fp[nr].var)
+
+/* Use 2500 as a mini-jumbo MTU for FCoE */
+#define BNX2X_FCOE_MINI_JUMBO_MTU 2500
+
#ifdef BCM_CNIC
/* FCoE L2 `fastpath' is right after the eth entries */
#define FCOE_IDX BNX2X_NUM_ETH_QUEUES(bp)
@@ -911,7 +917,6 @@ struct bnx2x {
int tx_ring_size;
u32 rx_csum;
- u32 rx_buf_size;
/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
#define ETH_OVREHEAD (ETH_HLEN + 8 + 8)
#define ETH_MIN_PACKET_SIZE 60
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 710ce5d..844afce 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -232,7 +232,7 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
/* move empty skb from pool to prod and map it */
prod_rx_buf->skb = fp->tpa_pool[queue].skb;
mapping = dma_map_single(&bp->pdev->dev, fp->tpa_pool[queue].skb->data,
- bp->rx_buf_size, DMA_FROM_DEVICE);
+ fp->rx_buf_size, DMA_FROM_DEVICE);
dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
/* move partial skb from cons to pool (don't unmap yet) */
@@ -333,13 +333,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
struct sw_rx_bd *rx_buf = &fp->tpa_pool[queue];
struct sk_buff *skb = rx_buf->skb;
/* alloc new skb */
- struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+ struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
/* Unmap skb in the pool anyway, as we are going to change
pool entry status to BNX2X_TPA_STOP even if new skb allocation
fails. */
dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping),
- bp->rx_buf_size, DMA_FROM_DEVICE);
+ fp->rx_buf_size, DMA_FROM_DEVICE);
if (likely(new_skb)) {
/* fix ip xsum and give it to the stack */
@@ -349,10 +349,10 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
prefetch(((char *)(skb)) + L1_CACHE_BYTES);
#ifdef BNX2X_STOP_ON_ERROR
- if (pad + len > bp->rx_buf_size) {
+ if (pad + len > fp->rx_buf_size) {
BNX2X_ERR("skb_put is about to fail... "
"pad %d len %d rx_buf_size %d\n",
- pad, len, bp->rx_buf_size);
+ pad, len, fp->rx_buf_size);
bnx2x_panic();
return;
}
@@ -582,7 +582,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) {
dma_unmap_single(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
- bp->rx_buf_size,
+ fp->rx_buf_size,
DMA_FROM_DEVICE);
skb_reserve(skb, pad);
skb_put(skb, len);
@@ -821,19 +821,16 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
u16 ring_prod;
int i, j;
- bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
- IP_HEADER_ALIGNMENT_PADDING;
-
- DP(NETIF_MSG_IFUP,
- "mtu %d rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size);
-
for_each_rx_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
+ DP(NETIF_MSG_IFUP,
+ "mtu %d rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
+
if (!fp->disable_tpa) {
for (i = 0; i < max_agg_queues; i++) {
fp->tpa_pool[i].skb =
- netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+ netdev_alloc_skb(bp->dev, fp->rx_buf_size);
if (!fp->tpa_pool[i].skb) {
BNX2X_ERR("Failed to allocate TPA "
"skb pool for queue[%d] - "
@@ -941,7 +938,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
dma_unmap_single(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
- bp->rx_buf_size, DMA_FROM_DEVICE);
+ fp->rx_buf_size, DMA_FROM_DEVICE);
rx_buf->skb = NULL;
dev_kfree_skb(skb);
@@ -1249,6 +1246,31 @@ static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
return rc;
}
+static inline void bnx2x_set_rx_buf_size(struct bnx2x *bp)
+{
+ int i;
+
+ for_each_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+
+ /* Always use a mini-jumbo MTU for the FCoE L2 ring */
+ if (IS_FCOE_IDX(i))
+ /*
+ * Although there are no IP frames expected to arrive to
+ * this ring we still want to add an
+ * IP_HEADER_ALIGNMENT_PADDING to prevent a buffer
+ * overrun attack.
+ */
+ fp->rx_buf_size =
+ BNX2X_FCOE_MINI_JUMBO_MTU + ETH_OVREHEAD +
+ BNX2X_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
+ else
+ fp->rx_buf_size =
+ bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
+ IP_HEADER_ALIGNMENT_PADDING;
+ }
+}
+
/* must be called with rtnl_lock */
int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
@@ -1272,6 +1294,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* must be called before memory allocation and HW init */
bnx2x_ilt_set_info(bp);
+ /* Set the receive queues buffer size */
+ bnx2x_set_rx_buf_size(bp);
+
if (bnx2x_alloc_mem(bp))
return -ENOMEM;
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index 03eb4d6..f062d5d 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -822,11 +822,11 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
dma_addr_t mapping;
- skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+ skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
if (unlikely(skb == NULL))
return -ENOMEM;
- mapping = dma_map_single(&bp->pdev->dev, skb->data, bp->rx_buf_size,
+ mapping = dma_map_single(&bp->pdev->dev, skb->data, fp->rx_buf_size,
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
dev_kfree_skb(skb);
@@ -892,7 +892,7 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
if (fp->tpa_state[i] == BNX2X_TPA_START)
dma_unmap_single(&bp->pdev->dev,
dma_unmap_addr(rx_buf, mapping),
- bp->rx_buf_size, DMA_FROM_DEVICE);
+ fp->rx_buf_size, DMA_FROM_DEVICE);
dev_kfree_skb(skb);
rx_buf->skb = NULL;
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 5b44a8b..816fef6 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -1618,7 +1618,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
/* prepare the loopback packet */
pkt_size = (((bp->dev->mtu < ETH_MAX_PACKET_SIZE) ?
bp->dev->mtu : ETH_MAX_PACKET_SIZE) + ETH_HLEN);
- skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+ skb = netdev_alloc_skb(bp->dev, fp_rx->rx_buf_size);
if (!skb) {
rc = -ENOMEM;
goto test_loopback_exit;
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index ae8d20a..4b2cc1f 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -2478,8 +2478,14 @@ static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
rxq_init->sge_map = fp->rx_sge_mapping;
rxq_init->rcq_map = fp->rx_comp_mapping;
rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
- rxq_init->mtu = bp->dev->mtu;
- rxq_init->buf_sz = bp->rx_buf_size;
+
+ /* Always use mini-jumbo MTU for FCoE L2 ring */
+ if (IS_FCOE_FP(fp))
+ rxq_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
+ else
+ rxq_init->mtu = bp->dev->mtu;
+
+ rxq_init->buf_sz = fp->rx_buf_size;
rxq_init->cl_qzone_id = fp->cl_qzone_id;
rxq_init->cl_id = fp->cl_id;
rxq_init->spcl_id = fp->cl_id;
--
1.7.0.4
^ permalink raw reply related
* Re: [Aranym-dev] [PATCH 4/4] m68k/atari: ARAnyM - Add support for network access
From: Milan Jurik @ 2011-02-06 12:52 UTC (permalink / raw)
To: aranym
Cc: linux-m68k, linux-kernel, cz-bobek-lists-aranym, Milan Jurik,
Michael Schmitz, netdev, Geert Uytterhoeven
In-Reply-To: <1296989469-7844-5-git-send-email-geert@linux-m68k.org>
Hi,
Signed-off-by: Milan Jurik <milan.jurik@xylab.cz>
The original e-mail address is dead for some time.
Best regards,
Milan
Geert Uytterhoeven píše v ne 06. 02. 2011 v 11:51 +0100:
> From: Michael Schmitz <schmitz@opal.biophys.uni-duesseldorf.de>
>
> Should be signed off by Milan and Petr, really.
>
> [geert] Cleanups and updates
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: Petr Stehlik <pstehlik@sophics.cz>
> Cc: Milan Jurik <M.Jurik@sh.cvut.cz>
> Cc: netdev@vger.kernel.org
>
> ---
> Changelog:
> - Convert to net_device_ops,
> - nfeth doesn't need obsolete <net/ieee80211.h>,
> - Convert print_mac to %pM,
> - Break too long lines,
> - Make needlessly global functions static,
> - Make version[] const,
> - Use pr_*(),
> - Use net_device_stats from struct net_device instead of our own,
> - Propagate error code from request_irq(),
> - Remove unused variable "handled".
> ---
> arch/m68k/Kconfig | 8 ++
> arch/m68k/emu/Makefile | 1 +
> arch/m68k/emu/nfeth.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 281 insertions(+), 0 deletions(-)
> create mode 100644 arch/m68k/emu/nfeth.c
>
> diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
> index 6719c56..80df6ee 100644
> --- a/arch/m68k/Kconfig
> +++ b/arch/m68k/Kconfig
> @@ -263,6 +263,14 @@ config NFCON
> which allows the console output to be redirected to the stderr
> output of ARAnyM.
>
> +config NFETH
> + tristate "NatFeat Ethernet support"
> + depends on NET_ETHERNET && NATFEAT
> + help
> + Say Y to include support for the ARAnyM NatFeat network device
> + which will emulate a regular ethernet device while presenting an
> + ethertap device to the host system.
> +
> comment "Processor type"
>
> config M68020
> diff --git a/arch/m68k/emu/Makefile b/arch/m68k/emu/Makefile
> index a83ef1e..7dc2010 100644
> --- a/arch/m68k/emu/Makefile
> +++ b/arch/m68k/emu/Makefile
> @@ -6,3 +6,4 @@ obj-y += natfeat.o
>
> obj-$(CONFIG_NFBLOCK) += nfblock.o
> obj-$(CONFIG_NFCON) += nfcon.o
> +obj-$(CONFIG_NFETH) += nfeth.o
> diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
> new file mode 100644
> index 0000000..5b2a33d
> --- /dev/null
> +++ b/arch/m68k/emu/nfeth.c
> @@ -0,0 +1,272 @@
> +/*
> + * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux
> + *
> + * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team
> + *
> + * Based on ARAnyM driver for FreeMiNT written by Standa Opichal
> + *
> + * This software may be used and distributed according to the terms of
> + * the GNU General Public License (GPL), incorporated herein by reference.
> + */
> +
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/module.h>
> +#include <asm/natfeat.h>
> +#include <asm/virtconvert.h>
> +
> +enum {
> + GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */
> + XIF_INTLEVEL, /* no parameters, return Interrupt Level in d0 */
> + XIF_IRQ, /* acknowledge interrupt from host */
> + XIF_START, /* (ethX), called on 'ifup', start receiver thread */
> + XIF_STOP, /* (ethX), called on 'ifdown', stop the thread */
> + XIF_READLENGTH, /* (ethX), return size of network data block to read */
> + XIF_READBLOCK, /* (ethX, buffer, size), read block of network data */
> + XIF_WRITEBLOCK, /* (ethX, buffer, size), write block of network data */
> + XIF_GET_MAC, /* (ethX, buffer, size), return MAC HW addr in buffer */
> + XIF_GET_IPHOST, /* (ethX, buffer, size), return IP address of host */
> + XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */
> + XIF_GET_NETMASK /* (ethX, buffer, size), return IP netmask */
> +};
> +
> +#define DRV_NAME "nfeth"
> +#define DRV_VERSION "0.3"
> +#define DRV_RELDATE "10/12/2005"
> +
> +#define MAX_UNIT 8
> +
> +/* These identify the driver base version and may not be removed. */
> +static const char version[] __devinitdata =
> + KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
> + " S.Opichal, M.Jurik, P.Stehlik\n"
> + KERN_INFO " http://aranym.atari.org/\n";
> +
> +MODULE_AUTHOR("Milan Jurik");
> +MODULE_DESCRIPTION("Atari NFeth driver");
> +MODULE_LICENSE("GPL");
> +/*
> +MODULE_PARM(nfeth_debug, "i");
> +MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)");
> +*/
> +
> +
> +static long nfEtherID;
> +static int nfEtherIRQ;
> +
> +struct nfeth_private {
> + int ethX;
> +};
> +
> +static struct net_device *nfeth_dev[MAX_UNIT];
> +
> +static int nfeth_open(struct net_device *dev)
> +{
> + struct nfeth_private *priv = netdev_priv(dev);
> + int res;
> +
> + res = nf_call(nfEtherID + XIF_START, priv->ethX);
> +
> + pr_debug(DRV_NAME ": open %d\n", res);
> +
> + /* Ready for data */
> + netif_start_queue(dev);
> +
> + return 0;
> +}
> +
> +static int nfeth_stop(struct net_device *dev)
> +{
> + struct nfeth_private *priv = netdev_priv(dev);
> +
> + /* No more data */
> + netif_stop_queue(dev);
> +
> + nf_call(nfEtherID + XIF_STOP, priv->ethX);
> +
> + return 0;
> +}
> +
> +/*
> + * Read a packet out of the adapter and pass it to the upper layers
> + */
> +static inline void recv_packet(struct net_device *dev)
> +{
> + struct nfeth_private *priv = netdev_priv(dev);
> + unsigned short pktlen;
> + struct sk_buff *skb;
> +
> + /* read packet length (excluding 32 bit crc) */
> + pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);
> +
> + pr_debug(DRV_NAME ": recv_packet: %i\n", pktlen);
> +
> + if (!pktlen) {
> + pr_debug(DRV_NAME ": recv_packet: pktlen == 0\n");
> + dev->stats.rx_errors++;
> + return;
> + }
> +
> + skb = dev_alloc_skb(pktlen + 2);
> + if (!skb) {
> + pr_debug(DRV_NAME
> + ": recv_packet: out of mem (buf_alloc failed)\n");
> + dev->stats.rx_dropped++;
> + return;
> + }
> +
> + skb->dev = dev;
> + skb_reserve(skb, 2); /* 16 Byte align */
> + skb_put(skb, pktlen); /* make room */
> + nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data),
> + pktlen);
> +
> + skb->protocol = eth_type_trans(skb, dev);
> + netif_rx(skb);
> + dev->last_rx = jiffies;
> + dev->stats.rx_packets++;
> + dev->stats.rx_bytes += pktlen;
> +
> + /* and enqueue packet */
> + return;
> +}
> +
> +static irqreturn_t nfeth_interrupt(int irq, void *dev_id)
> +{
> + int i, m, mask;
> +
> + mask = nf_call(nfEtherID + XIF_IRQ, 0);
> + for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) {
> + if (mask & m && nfeth_dev[i]) {
> + recv_packet(nfeth_dev[i]);
> + nf_call(nfEtherID + XIF_IRQ, m);
> + }
> + }
> + return IRQ_HANDLED;
> +}
> +
> +static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + int len;
> + char *data, shortpkt[ETH_ZLEN];
> + struct nfeth_private *priv = netdev_priv(dev);
> +
> + data = skb->data;
> + len = skb->len;
> + if (len < ETH_ZLEN) {
> + memset(shortpkt, 0, ETH_ZLEN);
> + memcpy(shortpkt, data, len);
> + data = shortpkt;
> + len = ETH_ZLEN;
> + }
> +
> + dev->trans_start = jiffies;
> +
> + pr_debug(DRV_NAME ": send %d bytes\n", len);
> + nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data),
> + len);
> +
> + dev->stats.tx_packets++;
> + dev->stats.tx_bytes += len;
> +
> + dev_kfree_skb(skb);
> + return 0;
> +}
> +
> +static void nfeth_tx_timeout(struct net_device *dev)
> +{
> + dev->stats.tx_errors++;
> + netif_wake_queue(dev);
> +}
> +
> +static const struct net_device_ops nfeth_netdev_ops = {
> + .ndo_open = nfeth_open,
> + .ndo_stop = nfeth_stop,
> + .ndo_start_xmit = nfeth_xmit,
> + .ndo_tx_timeout = nfeth_tx_timeout,
> + .ndo_validate_addr = eth_validate_addr,
> + .ndo_change_mtu = eth_change_mtu,
> + .ndo_set_mac_address = eth_mac_addr,
> +};
> +
> +static struct net_device * __init nfeth_probe(int unit)
> +{
> + struct net_device *dev;
> + struct nfeth_private *priv;
> + char mac[ETH_ALEN], host_ip[32], local_ip[32];
> + int err;
> +
> + if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN))
> + return NULL;
> +
> + dev = alloc_etherdev(sizeof(struct nfeth_private));
> + if (!dev)
> + return NULL;
> +
> + dev->irq = nfEtherIRQ;
> + dev->netdev_ops = &nfeth_netdev_ops;
> +
> + dev->flags |= NETIF_F_NO_CSUM;
> + memcpy(dev->dev_addr, mac, ETH_ALEN);
> +
> + priv = netdev_priv(dev);
> + priv->ethX = unit;
> +
> + err = register_netdev(dev);
> + if (err) {
> + free_netdev(dev);
> + return NULL;
> + }
> +
> + nf_call(nfEtherID + XIF_GET_IPHOST, unit,
> + host_ip, sizeof(host_ip));
> + nf_call(nfEtherID + XIF_GET_IPATARI, unit,
> + local_ip, sizeof(local_ip));
> +
> + pr_info("%s: nfeth addr:%s (%s) HWaddr:%pM\n", dev->name, host_ip,
> + local_ip, mac);
> +
> + return dev;
> +}
> +
> +static int __init nfeth_init(void)
> +{
> + long ver;
> + int error, i;
> +
> + nfEtherID = nf_get_id("ETHERNET");
> + if (!nfEtherID)
> + return -ENODEV;
> +
> + ver = nf_call(nfEtherID + GET_VERSION);
> + pr_info("nfeth API %lu\n", ver);
> +
> + nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
> + error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
> + "eth emu", nfeth_interrupt);
> + if (error) {
> + pr_err("nfeth: request for irq %d failed", nfEtherIRQ);
> + return error;
> + }
> +
> + for (i = 0; i < MAX_UNIT; i++)
> + nfeth_dev[i] = nfeth_probe(i);
> +
> + return 0;
> +}
> +
> +static void __exit nfeth_cleanup(void)
> +{
> + int i;
> +
> + for (i = 0; i < MAX_UNIT; i++) {
> + if (nfeth_dev[i]) {
> + unregister_netdev(nfeth_dev[0]);
> + free_netdev(nfeth_dev[0]);
> + }
> + }
> + free_irq(nfEtherIRQ, nfeth_interrupt);
> +}
> +
> +module_init(nfeth_init);
> +module_exit(nfeth_cleanup);
^ permalink raw reply
* [PATCH net-2.6] bnx2x: Duplication in promisc mode
From: Vladislav Zolotarov @ 2011-02-06 13:14 UTC (permalink / raw)
To: Dave Miller; +Cc: netdev list, Eilon Greenstein
Prevent packets duplication for frames targeting FCoE L2 ring:
packets were arriving to stack from both L2 RSS and from FCoE
L2 in a promiscuous mode.
Configure FCoE L2 ring to DROP_ALL rx mode, when interface is
configured to PROMISC, and to accept only unicast frames, when
interface is configured to ALL_MULTI.
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x/bnx2x_main.c | 32 +++++++++++++++++++++++---------
1 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index ae8d20a..84608c8 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -4281,9 +4281,12 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
BNX2X_ACCEPT_MULTICAST;
#ifdef BCM_CNIC
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_UNICAST |
- BNX2X_ACCEPT_MULTICAST);
+ if (!NO_FCOE(bp)) {
+ cl_id = bnx2x_fcoe(bp, cl_id);
+ bnx2x_rxq_set_mac_filters(bp, cl_id,
+ BNX2X_ACCEPT_UNICAST |
+ BNX2X_ACCEPT_MULTICAST);
+ }
#endif
break;
@@ -4291,18 +4294,29 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
BNX2X_ACCEPT_ALL_MULTICAST;
#ifdef BCM_CNIC
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_UNICAST |
- BNX2X_ACCEPT_MULTICAST);
+ /*
+ * Prevent duplication of multicast packets by configuring FCoE
+ * L2 Client to receive only matched unicast frames.
+ */
+ if (!NO_FCOE(bp)) {
+ cl_id = bnx2x_fcoe(bp, cl_id);
+ bnx2x_rxq_set_mac_filters(bp, cl_id,
+ BNX2X_ACCEPT_UNICAST);
+ }
#endif
break;
case BNX2X_RX_MODE_PROMISC:
def_q_filters |= BNX2X_PROMISCUOUS_MODE;
#ifdef BCM_CNIC
- cl_id = bnx2x_fcoe(bp, cl_id);
- bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_UNICAST |
- BNX2X_ACCEPT_MULTICAST);
+ /*
+ * Prevent packets duplication by configuring DROP_ALL for FCoE
+ * L2 Client.
+ */
+ if (!NO_FCOE(bp)) {
+ cl_id = bnx2x_fcoe(bp, cl_id);
+ bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
+ }
#endif
/* pass management unicast packets as well */
llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
--
1.7.0.4
^ permalink raw reply related
* Re: tlan: Code cleanup: checkpatch.pl is relatively happy now.
From: Sakari Ailus @ 2011-02-06 13:24 UTC (permalink / raw)
To: Dan Carpenter; +Cc: netdev
In-Reply-To: <20110206104330.GA4384@bicker>
Hi Dan,
Dan Carpenter wrote:
> Commit c659c38b279657 "tlan: Code cleanup: checkpatch.pl is relatively
> happy now." includes the following change without explanation.
>
> - if ( ( head_list->cStat& TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
> + if (head_list->c_stat& TLAN_CSTAT_READY) {
>
> Was this a bug fix or a bug introduce?
Ouch. Introduce in this case, unfortunately. I *thought*
TLAN_CSTAT_READY would have been a single bit instead of a bit mask. I
should have actually checked it, and still put that change into a
separate patch.
This might not be the one and only place where this kind of shortcut was
made --- for 80 characters per line compliance. There are very few,
anyway, in similar places.
I'll recheck the patch and provide a correction, in the coming days likely.
Many thanks for finding this!
--
Sakari Ailus
sakari.ailus@iki.fi
^ permalink raw reply
* [PATCH net-next] bnx2x: Proper netdev->ndo_set_rx_mode() implementation.
From: Vlad Zolotarov @ 2011-02-06 16:50 UTC (permalink / raw)
To: Dave Miller; +Cc: netdev@vger.kernel.org, Eilon Greenstein
Completed the bnx2x_set_rx_mode() to a proper netdev->ndo_set_rx_mode
implementation:
- Added a missing configuration of a unicast MAC addresses list.
- Changed bp->dma_lock from being a mutex to a spinlock as long as it's taken
under netdev->addr_list_lock now.
Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
---
drivers/net/bnx2x/bnx2x.h | 13 +-
drivers/net/bnx2x/bnx2x_cmn.c | 17 +-
drivers/net/bnx2x/bnx2x_main.c | 444 +++++++++++++++++++++++++++++++---------
3 files changed, 369 insertions(+), 105 deletions(-)
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 8e41837..9821bd9 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -129,6 +129,7 @@ void bnx2x_panic_dump(struct bnx2x *bp);
#endif
#define bnx2x_mc_addr(ha) ((ha)->addr)
+#define bnx2x_uc_addr(ha) ((ha)->addr)
#define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff)
#define U64_HI(x) (u32)(((u64)(x)) >> 32)
@@ -810,6 +811,7 @@ struct bnx2x_slowpath {
struct eth_stats_query fw_stats;
struct mac_configuration_cmd mac_config;
struct mac_configuration_cmd mcast_config;
+ struct mac_configuration_cmd uc_mac_config;
struct client_init_ramrod_data client_init_data;
/* used by dmae command executer */
@@ -939,7 +941,7 @@ struct bnx2x {
struct eth_spe *spq_prod_bd;
struct eth_spe *spq_last_bd;
__le16 *dsb_sp_prod;
- atomic_t spq_left; /* serialize spq */
+ atomic_t cq_spq_left; /* ETH_XXX ramrods credit */
/* used to synchronize spq accesses */
spinlock_t spq_lock;
@@ -949,6 +951,7 @@ struct bnx2x {
u16 eq_prod;
u16 eq_cons;
__le16 *eq_cons_sb;
+ atomic_t eq_spq_left; /* COMMON_XXX ramrods credit */
/* Flags for marking that there is a STAT_QUERY or
SET_MAC ramrod pending */
@@ -1131,7 +1134,7 @@ struct bnx2x {
int dmae_ready;
/* used to synchronize dmae accesses */
- struct mutex dmae_mutex;
+ spinlock_t dmae_lock;
/* used to protect the FW mail box */
struct mutex fw_mb_mutex;
@@ -1447,6 +1450,12 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
void bnx2x_calc_fc_adv(struct bnx2x *bp);
int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
u32 data_hi, u32 data_lo, int common);
+
+/* Clears multicast and unicast list configuration in the chip. */
+void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp);
+void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp);
+void bnx2x_invalidate_uc_list(struct bnx2x *bp);
+
void bnx2x_update_coalesce(struct bnx2x *bp);
int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index 710ce5d..ae98f7d 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -1427,28 +1427,35 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bnx2x_set_eth_mac(bp, 1);
+ /* Clear MC configuration */
+ if (CHIP_IS_E1(bp))
+ bnx2x_invalidate_e1_mc_list(bp);
+ else
+ bnx2x_invalidate_e1h_mc_list(bp);
+
+ /* Clear UC lists configuration */
+ bnx2x_invalidate_uc_list(bp);
+
if (bp->port.pmf)
bnx2x_initial_phy_init(bp, load_mode);
+ /* Initialize Rx filtering */
+ bnx2x_set_rx_mode(bp->dev);
+
/* Start fast path */
switch (load_mode) {
case LOAD_NORMAL:
/* Tx queue should be only reenabled */
netif_tx_wake_all_queues(bp->dev);
/* Initialize the receive filter. */
- bnx2x_set_rx_mode(bp->dev);
break;
case LOAD_OPEN:
netif_tx_start_all_queues(bp->dev);
smp_mb__after_clear_bit();
- /* Initialize the receive filter. */
- bnx2x_set_rx_mode(bp->dev);
break;
case LOAD_DIAG:
- /* Initialize the receive filter. */
- bnx2x_set_rx_mode(bp->dev);
bp->state = BNX2X_STATE_DIAG;
break;
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 8cdcf5b..ea10b26 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -586,7 +586,7 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
/* lock the dmae channel */
- mutex_lock(&bp->dmae_mutex);
+ spin_lock_bh(&bp->dmae_lock);
/* reset completion */
*wb_comp = 0;
@@ -617,7 +617,7 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
unlock:
- mutex_unlock(&bp->dmae_mutex);
+ spin_unlock_bh(&bp->dmae_lock);
return rc;
}
@@ -1397,7 +1397,7 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp,
}
smp_mb__before_atomic_inc();
- atomic_inc(&bp->spq_left);
+ atomic_inc(&bp->cq_spq_left);
/* push the change in fp->state and towards the memory */
smp_wmb();
@@ -2731,11 +2731,18 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
spin_lock_bh(&bp->spq_lock);
- if (!atomic_read(&bp->spq_left)) {
- BNX2X_ERR("BUG! SPQ ring full!\n");
- spin_unlock_bh(&bp->spq_lock);
- bnx2x_panic();
- return -EBUSY;
+ if (common) {
+ if (!atomic_read(&bp->eq_spq_left)) {
+ BNX2X_ERR("BUG! EQ ring full!\n");
+ spin_unlock_bh(&bp->spq_lock);
+ bnx2x_panic();
+ return -EBUSY;
+ }
+ } else if (!atomic_read(&bp->cq_spq_left)) {
+ BNX2X_ERR("BUG! SPQ ring full!\n");
+ spin_unlock_bh(&bp->spq_lock);
+ bnx2x_panic();
+ return -EBUSY;
}
spe = bnx2x_sp_get_next(bp);
@@ -2766,20 +2773,26 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
/* stats ramrod has it's own slot on the spq */
- if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY)
+ if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) {
/* It's ok if the actual decrement is issued towards the memory
* somewhere between the spin_lock and spin_unlock. Thus no
* more explict memory barrier is needed.
*/
- atomic_dec(&bp->spq_left);
+ if (common)
+ atomic_dec(&bp->eq_spq_left);
+ else
+ atomic_dec(&bp->cq_spq_left);
+ }
+
DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
"SPQE[%x] (%x:%x) command %d hw_cid %x data (%x:%x) "
- "type(0x%x) left %x\n",
+ "type(0x%x) left (ETH, COMMON) (%x,%x)\n",
bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping),
(u32)(U64_LO(bp->spq_mapping) +
(void *)bp->spq_prod_bd - (void *)bp->spq), command,
- HW_CID(bp, cid), data_hi, data_lo, type, atomic_read(&bp->spq_left));
+ HW_CID(bp, cid), data_hi, data_lo, type,
+ atomic_read(&bp->cq_spq_left), atomic_read(&bp->eq_spq_left));
bnx2x_sp_prod_update(bp);
spin_unlock_bh(&bp->spq_lock);
@@ -3691,8 +3704,8 @@ static void bnx2x_eq_int(struct bnx2x *bp)
sw_cons = bp->eq_cons;
sw_prod = bp->eq_prod;
- DP(BNX2X_MSG_SP, "EQ: hw_cons %u sw_cons %u bp->spq_left %u\n",
- hw_cons, sw_cons, atomic_read(&bp->spq_left));
+ DP(BNX2X_MSG_SP, "EQ: hw_cons %u sw_cons %u bp->cq_spq_left %u\n",
+ hw_cons, sw_cons, atomic_read(&bp->eq_spq_left));
for (; sw_cons != hw_cons;
sw_prod = NEXT_EQ_IDX(sw_prod), sw_cons = NEXT_EQ_IDX(sw_cons)) {
@@ -3757,13 +3770,15 @@ static void bnx2x_eq_int(struct bnx2x *bp)
case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
- bp->set_mac_pending = 0;
+ if (elem->message.data.set_mac_event.echo)
+ bp->set_mac_pending = 0;
break;
case (EVENT_RING_OPCODE_SET_MAC |
BNX2X_STATE_CLOSING_WAIT4_HALT):
DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
- bp->set_mac_pending = 0;
+ if (elem->message.data.set_mac_event.echo)
+ bp->set_mac_pending = 0;
break;
default:
/* unknown event log error and continue */
@@ -3775,7 +3790,7 @@ next_spqe:
} /* for */
smp_mb__before_atomic_inc();
- atomic_add(spqe_cnt, &bp->spq_left);
+ atomic_add(spqe_cnt, &bp->eq_spq_left);
bp->eq_cons = sw_cons;
bp->eq_prod = sw_prod;
@@ -4208,7 +4223,7 @@ void bnx2x_update_coalesce(struct bnx2x *bp)
static void bnx2x_init_sp_ring(struct bnx2x *bp)
{
spin_lock_init(&bp->spq_lock);
- atomic_set(&bp->spq_left, MAX_SPQ_PENDING);
+ atomic_set(&bp->cq_spq_left, MAX_SPQ_PENDING);
bp->spq_prod_idx = 0;
bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX;
@@ -4233,6 +4248,9 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
bp->eq_cons = 0;
bp->eq_prod = NUM_EQ_DESC;
bp->eq_cons_sb = BNX2X_EQ_INDEX;
+ /* we want a warning message before it gets rought... */
+ atomic_set(&bp->eq_spq_left,
+ min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
}
static void bnx2x_init_ind_table(struct bnx2x *bp)
@@ -5838,7 +5856,7 @@ int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
BP_ABS_FUNC(bp), load_code);
bp->dmae_ready = 0;
- mutex_init(&bp->dmae_mutex);
+ spin_lock_init(&bp->dmae_lock);
rc = bnx2x_gunzip_init(bp);
if (rc)
return rc;
@@ -6173,12 +6191,14 @@ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
int ramrod_flags = WAIT_RAMROD_COMMON;
bp->set_mac_pending = 1;
- smp_wmb();
config->hdr.length = 1;
config->hdr.offset = cam_offset;
config->hdr.client_id = 0xff;
- config->hdr.reserved1 = 0;
+ /* Mark the single MAC configuration ramrod as opposed to a
+ * UC/MC list configuration).
+ */
+ config->hdr.echo = 1;
/* primary MAC */
config->config_table[0].msb_mac_addr =
@@ -6210,6 +6230,8 @@ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
config->config_table[0].middle_mac_addr,
config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
+ mb();
+
bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
U64_HI(bnx2x_sp_mapping(bp, mac_config)),
U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
@@ -6274,20 +6296,15 @@ static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset)
if (CHIP_IS_E1H(bp))
return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp);
else if (CHIP_MODE_IS_4_PORT(bp))
- return BP_FUNC(bp) * 32 + rel_offset;
+ return E2_FUNC_MAX * rel_offset + BP_FUNC(bp);
else
- return BP_VN(bp) * 32 + rel_offset;
+ return E2_FUNC_MAX * rel_offset + BP_VN(bp);
}
/**
* LLH CAM line allocations: currently only iSCSI and ETH macs are
* relevant. In addition, current implementation is tuned for a
* single ETH MAC.
- *
- * When multiple unicast ETH MACs PF configuration in switch
- * independent mode is required (NetQ, multiple netdev MACs,
- * etc.), consider better utilisation of 16 per function MAC
- * entries in the LLH memory.
*/
enum {
LLH_CAM_ISCSI_ETH_LINE = 0,
@@ -6362,14 +6379,37 @@ void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
}
}
-static void bnx2x_set_e1_mc_list(struct bnx2x *bp, u8 offset)
+
+static inline u8 bnx2x_e1_cam_mc_offset(struct bnx2x *bp)
+{
+ return CHIP_REV_IS_SLOW(bp) ?
+ (BNX2X_MAX_EMUL_MULTI * (1 + BP_PORT(bp))) :
+ (BNX2X_MAX_MULTICAST * (1 + BP_PORT(bp)));
+}
+
+/* set mc list, do not wait as wait implies sleep and
+ * set_rx_mode can be invoked from non-sleepable context.
+ *
+ * Instead we use the same ramrod data buffer each time we need
+ * to configure a list of addresses, and use the fact that the
+ * list of MACs is changed in an incremental way and that the
+ * function is called under the netif_addr_lock. A temporary
+ * inconsistent CAM configuration (possible in case of a very fast
+ * sequence of add/del/add on the host side) will shortly be
+ * restored by the handler of the last ramrod.
+ */
+static int bnx2x_set_e1_mc_list(struct bnx2x *bp)
{
int i = 0, old;
struct net_device *dev = bp->dev;
+ u8 offset = bnx2x_e1_cam_mc_offset(bp);
struct netdev_hw_addr *ha;
struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
+ if (netdev_mc_count(dev) > BNX2X_MAX_MULTICAST)
+ return -EINVAL;
+
netdev_for_each_mc_addr(ha, dev) {
/* copy mac */
config_cmd->config_table[i].msb_mac_addr =
@@ -6410,32 +6450,47 @@ static void bnx2x_set_e1_mc_list(struct bnx2x *bp, u8 offset)
}
}
+ wmb();
+
config_cmd->hdr.length = i;
config_cmd->hdr.offset = offset;
config_cmd->hdr.client_id = 0xff;
- config_cmd->hdr.reserved1 = 0;
+ /* Mark that this ramrod doesn't use bp->set_mac_pending for
+ * synchronization.
+ */
+ config_cmd->hdr.echo = 0;
- bp->set_mac_pending = 1;
- smp_wmb();
+ mb();
- bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
}
-static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp)
+
+void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp)
{
int i;
struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
int ramrod_flags = WAIT_RAMROD_COMMON;
+ u8 offset = bnx2x_e1_cam_mc_offset(bp);
- bp->set_mac_pending = 1;
- smp_wmb();
-
- for (i = 0; i < config_cmd->hdr.length; i++)
+ for (i = 0; i < BNX2X_MAX_MULTICAST; i++)
SET_FLAG(config_cmd->config_table[i].flags,
MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
T_ETH_MAC_COMMAND_INVALIDATE);
+ wmb();
+
+ config_cmd->hdr.length = BNX2X_MAX_MULTICAST;
+ config_cmd->hdr.offset = offset;
+ config_cmd->hdr.client_id = 0xff;
+ /* We'll wait for a completion this time... */
+ config_cmd->hdr.echo = 1;
+
+ bp->set_mac_pending = 1;
+
+ mb();
+
bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
@@ -6445,6 +6500,44 @@ static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp)
}
+/* Accept one or more multicasts */
+static int bnx2x_set_e1h_mc_list(struct bnx2x *bp)
+{
+ struct net_device *dev = bp->dev;
+ struct netdev_hw_addr *ha;
+ u32 mc_filter[MC_HASH_SIZE];
+ u32 crc, bit, regidx;
+ int i;
+
+ memset(mc_filter, 0, 4 * MC_HASH_SIZE);
+
+ netdev_for_each_mc_addr(ha, dev) {
+ DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
+ bnx2x_mc_addr(ha));
+
+ crc = crc32c_le(0, bnx2x_mc_addr(ha),
+ ETH_ALEN);
+ bit = (crc >> 24) & 0xff;
+ regidx = bit >> 5;
+ bit &= 0x1f;
+ mc_filter[regidx] |= (1 << bit);
+ }
+
+ for (i = 0; i < MC_HASH_SIZE; i++)
+ REG_WR(bp, MC_HASH_OFFSET(bp, i),
+ mc_filter[i]);
+
+ return 0;
+}
+
+void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp)
+{
+ int i;
+
+ for (i = 0; i < MC_HASH_SIZE; i++)
+ REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+}
+
#ifdef BCM_CNIC
/**
* Set iSCSI MAC(s) at the next enties in the CAM after the ETH
@@ -7110,20 +7203,15 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
/* Give HW time to discard old tx messages */
msleep(1);
- if (CHIP_IS_E1(bp)) {
- /* invalidate mc list,
- * wait and poll (interrupts are off)
- */
- bnx2x_invlidate_e1_mc_list(bp);
- bnx2x_set_eth_mac(bp, 0);
-
- } else {
- REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+ bnx2x_set_eth_mac(bp, 0);
- bnx2x_set_eth_mac(bp, 0);
+ bnx2x_invalidate_uc_list(bp);
- for (i = 0; i < MC_HASH_SIZE; i++)
- REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+ if (CHIP_IS_E1(bp))
+ bnx2x_invalidate_e1_mc_list(bp);
+ else {
+ bnx2x_invalidate_e1h_mc_list(bp);
+ REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
}
#ifdef BCM_CNIC
@@ -8813,12 +8901,197 @@ static int bnx2x_close(struct net_device *dev)
return 0;
}
+#define E1_MAX_UC_LIST 29
+#define E1H_MAX_UC_LIST 30
+#define E2_MAX_UC_LIST 14
+static inline u8 bnx2x_max_uc_list(struct bnx2x *bp)
+{
+ if (CHIP_IS_E1(bp))
+ return E1_MAX_UC_LIST;
+ else if (CHIP_IS_E1H(bp))
+ return E1H_MAX_UC_LIST;
+ else
+ return E2_MAX_UC_LIST;
+}
+
+
+static inline u8 bnx2x_uc_list_cam_offset(struct bnx2x *bp)
+{
+ if (CHIP_IS_E1(bp))
+ /* CAM Entries for Port0:
+ * 0 - prim ETH MAC
+ * 1 - BCAST MAC
+ * 2 - iSCSI L2 ring ETH MAC
+ * 3-31 - UC MACs
+ *
+ * Port1 entries are allocated the same way starting from
+ * entry 32.
+ */
+ return 3 + 32 * BP_PORT(bp);
+ else if (CHIP_IS_E1H(bp)) {
+ /* CAM Entries:
+ * 0-7 - prim ETH MAC for each function
+ * 8-15 - iSCSI L2 ring ETH MAC for each function
+ * 16 till 255 UC MAC lists for each function
+ *
+ * Remark: There is no FCoE support for E1H, thus FCoE related
+ * MACs are not considered.
+ */
+ return E1H_FUNC_MAX * (CAM_ISCSI_ETH_LINE + 1) +
+ bnx2x_max_uc_list(bp) * BP_FUNC(bp);
+ } else {
+ /* CAM Entries (there is a separate CAM per engine):
+ * 0-4 - prim ETH MAC for each function
+ * 4-7 - iSCSI L2 ring ETH MAC for each function
+ * 8-11 - FIP ucast L2 MAC for each function
+ * 12-15 - ALL_ENODE_MACS mcast MAC for each function
+ * 16 till 71 UC MAC lists for each function
+ */
+ u8 func_idx =
+ (CHIP_MODE_IS_4_PORT(bp) ? BP_FUNC(bp) : BP_VN(bp));
+
+ return E2_FUNC_MAX * (CAM_MAX_PF_LINE + 1) +
+ bnx2x_max_uc_list(bp) * func_idx;
+ }
+}
+
+/* set uc list, do not wait as wait implies sleep and
+ * set_rx_mode can be invoked from non-sleepable context.
+ *
+ * Instead we use the same ramrod data buffer each time we need
+ * to configure a list of addresses, and use the fact that the
+ * list of MACs is changed in an incremental way and that the
+ * function is called under the netif_addr_lock. A temporary
+ * inconsistent CAM configuration (possible in case of very fast
+ * sequence of add/del/add on the host side) will shortly be
+ * restored by the handler of the last ramrod.
+ */
+static int bnx2x_set_uc_list(struct bnx2x *bp)
+{
+ int i = 0, old;
+ struct net_device *dev = bp->dev;
+ u8 offset = bnx2x_uc_list_cam_offset(bp);
+ struct netdev_hw_addr *ha;
+ struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
+ dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+
+ if (netdev_uc_count(dev) > bnx2x_max_uc_list(bp))
+ return -EINVAL;
+
+ netdev_for_each_uc_addr(ha, dev) {
+ /* copy mac */
+ config_cmd->config_table[i].msb_mac_addr =
+ swab16(*(u16 *)&bnx2x_uc_addr(ha)[0]);
+ config_cmd->config_table[i].middle_mac_addr =
+ swab16(*(u16 *)&bnx2x_uc_addr(ha)[2]);
+ config_cmd->config_table[i].lsb_mac_addr =
+ swab16(*(u16 *)&bnx2x_uc_addr(ha)[4]);
+
+ config_cmd->config_table[i].vlan_id = 0;
+ config_cmd->config_table[i].pf_id = BP_FUNC(bp);
+ config_cmd->config_table[i].clients_bit_vector =
+ cpu_to_le32(1 << BP_L_ID(bp));
+
+ SET_FLAG(config_cmd->config_table[i].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_SET);
+
+ DP(NETIF_MSG_IFUP,
+ "setting UCAST[%d] (%04x:%04x:%04x)\n", i,
+ config_cmd->config_table[i].msb_mac_addr,
+ config_cmd->config_table[i].middle_mac_addr,
+ config_cmd->config_table[i].lsb_mac_addr);
+
+ i++;
+
+ /* Set uc MAC in NIG */
+ bnx2x_set_mac_in_nig(bp, 1, bnx2x_uc_addr(ha),
+ LLH_CAM_ETH_LINE + i);
+ }
+ old = config_cmd->hdr.length;
+ if (old > i) {
+ for (; i < old; i++) {
+ if (CAM_IS_INVALID(config_cmd->
+ config_table[i])) {
+ /* already invalidated */
+ break;
+ }
+ /* invalidate */
+ SET_FLAG(config_cmd->config_table[i].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+ }
+ }
+
+ wmb();
+
+ config_cmd->hdr.length = i;
+ config_cmd->hdr.offset = offset;
+ config_cmd->hdr.client_id = 0xff;
+ /* Mark that this ramrod doesn't use bp->set_mac_pending for
+ * synchronization.
+ */
+ config_cmd->hdr.echo = 0;
+
+ mb();
+
+ return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+ U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+
+}
+
+void bnx2x_invalidate_uc_list(struct bnx2x *bp)
+{
+ int i;
+ struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
+ dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+ int ramrod_flags = WAIT_RAMROD_COMMON;
+ u8 offset = bnx2x_uc_list_cam_offset(bp);
+ u8 max_list_size = bnx2x_max_uc_list(bp);
+
+ for (i = 0; i < max_list_size; i++) {
+ SET_FLAG(config_cmd->config_table[i].flags,
+ MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+ T_ETH_MAC_COMMAND_INVALIDATE);
+ bnx2x_set_mac_in_nig(bp, 0, NULL, LLH_CAM_ETH_LINE + 1 + i);
+ }
+
+ wmb();
+
+ config_cmd->hdr.length = max_list_size;
+ config_cmd->hdr.offset = offset;
+ config_cmd->hdr.client_id = 0xff;
+ /* We'll wait for a completion this time... */
+ config_cmd->hdr.echo = 1;
+
+ bp->set_mac_pending = 1;
+
+ mb();
+
+ bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+ U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+
+ /* Wait for a completion */
+ bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
+ ramrod_flags);
+
+}
+
+static inline int bnx2x_set_mc_list(struct bnx2x *bp)
+{
+ /* some multicasts */
+ if (CHIP_IS_E1(bp)) {
+ return bnx2x_set_e1_mc_list(bp);
+ } else { /* E1H and newer */
+ return bnx2x_set_e1h_mc_list(bp);
+ }
+}
+
/* called with netif_tx_lock from dev_mcast.c */
void bnx2x_set_rx_mode(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
u32 rx_mode = BNX2X_RX_MODE_NORMAL;
- int port = BP_PORT(bp);
if (bp->state != BNX2X_STATE_OPEN) {
DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
@@ -8829,47 +9102,16 @@ void bnx2x_set_rx_mode(struct net_device *dev)
if (dev->flags & IFF_PROMISC)
rx_mode = BNX2X_RX_MODE_PROMISC;
- else if ((dev->flags & IFF_ALLMULTI) ||
- ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
- CHIP_IS_E1(bp)))
+ else if (dev->flags & IFF_ALLMULTI)
rx_mode = BNX2X_RX_MODE_ALLMULTI;
- else { /* some multicasts */
- if (CHIP_IS_E1(bp)) {
- /*
- * set mc list, do not wait as wait implies sleep
- * and set_rx_mode can be invoked from non-sleepable
- * context
- */
- u8 offset = (CHIP_REV_IS_SLOW(bp) ?
- BNX2X_MAX_EMUL_MULTI*(1 + port) :
- BNX2X_MAX_MULTICAST*(1 + port));
-
- bnx2x_set_e1_mc_list(bp, offset);
- } else { /* E1H */
- /* Accept one or more multicasts */
- struct netdev_hw_addr *ha;
- u32 mc_filter[MC_HASH_SIZE];
- u32 crc, bit, regidx;
- int i;
-
- memset(mc_filter, 0, 4 * MC_HASH_SIZE);
-
- netdev_for_each_mc_addr(ha, dev) {
- DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
- bnx2x_mc_addr(ha));
-
- crc = crc32c_le(0, bnx2x_mc_addr(ha),
- ETH_ALEN);
- bit = (crc >> 24) & 0xff;
- regidx = bit >> 5;
- bit &= 0x1f;
- mc_filter[regidx] |= (1 << bit);
- }
+ else {
+ /* some multicasts */
+ if (bnx2x_set_mc_list(bp))
+ rx_mode = BNX2X_RX_MODE_ALLMULTI;
- for (i = 0; i < MC_HASH_SIZE; i++)
- REG_WR(bp, MC_HASH_OFFSET(bp, i),
- mc_filter[i]);
- }
+ /* some unicasts */
+ if (bnx2x_set_uc_list(bp))
+ rx_mode = BNX2X_RX_MODE_PROMISC;
}
bp->rx_mode = rx_mode;
@@ -8950,7 +9192,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
.ndo_stop = bnx2x_close,
.ndo_start_xmit = bnx2x_start_xmit,
.ndo_select_queue = bnx2x_select_queue,
- .ndo_set_multicast_list = bnx2x_set_rx_mode,
+ .ndo_set_rx_mode = bnx2x_set_rx_mode,
.ndo_set_mac_address = bnx2x_change_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = bnx2x_ioctl,
@@ -9776,15 +10018,21 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
HW_CID(bp, BNX2X_ISCSI_ETH_CID));
}
- /* There may be not more than 8 L2 and COMMON SPEs and not more
- * than 8 L5 SPEs in the air.
+ /* There may be not more than 8 L2 and not more than 8 L5 SPEs
+ * We also check that the number of outstanding
+ * COMMON ramrods is not more than the EQ and SPQ can
+ * accommodate.
*/
- if ((type == NONE_CONNECTION_TYPE) ||
- (type == ETH_CONNECTION_TYPE)) {
- if (!atomic_read(&bp->spq_left))
+ if (type == ETH_CONNECTION_TYPE) {
+ if (!atomic_read(&bp->cq_spq_left))
+ break;
+ else
+ atomic_dec(&bp->cq_spq_left);
+ } else if (type == NONE_CONNECTION_TYPE) {
+ if (!atomic_read(&bp->eq_spq_left))
break;
else
- atomic_dec(&bp->spq_left);
+ atomic_dec(&bp->eq_spq_left);
} else if ((type == ISCSI_CONNECTION_TYPE) ||
(type == FCOE_CONNECTION_TYPE)) {
if (bp->cnic_spq_pending >=
@@ -9976,7 +10224,7 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
int count = ctl->data.credit.credit_count;
smp_mb__before_atomic_inc();
- atomic_add(count, &bp->spq_left);
+ atomic_add(count, &bp->cq_spq_left);
smp_mb__after_atomic_inc();
break;
}
--
1.7.0.4
^ permalink raw reply related
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