* Re: [PATCH] net: Add DEVTYPE support for Ethernet based devices
From: Stephen Hemminger @ 2009-09-05 4:49 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: netdev, davem, johannes
In-Reply-To: <1251788899-30156-1-git-send-email-marcel@holtmann.org>
On Tue, 1 Sep 2009 00:08:19 -0700
Marcel Holtmann <marcel@holtmann.org> wrote:
> The Ethernet framing is used for a lot of devices these days. Most
> prominent are WiFi and WiMAX based devices. However for userspace
> application it is important to classify these devices correctly and
> not only see them as Ethernet devices. The daemons like HAL, DeviceKit
> or even NetworkManager with udev support tries to do the classification
> in userspace with a lot trickery and extra system calls. This is not
> good and actually reaches its limitations. Especially since the kernel
> does know the type of the Ethernet device it is pretty stupid.
>
> To solve this problem the underlying device type needs to be set and
> then the value will be exported as DEVTYPE via uevents and available
> within udev.
>
> # cat /sys/class/net/wlan0/uevent
> DEVTYPE=wlan
> INTERFACE=wlan0
> IFINDEX=5
>
The problem with your idea is that there is only a nebulous definition of
what is a Wifi device, and what is a WiMAX device etc. What userspace should be looking
for is "does device XXX support API yyy?" and if it supports API
yyy then I it can be configured that way.
There already is some information in sysfs like /sys/class/net/XXX/type
which gives the hardware type (ARPHRD_ETHER, etc). Why not a better version
of something like this that provides "can do FOO" interface?
Doing a several system calls (open/read/close) per device is not a big
issue. Even an android phone can do open/read/close in less than a millisecond
I bet.
^ permalink raw reply
* Re: [PATCH] net: Add DEVTYPE support for Ethernet based devices
From: Marcel Holtmann @ 2009-09-05 5:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev, shemminger, johannes
In-Reply-To: <20090904.214615.198838334.davem@davemloft.net>
Hi David,
> > What is ugly about it. Do you have any other recommendation on how let
> > userspace know what type of Ethernet device it is?
>
> Well, for one thing, you're wasting 48 bytes on 64-bit when all you're
> really intrested in is one string.
the integration with struct device has plenty of other advantages. You
could use all the sysfs magic from it. For example in the next step the
hacking of some sysfs directories can be moved into the subsystem itself
and could be moved out of the core. Wireless would be one of them were
we would benefit here.
> Also, you didn't setup an assignment for plain ethernet devices,
> you just handle the non-traditional devices that do ethernet
> framing. Is this intentional?
For now it is. Mainly since some non plain Ethernet devices are using
alloc_etherdev instead of just alloc_netdev. So I would have to do some
extra work. I have planned it, but not gotten around it yet.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH] net: Add DEVTYPE support for Ethernet based devices
From: David Miller @ 2009-09-05 5:55 UTC (permalink / raw)
To: marcel; +Cc: netdev, shemminger, johannes
In-Reply-To: <1252129940.27694.9.camel@violet>
From: Marcel Holtmann <marcel@holtmann.org>
Date: Sat, 05 Sep 2009 07:52:20 +0200
>> > What is ugly about it. Do you have any other recommendation on how let
>> > userspace know what type of Ethernet device it is?
>>
>> Well, for one thing, you're wasting 48 bytes on 64-bit when all you're
>> really intrested in is one string.
>
> the integration with struct device has plenty of other advantages
Ok, this I agree with.
^ permalink raw reply
* Re: [PATCH] net: Add DEVTYPE support for Ethernet based devices
From: Marcel Holtmann @ 2009-09-05 5:55 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev, davem, johannes
In-Reply-To: <20090904214903.49e5a361@nehalam>
Hi Stephen,
> > The Ethernet framing is used for a lot of devices these days. Most
> > prominent are WiFi and WiMAX based devices. However for userspace
> > application it is important to classify these devices correctly and
> > not only see them as Ethernet devices. The daemons like HAL, DeviceKit
> > or even NetworkManager with udev support tries to do the classification
> > in userspace with a lot trickery and extra system calls. This is not
> > good and actually reaches its limitations. Especially since the kernel
> > does know the type of the Ethernet device it is pretty stupid.
> >
> > To solve this problem the underlying device type needs to be set and
> > then the value will be exported as DEVTYPE via uevents and available
> > within udev.
> >
> > # cat /sys/class/net/wlan0/uevent
> > DEVTYPE=wlan
> > INTERFACE=wlan0
> > IFINDEX=5
> >
>
> The problem with your idea is that there is only a nebulous definition of
> what is a Wifi device, and what is a WiMAX device etc. What userspace should be looking
> for is "does device XXX support API yyy?" and if it supports API
> yyy then I it can be configured that way.
We don't need that. We just need to know what technology is behind that
Ethernet device. Otherwise we have no real starting point.
> There already is some information in sysfs like /sys/class/net/XXX/type
> which gives the hardware type (ARPHRD_ETHER, etc). Why not a better version
> of something like this that provides "can do FOO" interface?
that was my initial idea, but I couldn't come up with something good.
And the DEVTYPE from struct device is a standard way of exposing such
information. Actually subsystem like SCSI, USB, Bluetooth etc. use that
already. So why not do the same for Ethernet based devices.
> Doing a several system calls (open/read/close) per device is not a big
> issue. Even an android phone can do open/read/close in less than a millisecond
> I bet.
It is not only the system calls that userspace has to do. There is no
central place for this stuff and why should be do it all if the kernel
already has all the details.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH] WAN: remove deprecated PCI_DEVICE_ID from PCI200SYN driver.
From: David Miller @ 2009-09-05 6:07 UTC (permalink / raw)
To: khc; +Cc: netdev
In-Reply-To: <m363byk3af.fsf@intrepid.localdomain>
From: Krzysztof Halasa <khc@pm.waw.pl>
Date: Fri, 04 Sep 2009 19:50:16 +0200
> PCI200SYN has its own PCI subsystem device ID for 3+ years, now it's
> time to remove the generic PLX905[02] ID from the driver. Anyone with
> old EEPROM data will have to run the upgrade.
>
> Having the generic PLX905[02] (PCI-local bus bridge) ID is harmful
> as the driver tries to handle other devices based on these bridges.
Please provide a proper signoff with all patches.
Thanks.
^ permalink raw reply
* Re: net_sched 00/07: classful multiqueue dummy scheduler
From: David Miller @ 2009-09-05 7:27 UTC (permalink / raw)
To: kaber; +Cc: netdev
In-Reply-To: <20090904164111.27300.29929.sendpatchset@x2.localnet>
From: Patrick McHardy <kaber@trash.net>
Date: Fri, 4 Sep 2009 18:41:12 +0200 (MEST)
> Any comments and test results welcome :)
This looks really nice. I have them already checked into my
local net-next-2.6 tree and will push them out after I do
some multiqueue testing with NIU.
Thanks!
^ permalink raw reply
* Re: [PATCH] netlink: silence compiler warning
From: Jarek Poplawski @ 2009-09-05 7:52 UTC (permalink / raw)
To: David Miller; +Cc: brian.haley, marcel, netdev, Stephen Rothwell
In-Reply-To: <20090904.203318.112406812.davem@davemloft.net>
David Miller wrote, On 09/05/2009 05:33 AM:
> From: Brian Haley <brian.haley@hp.com>
> Date: Fri, 04 Sep 2009 21:36:06 -0400
>
>> Hi Marcel,
>>
>> Marcel Holtmann wrote:
>>> can we please add the err = -E... where it actually is needed and not
>>> stupidly go ahead and silence compiler warnings with err = 0. This has
>>> been posted before.
>> Sorry, I don't remember it being posted before. If you look at the code
>> though, err is correctly initialized, gcc just can't figure it out. The
>> choices I see are either what I originally posted, using uninitialized_var(err),
>> or the patch below. It doesn't matter to me.
>
> uninitialized_var() would be absolutely wrong here, as then we'd
> return garbage if such a path were actually possible.
If the main "thesis" of the patch is:
> From following the code 'err' is initialized, but set it to zero to
> silence the warning.
"we" should better be sure it "is initialized", so considering: "if such
a path were actually possible" "would be absolutely wrong here"...
Here is a link to the message which proved something else was possible
at some moment in -next (I didn't check the current code yet):
From: Stephen Rothwell <sfr@canb.auug.org.au>
Subject: Re: [PATCH] Fix Warnings from net/netlink/genetlink.c
Date: Wed, 12 Aug 2009 13:50:31 +1000
Archived-At: http://permalink.gmane.org/gmane.linux.kernel.next/8786
Jarek P.
^ permalink raw reply
* Re: [PATCH] netlink: silence compiler warning
From: David Miller @ 2009-09-05 8:13 UTC (permalink / raw)
To: jarkao2; +Cc: brian.haley, marcel, netdev, sfr
In-Reply-To: <4AA218C8.4050800@gmail.com>
From: Jarek Poplawski <jarkao2@gmail.com>
Date: Sat, 05 Sep 2009 09:52:40 +0200
> http://permalink.gmane.org/gmane.linux.kernel.next/8786
Right, and that was my thinking. So setting it to zero to
begin with is the right thing to do.
^ permalink raw reply
* Re: net_sched 02/07: make cls_ops->tcf_chain() optional
From: Jarek Poplawski @ 2009-09-05 8:13 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netdev
In-Reply-To: <20090904164113.27300.79145.sendpatchset@x2.localnet>
Patrick McHardy wrote, On 09/04/2009 06:41 PM:
> commit 6ea4233ef8f398289a14a3305d4ed440fb026d43
> Author: Patrick McHardy <kaber@trash.net>
> Date: Fri Sep 4 14:28:11 2009 +0200
>
> net_sched: make cls_ops->tcf_chain() optional
>
> Some qdiscs don't support attaching filters. Handle this centrally in
> cls_api and return a proper errno code (EOPNOTSUPP) instead of EINVAL.
>
> Signed-off-by: Patrick McHardy <kaber@trash.net>
>
> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
> index 09cdcdf..eaa8f43 100644
> --- a/net/sched/cls_api.c
> +++ b/net/sched/cls_api.c
> @@ -181,6 +181,9 @@ replay:
> if ((cops = q->ops->cl_ops) == NULL)
> return -EINVAL;
>
> + if (cops->tcf_chain == NULL)
> + return -EOPNOTSUPP;
> +
You should probably repeat this in tc_dump_tfilter.
Jarek P.
^ permalink raw reply
* Re: [PATCH] WAN: remove deprecated PCI_DEVICE_ID from PCI200SYN driver.
From: Krzysztof Halasa @ 2009-09-05 10:52 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20090904.230740.247551288.davem@davemloft.net>
David Miller <davem@davemloft.net> writes:
> Please provide a proper signoff with all patches.
Oops. Sure.
--
Krzysztof Halasa
^ permalink raw reply
* [PATCH] WAN: remove deprecated PCI_DEVICE_ID from PCI200SYN driver.
From: Krzysztof Halasa @ 2009-09-05 10:54 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <m363byk3af.fsf@intrepid.localdomain>
PCI200SYN has its own PCI subsystem device ID for 3+ years, now it's
time to remove the generic PLX905[02] ID from the driver. Anyone with
old EEPROM data will have to run the upgrade.
Having the generic PLX905[02] (PCI-local bus bridge) ID is harmful
as the driver tries to handle other devices based on these bridges.
Signed-off-by: Krzysztof Halasa <khc@pm.waw.pl>
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -360,15 +360,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
" %u RX packets rings\n", ramsize / 1024, ramphys,
pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
- if (pdev->subsystem_device == PCI_DEVICE_ID_PLX_9050) {
- printk(KERN_ERR "Detected PCI200SYN card with old "
- "configuration data.\n");
- printk(KERN_ERR "See <http://www.kernel.org/pub/"
- "linux/utils/net/hdlc/pci200syn/> for update.\n");
- printk(KERN_ERR "The card will stop working with"
- " future versions of Linux if not updated.\n");
- }
-
if (card->tx_ring_buffers < 1) {
printk(KERN_ERR "pci200syn: RAM test failed\n");
pci200_pci_remove_one(pdev);
@@ -427,8 +418,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
static struct pci_device_id pci200_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
- PCI_DEVICE_ID_PLX_9050, 0, 0, 0 },
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 },
{ 0, }
};
--
Krzysztof Halasa
^ permalink raw reply
* Re: [PATCH net-next] wan: dlci/sdla transmit return dehacking
From: Krzysztof Halasa @ 2009-09-05 11:09 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, sfr, linux-next, netdev
In-Reply-To: <20090904193810.46543e3c@nehalam>
Stephen Hemminger <shemminger@vyatta.com> writes:
> In the Vyatta product we use the Sangoma drivers, so we actually have
> to make and not configure in the existing WAN drivers.
I'd expect all users of their hw are doing precisely the same (not to
imply there are any S5* (ISA) cards still in use).
But I don't know for sure, sometimes people use really old and long
unmaintained drivers with success. OTOH ISA...
--
Krzysztof Halasa
^ permalink raw reply
* Re: net_sched 02/07: make cls_ops->tcf_chain() optional
From: Jarek Poplawski @ 2009-09-05 11:57 UTC (permalink / raw)
Cc: Patrick McHardy, netdev
In-Reply-To: <4AA21D9F.8090600@gmail.com>
Jarek Poplawski wrote, On 09/05/2009 10:13 AM:
> Patrick McHardy wrote, On 09/04/2009 06:41 PM:
>
>> commit 6ea4233ef8f398289a14a3305d4ed440fb026d43
>> Author: Patrick McHardy <kaber@trash.net>
>> Date: Fri Sep 4 14:28:11 2009 +0200
>>
>> net_sched: make cls_ops->tcf_chain() optional
>>
>> Some qdiscs don't support attaching filters. Handle this centrally in
>> cls_api and return a proper errno code (EOPNOTSUPP) instead of EINVAL.
>>
>> Signed-off-by: Patrick McHardy <kaber@trash.net>
>>
>> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
>> index 09cdcdf..eaa8f43 100644
>> --- a/net/sched/cls_api.c
>> +++ b/net/sched/cls_api.c
>> @@ -181,6 +181,9 @@ replay:
>> if ((cops = q->ops->cl_ops) == NULL)
>> return -EINVAL;
>>
>> + if (cops->tcf_chain == NULL)
>> + return -EOPNOTSUPP;
>> +
>
>
> You should probably repeat this in tc_dump_tfilter.
...In case somebody finds the way to list a filter before
adding it. ;-) But, since it's quite unlikely, let's foget it.
Sorry,
Jarek P.
^ permalink raw reply
* Re: [PATCH] atm: dereference of he_dev->rbps_virt in he_init_group()
From: Roel Kluin @ 2009-09-05 12:35 UTC (permalink / raw)
To: David Miller; +Cc: chas, linux-atm-general, netdev, akpm
In-Reply-To: <20090902.232548.238393942.davem@davemloft.net>
he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail, so check
them. Make sure that he_init_group() cleans up after errors.
Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
> These new return statements will both leak resources allocated
> earlier.
>
> All the caller is going to do is return -ENOMEM as well and
> it does not cleanup actions at all.
>
> Please fix this up.
I am new to this api, so please review.
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 2de6406..1d873cb 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -777,7 +777,7 @@ he_init_cs_block_rcm(struct he_dev *he_dev)
static int __devinit
he_init_group(struct he_dev *he_dev, int group)
{
- int i;
+ int i, ret;
/* small buffer pool */
he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
@@ -790,19 +790,27 @@ he_init_group(struct he_dev *he_dev, int group)
he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
if (he_dev->rbps_base == NULL) {
- hprintk("failed to alloc rbps\n");
- return -ENOMEM;
+ hprintk("failed to alloc rbps_base\n");
+ ret = -ENOMEM;
+ goto out_destroy_rbps_pool;
}
memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+ if (he_dev->rbps_virt == NULL) {
+ hprintk("failed to alloc rbps_virt\n");
+ ret = -ENOMEM;
+ goto out_free_rbps_base;
+ }
for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
dma_addr_t dma_handle;
void *cpuaddr;
cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
- if (cpuaddr == NULL)
- return -ENOMEM;
+ if (cpuaddr == NULL) {
+ ret = -ENOMEM;
+ goto out_free_rbps_virt;
+ }
he_dev->rbps_virt[i].virt = cpuaddr;
he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
@@ -827,25 +835,34 @@ he_init_group(struct he_dev *he_dev, int group)
CONFIG_RBPL_BUFSIZE, 8, 0);
if (he_dev->rbpl_pool == NULL) {
hprintk("unable to create rbpl pool\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_free_rbps_virt;
}
he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
if (he_dev->rbpl_base == NULL) {
- hprintk("failed to alloc rbpl\n");
- return -ENOMEM;
+ hprintk("failed to alloc rbpl_base\n");
+ ret = -ENOMEM;
+ goto out_destroy_rbpl_pool;
}
memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
+ if (he_dev->rbpl_virt == NULL) {
+ hprintk("failed to alloc rbpl_virt\n");
+ ret = -ENOMEM;
+ goto out_free_rbpl_base;
+ }
for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
dma_addr_t dma_handle;
void *cpuaddr;
cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
- if (cpuaddr == NULL)
- return -ENOMEM;
+ if (cpuaddr == NULL) {
+ ret = -ENOMEM;
+ goto out_free_rbpl_virt;
+ }
he_dev->rbpl_virt[i].virt = cpuaddr;
he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
@@ -870,7 +887,8 @@ he_init_group(struct he_dev *he_dev, int group)
CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
if (he_dev->rbrq_base == NULL) {
hprintk("failed to allocate rbrq\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_free_rbpl_virt;
}
memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
@@ -894,7 +912,8 @@ he_init_group(struct he_dev *he_dev, int group)
CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
if (he_dev->tbrq_base == NULL) {
hprintk("failed to allocate tbrq\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_free_rbpq_base;
}
memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
@@ -906,6 +925,34 @@ he_init_group(struct he_dev *he_dev, int group)
he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
return 0;
+
+out_free_rbpq_base:
+ pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
+ he_dev->rbrq_base, he_dev->rbrq_phys);
+ i = CONFIG_RBPL_SIZE;
+out_free_rbpl_virt:
+ while (--i)
+ pci_pool_free(he_dev->rbpl_virt[i].virt);
+ kfree(he_dev->rbpl_virt);
+
+out_free_rbpl_base:
+ pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
+ he_dev->rbpl_base, he_dev->rbpl_phys);
+out_destroy_rbpl_pool:
+ pci_pool_destroy(he_dev->rbpl_pool);
+
+ i = CONFIG_RBPL_SIZE;
+out_free_rbps_virt:
+ while (--i)
+ pci_pool_free(he_dev->rbps_virt[i].virt);
+ kfree(he_dev->rbps_virt);
+
+out_free_rbps_base:
+ pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE * sizeof(struct he_rbp),
+ he_dev->rbps_base, he_dev->rbps_phys);
+out_destroy_rbps_pool:
+ pci_pool_destroy(he_dev->rbps_pool);
+ return ret;
}
static int __devinit
^ permalink raw reply related
* Re: net_sched 02/07: make cls_ops->tcf_chain() optional
From: Jarek Poplawski @ 2009-09-05 12:32 UTC (permalink / raw)
Cc: Patrick McHardy, netdev
In-Reply-To: <4AA2520D.2060603@gmail.com>
Jarek Poplawski wrote, On 09/05/2009 01:57 PM:
> Jarek Poplawski wrote, On 09/05/2009 10:13 AM:
>
>> Patrick McHardy wrote, On 09/04/2009 06:41 PM:
>>
>>> commit 6ea4233ef8f398289a14a3305d4ed440fb026d43
>>> Author: Patrick McHardy <kaber@trash.net>
>>> Date: Fri Sep 4 14:28:11 2009 +0200
>>>
>>> net_sched: make cls_ops->tcf_chain() optional
>>>
>>> Some qdiscs don't support attaching filters. Handle this centrally in
>>> cls_api and return a proper errno code (EOPNOTSUPP) instead of EINVAL.
>>>
>>> Signed-off-by: Patrick McHardy <kaber@trash.net>
>>>
>>> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
>>> index 09cdcdf..eaa8f43 100644
>>> --- a/net/sched/cls_api.c
>>> +++ b/net/sched/cls_api.c
>>> @@ -181,6 +181,9 @@ replay:
>>> if ((cops = q->ops->cl_ops) == NULL)
>>> return -EINVAL;
>>>
>>> + if (cops->tcf_chain == NULL)
>>> + return -EOPNOTSUPP;
>>> +
>>
>> You should probably repeat this in tc_dump_tfilter.
>
>
> ...In case somebody finds the way to list a filter before
> adding it. ;-) But, since it's quite unlikely, let's foget it.
...or simply tries to do it instead of meditating the code.
So this change is definitely needed in tc_dump_tfilter too.
Sorry to myself,
Jarek P.
^ permalink raw reply
* Staging: cpc-usb CAN driver TODO list
From: Oliver Hartkopp @ 2009-09-05 13:08 UTC (permalink / raw)
To: Greg KH, Sebastian Haas
Cc: Linux Netdev List, Felipe Balbi, Wolfgang Grandegger
Hello Greg and Sebastian,
i just looked around in the linux-next tree for the cpc-usb driver.
http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=tree;f=drivers/staging/cpc-usb;hb=HEAD
IMHO the sja2m16c* files are completely obsolete as the setting of the CAN
bittimings needs to be done by separate functions (one for the SJA1000 and one
for the M16C). For both of them a separate can_bittiming_const is needed, like
it is defined in drivers/net/can/sja1000/sja1000.c:
static struct can_bittiming_const sja1000_bittiming_const = {
.name = DRV_NAME,
.tseg1_min = 1,
.tseg1_max = 16,
.tseg2_min = 1,
.tseg2_max = 8,
.sjw_max = 4,
.brp_min = 1,
.brp_max = 64,
.brp_inc = 1,
};
Also a separate function to determine the register values from the calculated
bittiming values is needed for both hardware types (SJA1000(LPC2119)/M16C) of
the cpc-usb. How this is done can be checked in linux/drivers/net/can/* or in
the source code of upcoming drivers in
http://svn.berlios.de/svnroot/repos/socketcan/trunk/kernel/2.6/drivers/net/can/
I wondered about the following items in the TODO list:
- tie into CAN socket interfaces if possible
- figure out sane userspace api
This is definitely a no go! IMO there is no real alternative to make this
cpc-usb driver a real CAN network driver.
The CAN driver interface has a sane configuration API via netlink and brings
everything to configure CAN specific bitrates, error counters, recovery, etc.
The missing thing is to connect the usb-device to a netdevice (can%d), remove
all the chardev file-I/O stuff and adapt the cpc-usb to use the
bitrate-settings, error counters and whatever - which is already well-defined
and provided by the CAN driver interface library contributed by Wolfgang
Grandegger ( drivers/net/can/dev.c and include/linux/can/[dev.h|netlink.h] ).
Unfortunately i'm not an expert in USB programming and i don't have that
hardware - but if you need some ideas from the CAN driver peoples like
Wolfgang, questions are always welcome, e.g. on the socketcan-core ML:
http://developer.berlios.de/projects/socketcan
I don't think it's a big effort for people that know USB & CAN to clean up the
cpc-usb and make it a slim CAN netdev. Believe me, it took years to figure out
a sane userspace api for CAN interfaces, which is now provided by the netlink
interface ;-)
Best regards,
Oliver
^ permalink raw reply
* [PATCH] IXP42x HSS support for setting internal clock rate
From: Krzysztof Halasa @ 2009-09-05 13:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
HSS usually uses external clocks, so it's not a big deal. Internal clock
is used for direct DTE-DTE connections and when the DCE doesn't provide
it's own clock.
This also depends on the oscillator frequency. Intel seems to have
calculated the clock register settings for 33.33 MHz (66.66 MHz timer
base). Their settings seem quite suboptimal both in terms of average
frequency (60 ppm is unacceptable for G.703 applications, their primary
intended usage(?)) and jitter.
Many (most?) platforms use a 33.333 MHz oscillator, a 10 ppm difference
from Intel's base.
Instead of creating static tables, I've created a procedure to program
the HSS clock register. The register consists of 3 parts (A, B, C).
The average frequency (= bit rate) is:
66.66x MHz / (A + (B + 1) / (C + 1))
The procedure aims at the closest average frequency, possibly at the
cost of increased jitter. Nobody would be able to directly drive an
unbufferred transmitter with a HSS anyway, and the frequency error is
what it really counts.
I've verified the above with an oscilloscope on IXP425. It seems IXP46x
and possibly IXP43x use a bit different clock generation algorithm - it
looks like the avg frequency is:
(on IXP465) 66.66x MHz / (A + B / (C + 1)).
Also they use much greater precomputed A and B - on IXP425 it would
simply result in more jitter, but I don't know how does it work on
IXP46x (perhaps 3 least significant bits aren't used?).
Anyway it looks that they were aiming for exactly +60 ppm or -60 ppm,
while <1 ppm is typically possible (with a synchronized clock, of
course).
The attached patch makes it possible to set almost any bit rate
(my IXP425 533 MHz quits at > 22 Mb/s if a single port is used, and the
minimum is ca. 65 Kb/s).
This is independent of MVIP (multi-E1/T1 on one HSS) mode.
Signed-off-by: Krzysztof Hałasa <khc@pm.waw.pl>
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 1e93dfe..5083f03 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -416,6 +416,7 @@ static struct clocksource clocksource_ixp4xx = {
};
unsigned long ixp4xx_timer_freq = FREQ;
+EXPORT_SYMBOL(ixp4xx_timer_freq);
static int __init ixp4xx_clocksource_init(void)
{
clocksource_ixp4xx.mult =
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index bb719b6..c705046 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -166,6 +166,29 @@
#define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023)
#define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047)
+/*
+ * HSS_CONFIG_CLOCK_CR register consists of 3 parts:
+ * A (10 bits), B (10 bits) and C (12 bits).
+ * IXP42x HSS clock generator operation (verified with an oscilloscope):
+ * Each clock bit takes 7.5 ns (1 / 133.xx MHz).
+ * The clock sequence consists of (C - B) states of 0s and 1s, each state is
+ * A bits wide. It's followed by (B + 1) states of 0s and 1s, each state is
+ * (A + 1) bits wide.
+ *
+ * The resulting average clock frequency (assuming 33.333 MHz oscillator) is:
+ * freq = 66.666 MHz / (A + (B + 1) / (C + 1))
+ * minumum freq = 66.666 MHz / (A + 1)
+ * maximum freq = 66.666 MHz / A
+ *
+ * Example: A = 2, B = 2, C = 7, CLOCK_CR register = 2 << 22 | 2 << 12 | 7
+ * freq = 66.666 MHz / (2 + (2 + 1) / (7 + 1)) = 28.07 MHz (Mb/s).
+ * The clock sequence is: 1100110011 (5 doubles) 000111000 (3 triples).
+ * The sequence takes (C - B) * A + (B + 1) * (A + 1) = 5 * 2 + 3 * 3 bits
+ * = 19 bits (each 7.5 ns long) = 142.5 ns (then the sequence repeats).
+ * The sequence consists of 4 complete clock periods, thus the average
+ * frequency (= clock rate) is 4 / 142.5 ns = 28.07 MHz (Mb/s).
+ * (max specified clock rate for IXP42x HSS is 8.192 Mb/s).
+ */
/* hss_config, LUT entries */
#define TDMMAP_UNASSIGNED 0
@@ -239,6 +262,7 @@ struct port {
unsigned int clock_type, clock_rate, loopback;
unsigned int initialized, carrier;
u8 hdlc_cfg;
+ u32 clock_reg;
};
/* NPE message structure */
@@ -393,7 +417,7 @@ static void hss_config(struct port *port)
msg.cmd = PORT_CONFIG_WRITE;
msg.hss_port = port->id;
msg.index = HSS_CONFIG_CLOCK_CR;
- msg.data32 = CLK42X_SPEED_2048KHZ /* FIXME */;
+ msg.data32 = port->clock_reg;
hss_npe_send(port, &msg, "HSS_SET_CLOCK_CR");
memset(&msg, 0, sizeof(msg));
@@ -1160,6 +1184,62 @@ static int hss_hdlc_attach(struct net_device *dev, unsigned short encoding,
}
}
+static u32 check_clock(u32 rate, u32 a, u32 b, u32 c,
+ u32 *best, u32 *best_diff, u32 *reg)
+{
+ /* a is 10-bit, b is 10-bit, c is 12-bit */
+ u64 new_rate;
+ u32 new_diff;
+
+ new_rate = ixp4xx_timer_freq * (u64)(c + 1);
+ do_div(new_rate, a * (c + 1) + b + 1);
+ new_diff = abs((u32)new_rate - rate);
+
+ if (new_diff < *best_diff) {
+ *best = new_rate;
+ *best_diff = new_diff;
+ *reg = (a << 22) | (b << 12) | c;
+ }
+ return new_diff;
+}
+
+static void find_best_clock(u32 rate, u32 *best, u32 *reg)
+{
+ u32 a, b, diff = 0xFFFFFFFF;
+
+ a = ixp4xx_timer_freq / rate;
+
+ if (a > 0x3FF) { /* 10-bit value - we can go as slow as ca. 65 kb/s */
+ check_clock(rate, 0x3FF, 1, 1, best, &diff, reg);
+ return;
+ }
+ if (a == 0) { /* > 66.666 MHz */
+ a = 1; /* minimum divider is 1 (a = 0, b = 1, c = 1) */
+ rate = ixp4xx_timer_freq;
+ }
+
+ if (rate * a == ixp4xx_timer_freq) { /* don't divide by 0 later */
+ check_clock(rate, a - 1, 1, 1, best, &diff, reg);
+ return;
+ }
+
+ for (b = 0; b < 0x400; b++) {
+ u64 c = (b + 1) * (u64)rate;
+ do_div(c, ixp4xx_timer_freq - rate * a);
+ c--;
+ if (c >= 0xFFF) { /* 12-bit - no need to check more 'b's */
+ if (b == 0 && /* also try a bit higher rate */
+ !check_clock(rate, a - 1, 1, 1, best, &diff, reg))
+ return;
+ check_clock(rate, a, b, 0xFFF, best, &diff, reg);
+ return;
+ }
+ if (!check_clock(rate, a, b, c, best, &diff, reg))
+ return;
+ if (!check_clock(rate, a, b, c + 1, best, &diff, reg))
+ return;
+ }
+}
static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -1182,7 +1262,7 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
memset(&new_line, 0, sizeof(new_line));
new_line.clock_type = port->clock_type;
- new_line.clock_rate = 2048000; /* FIXME */
+ new_line.clock_rate = port->clock_rate;
new_line.loopback = port->loopback;
if (copy_to_user(line, &new_line, size))
return -EFAULT;
@@ -1206,7 +1286,13 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EINVAL;
port->clock_type = clk; /* Update settings */
- /* FIXME port->clock_rate = new_line.clock_rate */;
+ if (clk == CLOCK_INT)
+ find_best_clock(new_line.clock_rate, &port->clock_rate,
+ &port->clock_reg);
+ else {
+ port->clock_rate = 0;
+ port->clock_reg = CLK42X_SPEED_2048KHZ;
+ }
port->loopback = new_line.loopback;
spin_lock_irqsave(&npe_lock, flags);
@@ -1266,7 +1352,8 @@ static int __devinit hss_init_one(struct platform_device *pdev)
dev->netdev_ops = &hss_hdlc_ops;
dev->tx_queue_len = 100;
port->clock_type = CLOCK_EXT;
- port->clock_rate = 2048000;
+ port->clock_rate = 0;
+ port->clock_reg = CLK42X_SPEED_2048KHZ;
port->id = pdev->id;
port->dev = &pdev->dev;
port->plat = pdev->dev.platform_data;
--
Krzysztof Halasa
^ permalink raw reply related
* Re: ipw2200: firmware DMA loading rework
From: Theodore Tso @ 2009-09-05 14:28 UTC (permalink / raw)
To: Mel Gorman
Cc: Luis R. Rodriguez, Bartlomiej Zolnierkiewicz, Aneesh Kumar K.V,
Zhu Yi, Andrew Morton, Johannes Weiner, Pekka Enberg,
Rafael J. Wysocki, Linux Kernel Mailing List, Kernel Testers List,
Mel Gorman, netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org, James Ketrenos,
Chatre, Reinette,
linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
ipw2100-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
In-Reply-To: <20090903124913.GA26110-wPRd99KPJ+uzQB+pC5nmwQ@public.gmane.org>
On Thu, Sep 03, 2009 at 01:49:14PM +0100, Mel Gorman wrote:
> >
> > This looks very similar to the kmemleak ext4 reports upon a mount. If
> > it is the same issue, which from the trace it seems it is, then this
> > is due to an extra kmalloc() allocation and this apparently will not
> > get fixed on 2.6.31 due to the closeness of the merge window and the
> > non-criticalness this issue has been deemed.
No, it's a different problem.
> I suspect the more pressing concern is why is this kmalloc() resulting in
> an order-5 allocation request? What size is the buffer being requested?
> Was that expected? What is the contents of /proc/slabinfo in case a buffer
> that should have required order-1 or order-2 is using a higher order for
> some reason.
It's allocating 68,000 bytes for the mb_history structure, which is
used for debugging purposes. That's why it's optional and we continue
if it's not allocated. We should fix it to use vmalloc() and I'm
inclined to turn it off by default since it's not worth the overhead,
and most ext4 users won't find it useful or interesting.
- Ted
^ permalink raw reply
* Re: net_sched 00/07: classful multiqueue dummy scheduler
From: Patrick McHardy @ 2009-09-05 17:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20090905.002705.16361217.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 405 bytes --]
David Miller wrote:
> From: Patrick McHardy <kaber@trash.net>
> Date: Fri, 4 Sep 2009 18:41:12 +0200 (MEST)
>
>> Any comments and test results welcome :)
>
> This looks really nice. I have them already checked into my
> local net-next-2.6 tree and will push them out after I do
> some multiqueue testing with NIU.
Thanks. Attached is a small fix on top hat fixes inverted logic
in mq_destroy().
[-- Attachment #2: x --]
[-- Type: text/plain, Size: 417 bytes --]
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index 5e453fd..c84dec9 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -26,7 +26,7 @@ static void mq_destroy(struct Qdisc *sch)
struct mq_sched *priv = qdisc_priv(sch);
unsigned int ntx;
- if (priv->qdiscs)
+ if (!priv->qdiscs)
return;
for (ntx = 0; ntx < dev->num_tx_queues && priv->qdiscs[ntx]; ntx++)
qdisc_destroy(priv->qdiscs[ntx]);
^ permalink raw reply related
* Re: net_sched 02/07: make cls_ops->tcf_chain() optional
From: Patrick McHardy @ 2009-09-05 17:03 UTC (permalink / raw)
To: Jarek Poplawski; +Cc: netdev
In-Reply-To: <4AA25A51.2040100@gmail.com>
Jarek Poplawski wrote:
> Jarek Poplawski wrote, On 09/05/2009 01:57 PM:
>
>>>> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
>>>> index 09cdcdf..eaa8f43 100644
>>>> --- a/net/sched/cls_api.c
>>>> +++ b/net/sched/cls_api.c
>>>> @@ -181,6 +181,9 @@ replay:
>>>> if ((cops = q->ops->cl_ops) == NULL)
>>>> return -EINVAL;
>>>>
>>>> + if (cops->tcf_chain == NULL)
>>>> + return -EOPNOTSUPP;
>>>> +
>>> You should probably repeat this in tc_dump_tfilter.
>>
>>
>> ...In case somebody finds the way to list a filter before
>> adding it. ;-) But, since it's quite unlikely, let's foget it.
>
>
> ...or simply tries to do it instead of meditating the code.
> So this change is definitely needed in tc_dump_tfilter too.
Thanks Jarek. I'm on my way out the door, but I'll fix that tommorrow.
^ permalink raw reply
* [PATCH NEXT 1/6] netxen: handle firmware load errors
From: Dhananjay Phadke @ 2009-09-06 3:43 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1252208592-2240-1-git-send-email-dhananjay@netxen.com>
Unwind allocations and release file firmware when
when firmware load fails.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
---
drivers/net/netxen/netxen_nic_hw.c | 3 +++
drivers/net/netxen/netxen_nic_init.c | 1 +
drivers/net/netxen/netxen_nic_main.c | 20 ++++++++++++++++----
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index db510ce..d0ac8fa 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -566,6 +566,9 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
i = 0;
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return -EIO;
+
tx_ring = adapter->tx_ring;
__netif_tx_lock_bh(tx_ring->txq);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 04e36f2..534994d 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -905,6 +905,7 @@ netxen_release_firmware(struct netxen_adapter *adapter)
{
if (adapter->fw)
release_firmware(adapter->fw);
+ adapter->fw = NULL;
}
int netxen_init_dummy_dma(struct netxen_adapter *adapter)
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 41b2967..47aede6 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -757,7 +757,7 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
err = netxen_need_fw_reset(adapter);
if (err < 0)
- return err;
+ goto err_out;
if (err == 0)
goto wait_init;
@@ -771,7 +771,9 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
netxen_set_port_mode(adapter);
- netxen_load_firmware(adapter);
+ err = netxen_load_firmware(adapter);
+ if (err)
+ goto err_out;
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
@@ -785,7 +787,7 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
err = netxen_init_dummy_dma(adapter);
if (err)
- return err;
+ goto err_out;
/*
* Tell the hardware our version number.
@@ -800,7 +802,7 @@ wait_init:
err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
if (err) {
netxen_free_dummy_dma(adapter);
- return err;
+ goto err_out;
}
nx_update_dma_mask(adapter);
@@ -808,6 +810,10 @@ wait_init:
netxen_nic_get_firmware_info(adapter);
return 0;
+
+err_out:
+ netxen_release_firmware(adapter);
+ return err;
}
static int
@@ -876,6 +882,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
{
int err;
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return -EIO;
+
err = adapter->init_port(adapter, adapter->physical_port);
if (err) {
printk(KERN_ERR "%s: Failed to initialize port %d\n",
@@ -914,6 +923,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
static void
netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
{
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return;
+
spin_lock(&adapter->tx_clean_lock);
netif_carrier_off(netdev);
netif_tx_disable(netdev);
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 0/6] nexten: fixes and enhancements
From: Dhananjay Phadke @ 2009-09-06 3:43 UTC (permalink / raw)
To: davem; +Cc: netdev
Series of 6 driver enhancements / fixes, please apply to net-next-2.6.
Thanks,
Dhananjay
^ permalink raw reply
* [PATCH NEXT 3/6] netxen: fix ip addr hashing after firmware reset
From: Dhananjay Phadke @ 2009-09-06 3:43 UTC (permalink / raw)
To: davem; +Cc: netdev, Amit Kumar Salecha
In-Reply-To: <1252208592-2240-1-git-send-email-dhananjay@netxen.com>
From: Amit Kumar Salecha <amit@netxen.com>
Reprogram local IP addresses after firmware is reset
or after resuming from suspend.
Signed-off-by: Amit Kumar Salecha <amit@netxen.com>
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
---
drivers/net/netxen/netxen_nic_main.c | 61 +++++++++++++++++++++------------
1 files changed, 39 insertions(+), 22 deletions(-)
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 4989436..7038e1b 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -86,6 +86,8 @@ static irqreturn_t netxen_intr(int irq, void *data);
static irqreturn_t netxen_msi_intr(int irq, void *data);
static irqreturn_t netxen_msix_intr(int irq, void *data);
+static void netxen_config_indev_addr(struct net_device *dev, unsigned long);
+
/* PCI Device ID Table */
#define ENTRY(device) \
{PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \
@@ -1411,6 +1413,8 @@ netxen_nic_resume(struct pci_dev *pdev)
goto err_out_detach;
netif_device_attach(netdev);
+
+ netxen_config_indev_addr(netdev, NETDEV_UP);
}
netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
@@ -2057,6 +2061,7 @@ netxen_attach_work(struct work_struct *work)
goto done;
}
+ netxen_config_indev_addr(netdev, NETDEV_UP);
}
netif_device_attach(netdev);
@@ -2282,12 +2287,43 @@ netxen_destip_supported(struct netxen_adapter *adapter)
return 1;
}
+static void
+netxen_config_indev_addr(struct net_device *dev, unsigned long event)
+{
+ struct in_device *indev;
+ struct netxen_adapter *adapter = netdev_priv(dev);
+
+ if (netxen_destip_supported(adapter))
+ return;
+
+ indev = in_dev_get(dev);
+ if (!indev)
+ return;
+
+ for_ifa(indev) {
+ switch (event) {
+ case NETDEV_UP:
+ netxen_config_ipaddr(adapter,
+ ifa->ifa_address, NX_IP_UP);
+ break;
+ case NETDEV_DOWN:
+ netxen_config_ipaddr(adapter,
+ ifa->ifa_address, NX_IP_DOWN);
+ break;
+ default:
+ break;
+ }
+ } endfor_ifa(indev);
+
+ in_dev_put(indev);
+ return;
+}
+
static int netxen_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct netxen_adapter *adapter;
struct net_device *dev = (struct net_device *)ptr;
- struct in_device *indev;
recheck:
if (dev == NULL)
@@ -2303,32 +2339,13 @@ recheck:
adapter = netdev_priv(dev);
- if (!adapter || !netxen_destip_supported(adapter))
+ if (!adapter)
goto done;
if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
goto done;
- indev = in_dev_get(dev);
- if (!indev)
- goto done;
-
- for_ifa(indev) {
- switch (event) {
- case NETDEV_UP:
- netxen_config_ipaddr(adapter,
- ifa->ifa_address, NX_IP_UP);
- break;
- case NETDEV_DOWN:
- netxen_config_ipaddr(adapter,
- ifa->ifa_address, NX_IP_DOWN);
- break;
- default:
- break;
- }
- } endfor_ifa(indev);
-
- in_dev_put(indev);
+ netxen_config_indev_addr(dev, event);
done:
return NOTIFY_DONE;
}
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 2/6] netxen: firmware hang detection
From: Dhananjay Phadke @ 2009-09-06 3:43 UTC (permalink / raw)
To: davem; +Cc: netdev, Amit Kumar Salecha
In-Reply-To: <1252208592-2240-1-git-send-email-dhananjay@netxen.com>
Implement state machine to detect firmware hung state
and recover. Since firmware will be shared by all PCI
functions that have different class drivers (NIC or
FCOE or iSCSI), explicit hardware based serialization
is required for initializing firmware.
o Used global scratchpad register to maintain device
reference count. Every probed pci function adds to
ref count.
o Implement timer (delayed work) for each pci func
that checks firmware heartbit every 5 sec and detaches
itself if firmware is dead. Last detaching function
reloads firmware. Other functions wait for firmware
init, and re-attach themselves.
Heartbit is not supported by NX2031 firmware.
Signed-off-by: Amit Kumar Salecha <amit@netxen.com>
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
---
drivers/net/netxen/netxen_nic.h | 17 ++-
drivers/net/netxen/netxen_nic_ctx.c | 8 +
drivers/net/netxen/netxen_nic_hdr.h | 23 ++
drivers/net/netxen/netxen_nic_main.c | 388 ++++++++++++++++++++++++++--------
4 files changed, 348 insertions(+), 88 deletions(-)
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index ede2fa7..30a3816 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -229,6 +229,8 @@
#define MPORT_SINGLE_FUNCTION_MODE 0x1111
#define MPORT_MULTI_FUNCTION_MODE 0x2222
+#define NX_MAX_PCI_FUNC 8
+
/*
* NetXen host-peg signal message structure
*
@@ -1101,6 +1103,10 @@ typedef struct {
#define NETXEN_ADAPTER_UP_MAGIC 777
#define NETXEN_NIC_PEG_TUNE 0
+#define __NX_FW_ATTACHED 0
+#define __NX_DEV_UP 1
+#define __NX_RESETTING 2
+
struct netxen_dummy_dma {
void *addr;
dma_addr_t phys_addr;
@@ -1137,7 +1143,9 @@ struct netxen_adapter {
u8 max_mc_count;
u8 rss_supported;
u8 link_changed;
- u32 resv3;
+ u8 fw_wait_cnt;
+ u8 fw_fail_cnt;
+ u16 resv4;
u8 has_link_events;
u8 fw_type;
@@ -1156,7 +1164,7 @@ struct netxen_adapter {
u32 temp;
u32 msi_tgt_status;
- u32 resv4;
+ u32 heartbit;
struct netxen_adapter_stats stats;
@@ -1187,14 +1195,15 @@ struct netxen_adapter {
struct netxen_dummy_dma dummy_dma;
- struct work_struct watchdog_task;
- struct timer_list watchdog_timer;
+ struct delayed_work fw_work;
+
struct work_struct tx_timeout_task;
struct net_device_stats net_stats;
nx_nic_intr_coalesce_t coal;
+ unsigned long state;
u32 resv5;
u32 fw_version;
const struct firmware *fw;
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index 0f42ab9..8ab5773 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -678,6 +678,9 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ if (test_and_set_bit(__NX_FW_ATTACHED, &adapter->state))
+ goto done;
+
err = nx_fw_cmd_create_rx_ctx(adapter);
if (err)
goto err_out_free;
@@ -690,6 +693,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
goto err_out_free;
}
+done:
return 0;
err_out_free:
@@ -708,6 +712,9 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
int port = adapter->portnum;
if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ if (!test_and_clear_bit(__NX_FW_ATTACHED, &adapter->state))
+ goto done;
+
nx_fw_cmd_destroy_rx_ctx(adapter);
nx_fw_cmd_destroy_tx_ctx(adapter);
} else {
@@ -720,6 +727,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
/* Allow dma queues to drain after context reset */
msleep(20);
+done:
recv_ctx = &adapter->recv_ctx;
if (recv_ctx->hwctx != NULL) {
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 92f5970..26188b4 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -433,6 +433,7 @@ enum {
#define NETXEN_CRB_PEG_NET_1 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN1)
#define NETXEN_CRB_PEG_NET_2 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN2)
#define NETXEN_CRB_PEG_NET_3 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN3)
+#define NETXEN_CRB_PEG_NET_4 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SQS2)
#define NETXEN_CRB_PEG_NET_D NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGND)
#define NETXEN_CRB_PEG_NET_I NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGNI)
#define NETXEN_CRB_DDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_MN)
@@ -945,6 +946,28 @@ enum {
#define NETXEN_DMA_WATCHDOG_CTRL (NETXEN_CAM_RAM(0x14))
#define NETXEN_PEG_ALIVE_COUNTER (NETXEN_CAM_RAM(0xb0))
+#define NETXEN_PEG_HALT_STATUS1 (NETXEN_CAM_RAM(0xa8))
+#define NETXEN_PEG_HALT_STATUS2 (NETXEN_CAM_RAM(0xac))
+#define NX_CRB_DEV_REF_COUNT (NETXEN_CAM_RAM(0x138))
+#define NX_CRB_DEV_STATE (NETXEN_CAM_RAM(0x140))
+
+/* Device State */
+#define NX_DEV_COLD 1
+#define NX_DEV_INITALIZING 2
+#define NX_DEV_READY 3
+#define NX_DEV_NEED_RESET 4
+#define NX_DEV_NEED_QUISCENT 5
+#define NX_DEV_FAILED 6
+
+#define NX_RCODE_DRIVER_INFO 0x20000000
+#define NX_RCODE_DRIVER_CAN_RELOAD 0x40000000
+#define NX_RCODE_FATAL_ERROR 0x80000000
+#define NX_FWERROR_PEGNUM(code) ((code) & 0xff)
+#define NX_FWERROR_CODE(code) ((code >> 8) & 0xfffff)
+
+#define FW_POLL_DELAY (2 * HZ)
+#define FW_FAIL_THRESH 3
+#define FW_POLL_THRESH 10
#define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200)
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 47aede6..4989436 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -67,7 +67,10 @@ static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *,
struct net_device *);
static void netxen_tx_timeout(struct net_device *netdev);
static void netxen_reset_task(struct work_struct *work);
-static void netxen_watchdog(unsigned long);
+static void netxen_fw_poll_work(struct work_struct *work);
+static void netxen_schedule_work(struct netxen_adapter *adapter,
+ work_func_t func, int delay);
+static void netxen_cancel_fw_work(struct netxen_adapter *adapter);
static int netxen_nic_poll(struct napi_struct *napi, int budget);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void netxen_nic_poll_controller(struct net_device *netdev);
@@ -76,6 +79,9 @@ static void netxen_nic_poll_controller(struct net_device *netdev);
static void netxen_create_sysfs_entries(struct netxen_adapter *adapter);
static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter);
+static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter);
+static int netxen_can_start_firmware(struct netxen_adapter *adapter);
+
static irqreturn_t netxen_intr(int irq, void *data);
static irqreturn_t netxen_msi_intr(int irq, void *data);
static irqreturn_t netxen_msix_intr(int irq, void *data);
@@ -729,19 +735,12 @@ err_out:
}
static int
-netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
+netxen_start_firmware(struct netxen_adapter *adapter)
{
int val, err, first_boot;
struct pci_dev *pdev = adapter->pdev;
- int first_driver = 0;
-
- if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
- first_driver = (adapter->portnum == 0);
- else
- first_driver = (adapter->ahw.pci_func == 0);
-
- if (!first_driver)
+ if (!netxen_can_start_firmware(adapter))
goto wait_init;
first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc));
@@ -752,8 +751,7 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
return err;
}
- if (request_fw)
- netxen_request_firmware(adapter);
+ netxen_request_firmware(adapter);
err = netxen_need_fw_reset(adapter);
if (err < 0)
@@ -768,6 +766,9 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
}
NXWR32(adapter, CRB_DMA_SHIFT, 0x55555555);
+ NXWR32(adapter, NETXEN_PEG_HALT_STATUS1, 0);
+ NXWR32(adapter, NETXEN_PEG_HALT_STATUS2, 0);
+
if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
netxen_set_port_mode(adapter);
@@ -775,6 +776,8 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
if (err)
goto err_out;
+ netxen_release_firmware(adapter);
+
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
/* Initialize multicast addr pool owners */
@@ -797,6 +800,8 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
| (_NETXEN_NIC_LINUX_SUBVERSION);
NXWR32(adapter, CRB_DRIVER_VERSION, val);
+ NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_READY);
+
wait_init:
/* Handshake with the card before we register the devices. */
err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
@@ -808,6 +813,7 @@ wait_init:
nx_update_dma_mask(adapter);
netxen_nic_get_firmware_info(adapter);
+ netxen_check_options(adapter);
return 0;
@@ -915,8 +921,7 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
else
netxen_nic_set_link_parameters(adapter);
- mod_timer(&adapter->watchdog_timer, jiffies);
-
+ set_bit(__NX_DEV_UP, &adapter->state);
return 0;
}
@@ -926,6 +931,8 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
return;
+ clear_bit(__NX_DEV_UP, &adapter->state);
+
spin_lock(&adapter->tx_clean_lock);
netif_carrier_off(netdev);
netif_tx_disable(netdev);
@@ -942,8 +949,6 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
netxen_release_tx_buffers(adapter);
spin_unlock(&adapter->tx_clean_lock);
-
- del_timer_sync(&adapter->watchdog_timer);
}
@@ -974,8 +979,6 @@ netxen_nic_attach(struct netxen_adapter *adapter)
return err;
}
- netxen_nic_clear_stats(adapter);
-
err = netxen_alloc_hw_resources(adapter);
if (err) {
printk(KERN_ERR "%s: Error in setting hw resources\n",
@@ -1046,21 +1049,32 @@ netxen_nic_reset_context(struct netxen_adapter *adapter)
int err = 0;
struct net_device *netdev = adapter->netdev;
+ if (test_and_set_bit(__NX_RESETTING, &adapter->state))
+ return -EBUSY;
+
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+ netif_device_detach(netdev);
+
if (netif_running(netdev))
netxen_nic_down(adapter, netdev);
netxen_nic_detach(adapter);
- err = netxen_nic_attach(adapter);
- if (err)
- goto done;
+ if (netif_running(netdev)) {
+ err = netxen_nic_attach(adapter);
+ if (!err)
+ err = netxen_nic_up(adapter, netdev);
- if (netif_running(netdev))
- err = netxen_nic_up(adapter, netdev);
+ if (err)
+ goto done;
+ }
+
+ netif_device_attach(netdev);
}
+
done:
+ clear_bit(__NX_RESETTING, &adapter->state);
return err;
}
@@ -1107,10 +1121,6 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
netdev->irq = adapter->msix_entries[0].vector;
- init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &netxen_watchdog;
- adapter->watchdog_timer.data = (unsigned long)adapter;
- INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
INIT_WORK(&adapter->tx_timeout_task, netxen_reset_task);
if (netxen_read_mac_addr(adapter))
@@ -1214,7 +1224,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
- err = netxen_start_firmware(adapter, 1);
+ err = netxen_start_firmware(adapter);
if (err)
goto err_out_iounmap;
@@ -1228,7 +1238,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->physical_port = i;
}
- netxen_check_options(adapter);
+ netxen_nic_clear_stats(adapter);
netxen_setup_intr(adapter);
@@ -1238,6 +1248,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, adapter);
+ netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
+
switch (adapter->ahw.port_type) {
case NETXEN_NIC_GBE:
dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
@@ -1256,6 +1268,8 @@ err_out_disable_msi:
netxen_free_dummy_dma(adapter);
+ nx_decr_dev_ref_cnt(adapter);
+
err_out_iounmap:
netxen_cleanup_pci_map(adapter);
@@ -1282,16 +1296,21 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
netdev = adapter->netdev;
+ netxen_cancel_fw_work(adapter);
+
unregister_netdev(netdev);
- cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->tx_timeout_task);
netxen_nic_detach(adapter);
+ nx_decr_dev_ref_cnt(adapter);
+
if (adapter->portnum == 0)
netxen_free_dummy_dma(adapter);
+ clear_bit(__NX_RESETTING, &adapter->state);
+
netxen_teardown_intr(adapter);
netxen_cleanup_pci_map(adapter);
@@ -1312,10 +1331,11 @@ static int __netxen_nic_shutdown(struct pci_dev *pdev)
netif_device_detach(netdev);
+ netxen_cancel_fw_work(adapter);
+
if (netif_running(netdev))
netxen_nic_down(adapter, netdev);
- cancel_work_sync(&adapter->watchdog_task);
cancel_work_sync(&adapter->tx_timeout_task);
netxen_nic_detach(adapter);
@@ -1323,6 +1343,10 @@ static int __netxen_nic_shutdown(struct pci_dev *pdev)
if (adapter->portnum == 0)
netxen_free_dummy_dma(adapter);
+ nx_decr_dev_ref_cnt(adapter);
+
+ clear_bit(__NX_RESETTING, &adapter->state);
+
retval = pci_save_state(pdev);
if (retval)
return retval;
@@ -1371,7 +1395,7 @@ netxen_nic_resume(struct pci_dev *pdev)
adapter->curr_window = 255;
- err = netxen_start_firmware(adapter, 0);
+ err = netxen_start_firmware(adapter);
if (err) {
dev_err(&pdev->dev, "failed to start firmware\n");
return err;
@@ -1380,16 +1404,22 @@ netxen_nic_resume(struct pci_dev *pdev)
if (netif_running(netdev)) {
err = netxen_nic_attach(adapter);
if (err)
- return err;
+ goto err_out;
err = netxen_nic_up(adapter, netdev);
if (err)
- return err;
+ goto err_out_detach;
netif_device_attach(netdev);
}
- return 0;
+ netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
+
+err_out_detach:
+ netxen_nic_detach(adapter);
+err_out:
+ nx_decr_dev_ref_cnt(adapter);
+ return err;
}
#endif
@@ -1783,59 +1813,13 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
netxen_advert_link_change(adapter, linkup);
}
-static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
-
- netif_device_detach(netdev);
- netxen_nic_down(adapter, netdev);
- netxen_nic_detach(adapter);
-}
-
-static void netxen_watchdog(unsigned long v)
-{
- struct netxen_adapter *adapter = (struct netxen_adapter *)v;
-
- if (netxen_nic_check_temp(adapter))
- goto do_sched;
-
- if (!adapter->has_link_events) {
- netxen_nic_handle_phy_intr(adapter);
-
- if (adapter->link_changed)
- goto do_sched;
- }
-
- if (netif_running(adapter->netdev))
- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-
- return;
-
-do_sched:
- schedule_work(&adapter->watchdog_task);
-}
-
-void netxen_watchdog_task(struct work_struct *work)
-{
- struct netxen_adapter *adapter =
- container_of(work, struct netxen_adapter, watchdog_task);
-
- if (adapter->temp == NX_TEMP_PANIC) {
- netxen_nic_thermal_shutdown(adapter);
- return;
- }
-
- if (adapter->link_changed)
- netxen_nic_set_link_parameters(adapter);
-
- if (netif_running(adapter->netdev))
- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-}
-
static void netxen_tx_timeout(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
+ if (test_bit(__NX_RESETTING, &adapter->state))
+ return;
+
dev_err(&netdev->dev, "transmit timeout, resetting.\n");
schedule_work(&adapter->tx_timeout_task);
}
@@ -1848,6 +1832,9 @@ static void netxen_reset_task(struct work_struct *work)
if (!netif_running(adapter->netdev))
return;
+ if (test_bit(__NX_RESETTING, &adapter->state))
+ return;
+
netxen_napi_disable(adapter);
adapter->netdev->trans_start = jiffies;
@@ -1974,6 +1961,239 @@ static void netxen_nic_poll_controller(struct net_device *netdev)
}
#endif
+static int
+nx_incr_dev_ref_cnt(struct netxen_adapter *adapter)
+{
+ int count;
+ if (netxen_api_lock(adapter))
+ return -EIO;
+
+ count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
+
+ NXWR32(adapter, NX_CRB_DEV_REF_COUNT, ++count);
+
+ netxen_api_unlock(adapter);
+ return count;
+}
+
+static int
+nx_decr_dev_ref_cnt(struct netxen_adapter *adapter)
+{
+ int count;
+ if (netxen_api_lock(adapter))
+ return -EIO;
+
+ count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
+ WARN_ON(count == 0);
+
+ NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count);
+
+ if (count == 0)
+ NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD);
+
+ netxen_api_unlock(adapter);
+ return count;
+}
+
+static int
+netxen_can_start_firmware(struct netxen_adapter *adapter)
+{
+ int count;
+ int can_start = 0;
+
+ if (netxen_api_lock(adapter))
+ return 0;
+
+ count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
+
+ if ((count < 0) || (count >= NX_MAX_PCI_FUNC))
+ count = 0;
+
+ if (count == 0) {
+ can_start = 1;
+ NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_INITALIZING);
+ }
+
+ NXWR32(adapter, NX_CRB_DEV_REF_COUNT, ++count);
+
+ netxen_api_unlock(adapter);
+
+ return can_start;
+}
+
+static void
+netxen_schedule_work(struct netxen_adapter *adapter,
+ work_func_t func, int delay)
+{
+ INIT_DELAYED_WORK(&adapter->fw_work, func);
+ schedule_delayed_work(&adapter->fw_work, delay);
+}
+
+static void
+netxen_cancel_fw_work(struct netxen_adapter *adapter)
+{
+ while (test_and_set_bit(__NX_RESETTING, &adapter->state))
+ msleep(10);
+
+ cancel_delayed_work_sync(&adapter->fw_work);
+}
+
+static void
+netxen_attach_work(struct work_struct *work)
+{
+ struct netxen_adapter *adapter = container_of(work,
+ struct netxen_adapter, fw_work.work);
+ struct net_device *netdev = adapter->netdev;
+ int err = 0;
+
+ if (netif_running(netdev)) {
+ err = netxen_nic_attach(adapter);
+ if (err)
+ goto done;
+
+ err = netxen_nic_up(adapter, netdev);
+ if (err) {
+ netxen_nic_detach(adapter);
+ goto done;
+ }
+
+ }
+
+ netif_device_attach(netdev);
+
+done:
+ adapter->fw_fail_cnt = 0;
+ clear_bit(__NX_RESETTING, &adapter->state);
+ netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
+}
+
+static void
+netxen_fwinit_work(struct work_struct *work)
+{
+ struct netxen_adapter *adapter = container_of(work,
+ struct netxen_adapter, fw_work.work);
+ int dev_state;
+
+ dev_state = NXRD32(adapter, NX_CRB_DEV_STATE);
+
+ switch (dev_state) {
+ case NX_DEV_COLD:
+ case NX_DEV_READY:
+ netxen_start_firmware(adapter);
+ netxen_schedule_work(adapter, netxen_attach_work, 0);
+ return;
+
+ case NX_DEV_INITALIZING:
+ if (++adapter->fw_wait_cnt < FW_POLL_THRESH) {
+ netxen_schedule_work(adapter,
+ netxen_fwinit_work, 2 * FW_POLL_DELAY);
+ return;
+ }
+ break;
+
+ case NX_DEV_FAILED:
+ default:
+ break;
+ }
+
+ nx_incr_dev_ref_cnt(adapter);
+ clear_bit(__NX_RESETTING, &adapter->state);
+}
+
+static void
+netxen_detach_work(struct work_struct *work)
+{
+ struct netxen_adapter *adapter = container_of(work,
+ struct netxen_adapter, fw_work.work);
+ struct net_device *netdev = adapter->netdev;
+ int ref_cnt, delay;
+ u32 status;
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev))
+ netxen_nic_down(adapter, netdev);
+
+ netxen_nic_detach(adapter);
+
+ status = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1);
+
+ ref_cnt = nx_decr_dev_ref_cnt(adapter);
+
+ if (status & NX_RCODE_FATAL_ERROR)
+ return;
+
+ if (adapter->temp == NX_TEMP_PANIC)
+ return;
+
+ delay = (ref_cnt == 0) ? 0 : (2 * FW_POLL_DELAY);
+
+ adapter->fw_wait_cnt = 0;
+ netxen_schedule_work(adapter, netxen_fwinit_work, delay);
+}
+
+static int
+netxen_check_health(struct netxen_adapter *adapter)
+{
+ u32 state, heartbit;
+ struct net_device *netdev = adapter->netdev;
+
+ if (netxen_nic_check_temp(adapter))
+ goto detach;
+
+ state = NXRD32(adapter, NX_CRB_DEV_STATE);
+ if (state == NX_DEV_NEED_RESET)
+ goto detach;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return 0;
+
+ heartbit = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+ if (heartbit != adapter->heartbit) {
+ adapter->heartbit = heartbit;
+ adapter->fw_fail_cnt = 0;
+ return 0;
+ }
+
+ if (++adapter->fw_fail_cnt < FW_FAIL_THRESH)
+ return 0;
+
+ clear_bit(__NX_FW_ATTACHED, &adapter->state);
+
+ dev_info(&netdev->dev, "firmware hang detected\n");
+
+detach:
+ if (!test_and_set_bit(__NX_RESETTING, &adapter->state))
+ netxen_schedule_work(adapter, netxen_detach_work, 0);
+ return 1;
+}
+
+static void
+netxen_fw_poll_work(struct work_struct *work)
+{
+ struct netxen_adapter *adapter = container_of(work,
+ struct netxen_adapter, fw_work.work);
+
+ if (test_bit(__NX_RESETTING, &adapter->state))
+ goto reschedule;
+
+ if (test_bit(__NX_DEV_UP, &adapter->state)) {
+ if (!adapter->has_link_events) {
+
+ netxen_nic_handle_phy_intr(adapter);
+
+ if (adapter->link_changed)
+ netxen_nic_set_link_parameters(adapter);
+ }
+ }
+
+ if (netxen_check_health(adapter))
+ return;
+
+reschedule:
+ netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY);
+}
+
static ssize_t
netxen_store_bridged_mode(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
--
1.6.0.2
^ permalink raw reply related
* [PATCH NEXT 5/6] netxen: refactor firmware info code
From: Dhananjay Phadke @ 2009-09-06 3:43 UTC (permalink / raw)
To: davem; +Cc: netdev
In-Reply-To: <1252208592-2240-1-git-send-email-dhananjay@netxen.com>
o Combine netxen_get_firmware_info(), netxen_check_options()
so that they are updated every time firmware is reset.
o Set dma mask everytime firmware is reset.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
---
drivers/net/netxen/netxen_nic.h | 1 -
drivers/net/netxen/netxen_nic_hw.c | 59 --------------
drivers/net/netxen/netxen_nic_main.c | 141 +++++++++++++++++++++++----------
3 files changed, 98 insertions(+), 103 deletions(-)
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 5bbc40b..df03ea4 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -1263,7 +1263,6 @@ void netxen_pcie_sem_unlock(struct netxen_adapter *, int);
netxen_pcie_sem_unlock((a), 7)
int netxen_nic_get_board_info(struct netxen_adapter *adapter);
-void netxen_nic_get_firmware_info(struct netxen_adapter *adapter);
int netxen_nic_wol_supported(struct netxen_adapter *adapter);
/* Functions from netxen_nic_init.c */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index cbfd610..555bc4a 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -2240,65 +2240,6 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
}
}
-void netxen_nic_get_firmware_info(struct netxen_adapter *adapter)
-{
- u32 fw_major, fw_minor, fw_build;
- char brd_name[NETXEN_MAX_SHORT_NAME];
- char serial_num[32];
- int i, offset, val;
- int *ptr32;
- struct pci_dev *pdev = adapter->pdev;
-
- adapter->driver_mismatch = 0;
-
- ptr32 = (int *)&serial_num;
- offset = NX_FW_SERIAL_NUM_OFFSET;
- for (i = 0; i < 8; i++) {
- if (netxen_rom_fast_read(adapter, offset, &val) == -1) {
- dev_err(&pdev->dev, "error reading board info\n");
- adapter->driver_mismatch = 1;
- return;
- }
- ptr32[i] = cpu_to_le32(val);
- offset += sizeof(u32);
- }
-
- fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
- fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
- fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
-
- adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build);
-
- if (adapter->portnum == 0) {
- get_brd_name_by_type(adapter->ahw.board_type, brd_name);
-
- printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n",
- brd_name, serial_num, adapter->ahw.revision_id);
- }
-
- if (adapter->fw_version < NETXEN_VERSION_CODE(3, 4, 216)) {
- adapter->driver_mismatch = 1;
- dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n",
- fw_major, fw_minor, fw_build);
- return;
- }
-
- dev_info(&pdev->dev, "firmware version %d.%d.%d\n",
- fw_major, fw_minor, fw_build);
-
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
- i = NXRD32(adapter, NETXEN_SRE_MISC);
- adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0;
- dev_info(&pdev->dev, "firmware running in %s mode\n",
- adapter->ahw.cut_through ? "cut-through" : "legacy");
- }
-
- if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222))
- adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
-
- adapter->flags &= ~NETXEN_NIC_LRO_ENABLED;
-}
-
int
netxen_nic_wol_supported(struct netxen_adapter *adapter)
{
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index b2fd713..304618a 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -318,44 +318,6 @@ err_out:
return err;
}
-static void
-netxen_check_options(struct netxen_adapter *adapter)
-{
- if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
- adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
- adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
- } else if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
- adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
- adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
- }
-
- adapter->msix_supported = 0;
- if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
- adapter->msix_supported = !!use_msi_x;
- adapter->rss_supported = !!use_msi_x;
- } else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) {
- switch (adapter->ahw.board_type) {
- case NETXEN_BRDTYPE_P2_SB31_10G:
- case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
- adapter->msix_supported = !!use_msi_x;
- adapter->rss_supported = !!use_msi_x;
- break;
- default:
- break;
- }
- }
-
- adapter->num_txd = MAX_CMD_DESCRIPTORS;
-
- if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
- adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
- adapter->max_rds_rings = 3;
- } else {
- adapter->num_lro_rxd = 0;
- adapter->max_rds_rings = 2;
- }
-}
-
static int
netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
{
@@ -733,12 +695,110 @@ err_out:
return err;
}
+static void
+netxen_check_options(struct netxen_adapter *adapter)
+{
+ u32 fw_major, fw_minor, fw_build;
+ char brd_name[NETXEN_MAX_SHORT_NAME];
+ char serial_num[32];
+ int i, offset, val;
+ int *ptr32;
+ struct pci_dev *pdev = adapter->pdev;
+
+ adapter->driver_mismatch = 0;
+
+ ptr32 = (int *)&serial_num;
+ offset = NX_FW_SERIAL_NUM_OFFSET;
+ for (i = 0; i < 8; i++) {
+ if (netxen_rom_fast_read(adapter, offset, &val) == -1) {
+ dev_err(&pdev->dev, "error reading board info\n");
+ adapter->driver_mismatch = 1;
+ return;
+ }
+ ptr32[i] = cpu_to_le32(val);
+ offset += sizeof(u32);
+ }
+
+ fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+ fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+ fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
+
+ adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build);
+
+ if (adapter->portnum == 0) {
+ get_brd_name_by_type(adapter->ahw.board_type, brd_name);
+
+ printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n",
+ brd_name, serial_num, adapter->ahw.revision_id);
+ }
+
+ if (adapter->fw_version < NETXEN_VERSION_CODE(3, 4, 216)) {
+ adapter->driver_mismatch = 1;
+ dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n",
+ fw_major, fw_minor, fw_build);
+ return;
+ }
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ i = NXRD32(adapter, NETXEN_SRE_MISC);
+ adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0;
+ }
+
+ dev_info(&pdev->dev, "firmware v%d.%d.%d [%s]\n",
+ fw_major, fw_minor, fw_build,
+ adapter->ahw.cut_through ? "cut-through" : "legacy");
+
+ if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222))
+ adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
+
+ adapter->flags &= ~NETXEN_NIC_LRO_ENABLED;
+
+ if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+ } else if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
+ }
+
+ adapter->msix_supported = 0;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ adapter->msix_supported = !!use_msi_x;
+ adapter->rss_supported = !!use_msi_x;
+ } else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) {
+ switch (adapter->ahw.board_type) {
+ case NETXEN_BRDTYPE_P2_SB31_10G:
+ case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ adapter->msix_supported = !!use_msi_x;
+ adapter->rss_supported = !!use_msi_x;
+ break;
+ default:
+ break;
+ }
+ }
+
+ adapter->num_txd = MAX_CMD_DESCRIPTORS;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
+ adapter->max_rds_rings = 3;
+ } else {
+ adapter->num_lro_rxd = 0;
+ adapter->max_rds_rings = 2;
+ }
+}
+
static int
netxen_start_firmware(struct netxen_adapter *adapter)
{
int val, err, first_boot;
struct pci_dev *pdev = adapter->pdev;
+ /* required for NX2031 dummy dma */
+ err = nx_set_dma_mask(adapter);
+ if (err)
+ return err;
+
if (!netxen_can_start_firmware(adapter))
goto wait_init;
@@ -811,7 +871,6 @@ wait_init:
nx_update_dma_mask(adapter);
- netxen_nic_get_firmware_info(adapter);
netxen_check_options(adapter);
return 0;
@@ -1191,10 +1250,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
revision_id = pdev->revision;
adapter->ahw.revision_id = revision_id;
- err = nx_set_dma_mask(adapter);
- if (err)
- goto err_out_free_netdev;
-
rwlock_init(&adapter->adapter_lock);
spin_lock_init(&adapter->tx_clean_lock);
INIT_LIST_HEAD(&adapter->mac_list);
--
1.6.0.2
^ 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