* Re: reminder, 2.6.18 window...
From: Dave Dillow @ 2006-05-25 13:34 UTC (permalink / raw)
To: Bill Fink; +Cc: netdev
In-Reply-To: <20060525032357.4990425f.billfink@mindspring.com>
On Thu, 2006-05-25 at 03:23 -0400, Bill Fink wrote:
> likely problem areas. The human mind (at least speaking for myself) is
> not nearly as adept when having to deal with deltas. Yes, you can record
> the initial state of all the devices, run the stress test, record the new
> state of all the devices, and then spend a large amount of time devising
> a script to calculate all the deltas for all the scores of variables on
> all the involved devices, and then finally try and figure out what is
> wrong. But it would be so much better, easier, and more efficient, if
> the kernel simply provided such a feature that almost all other networking
> devices provide.
ftp://ftp.cup.hp.com/dist/networking/tools/beforeafter.tar.gz
as Rick mentioned earlier, and then you won't need to write a
complicated script.
--
Dave Dillow <dave@thedillows.org>
^ permalink raw reply
* Re: [Bugme-new] [Bug 6613] New: iptables broken on 32-bit PReP (ARCH=ppc)
From: Andrew Morton @ 2006-05-25 14:03 UTC (permalink / raw)
To: bugme-daemon; +Cc: netdev, Patrick McHardy, mroos
In-Reply-To: <200605251004.k4PA4Lek007751@fire-2.osdl.org>
bugme-daemon@bugzilla.kernel.org wrote:
>
> http://bugzilla.kernel.org/show_bug.cgi?id=6613
>
> Summary: iptables broken on 32-bit PReP (ARCH=ppc)
> Kernel Version: 2.6.17-rc4
> Status: NEW
> Severity: normal
> Owner: laforge@gnumonks.org
> Submitter: mroos@linux.ee
>
>
> Most recent kernel where this bug did not occur: none known, this is a fresh
> install
> Distribution: Debian unstable
> Hardware Environment: 32-bit PowerPC 604 with PReP subarch (using old
> ARCH=ppc)
> Software Environment: usual 32-bit ppc userspace, gcc 4.0.3
> Problem Description: iptables operations usually just give "Incalida
> operation". modprobe iptable_filter and adding rules to the nat table have
> failed in testing while iptable_nat can be modprobed and listed.
>
> Steps to reproduce:
> modprobe iptable_filter (errors out with Invalid Argument)
> iptables -t nat -A POSTROUTING -s 10.0.0.0/8 -j SNAT --to 192.168.1.1 (usually
> errors out with Invalid Argument, sometimes succeeds, when succeeds then the
> rule works fine)
>
^ permalink raw reply
* Re: [PATCH] bridge: fix locking and memory leak in br_add_bridge
From: Jiri Benc @ 2006-05-25 14:07 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, NetDev
In-Reply-To: <20060525153124.478bea57@griffin.suse.cz>
On Thu, 25 May 2006 15:31:24 +0200, Jiri Benc wrote:
> err2:
> - free_netdev(dev);
> + unregister_netdevice(dev);
> err1:
> rtnl_unlock();
> + free_netdev(dev);
> return ret;
Sorry, this is wrong. I didn't notice that br_dev_setup sets
dev->destructor to free_netdev. Corrected patch will follow.
Jiri
--
Jiri Benc
SUSE Labs
^ permalink raw reply
* [PATCH v2] bridge: fix locking and memory leak in br_add_bridge
From: Jiri Benc @ 2006-05-25 14:14 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, NetDev
In-Reply-To: <20060525160735.3c2aa9a5@griffin.suse.cz>
There are several bugs in error handling in br_add_bridge:
- when dev_alloc_name fails, allocated net_device is not freed
- unregister_netdev is called when rtnl lock is held
- free_netdev is called before netdev_run_todo has a chance to be run after
unregistering net_device
This patch should fix these issues.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
net/bridge/br_if.c | 15 ++++++---------
1 files changed, 6 insertions(+), 9 deletions(-)
--- dscape.orig/net/bridge/br_if.c
+++ dscape/net/bridge/br_if.c
@@ -301,25 +301,22 @@ int br_add_bridge(const char *name)
if (strchr(dev->name, '%')) {
ret = dev_alloc_name(dev, dev->name);
if (ret < 0)
- goto err1;
+ goto err;
}
ret = register_netdevice(dev);
if (ret)
- goto err2;
+ goto err;
ret = br_sysfs_addbr(dev);
if (ret)
- goto err3;
+ unregister_netdevice(dev);
rtnl_unlock();
- return 0;
+ return ret;
- err3:
- unregister_netdev(dev);
- err2:
- free_netdev(dev);
- err1:
+ err:
rtnl_unlock();
+ free_netdev(dev);
return ret;
}
--
Jiri Benc
SUSE Labs
^ permalink raw reply
* [RFC PATCH 0/2] Hardware button support for Wireless cards
From: Ivo van Doorn @ 2006-05-25 15:15 UTC (permalink / raw)
To: netdev
In-Reply-To: <!&!AAAAAAAAAAAuAAAAAAAAAFjEWUvexJtFsm0woXMZeHABAC4qy2+Ja65JmQuhL0/hqcgAAAAARPYAABAAAACMsnpvfH4iTKrBh6ONAHj7AQAAAAA=@serialmonkey.com>
[-- Attachment #1: Type: text/plain, Size: 914 bytes --]
Hi,
As discussed previously on this list hardware button support
for wireless cards and Bluetooth devices could use a seperate
generalized driver.
I have made a first attempt to do this with the suggestions from the
discussion. This means that in all cases the hardware will be requested
to enable or disable the radio (if this command needs to be issued from
software) and it will send a signal to the input device created for the button.
At the moment a input device will be created for each registered button,
not sure if this is the desired situation, but thats why this is a RFC patch. ;)
I am also not sure where to place this driver so at the moment I have placed
it in /drivers/input/misc
The second patch is an example of the implementation in rt2x00.
That is just an example since that already contained a similar approach with
hardware button support.
All hints/tips/comments are welcome. :)
Ivo
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [RFC PATCH 1/2] Hardware button support for Wireless cards: radiobtn
From: Ivo van Doorn @ 2006-05-25 15:16 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 10016 bytes --]
Add radiobtn driver.
This driver creates an iput device for each registered button
and will poll the device frequently to check the latest status of the button.
Once the status has changed it will try to enable or disable the radio
and send an event to the input device.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev/drivers/input/misc/Kconfig wireless-dev-radiobtn/drivers/input/misc/Kconfig
--- wireless-dev/drivers/input/misc/Kconfig 2006-04-27 00:52:53.000000000 +0200
+++ wireless-dev-radiobtn/drivers/input/misc/Kconfig 2006-05-25 16:29:23.000000000 +0200
@@ -79,4 +79,13 @@ config HP_SDC_RTC
Say Y here if you want to support the built-in real time clock
of the HP SDC controller.
+config RADIOBTN
+ tristate "Hardware radio button support"
+ help
+ Say Y here if you have an integrated WiFi or Bluetooth device
+ which contains an hardware button for enabling or disabling the radio.
+ When this driver is used, this driver will make sure the radio will
+ be correctly enabled and disabled when needed. It will then also
+ use the created input device to signal user space of this event
+ which allows userspace to take additional actions.
endif
diff -uprN wireless-dev/drivers/input/misc/Makefile wireless-dev-radiobtn/drivers/input/misc/Makefile
--- wireless-dev/drivers/input/misc/Makefile 2006-04-27 00:52:53.000000000 +0200
+++ wireless-dev-radiobtn/drivers/input/misc/Makefile 2006-05-25 16:25:43.000000000 +0200
@@ -11,3 +11,4 @@ obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
+obj-$(CONFIG_RADIOBTN) += radiobtn.o
diff -uprN wireless-dev/drivers/input/misc/radiobtn.c wireless-dev-radiobtn/drivers/input/misc/radiobtn.c
--- wireless-dev/drivers/input/misc/radiobtn.c 1970-01-01 01:00:00.000000000 +0100
+++ wireless-dev-radiobtn/drivers/input/misc/radiobtn.c 2006-05-25 16:23:59.000000000 +0200
@@ -0,0 +1,158 @@
+/*
+ Copyright (C) 2006 Ivo van Doorn
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Radio hardware button support
+ Poll frequently all registered hardware for hardware button status,
+ if changed enabled or disable the radio of that hardware device.
+ Send signal to input device to inform userspace about the new status.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/radiobtn.h>
+
+MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("Radio hardware button support");
+MODULE_LICENSE("GPL");
+
+void radiobtn_poll(unsigned long data)
+{
+ struct radio_button *radiobtn = (struct radio_button*)data;
+ int state;
+
+ /*
+ * Poll for the new state.
+ * Check if the state has changed.
+ */
+ state = !!radiobtn->button_poll(radiobtn->data);
+ if (state != radiobtn->current_state) {
+ radiobtn->current_state = state;
+
+ /*
+ * Enable or disable the radio when this
+ * should be done in software.
+ */
+ if (state && radiobtn->enable_radio)
+ radiobtn->enable_radio(radiobtn->data);
+ else if (!state && radiobtn->disable_radio)
+ radiobtn->disable_radio(radiobtn->data);
+
+ /*
+ * Report key event.
+ */
+ input_report_key(radiobtn->input_dev, KEY_RADIO, 1);
+ input_sync(radiobtn->input_dev);
+ input_report_key(radiobtn->input_dev, KEY_RADIO, 0);
+ input_sync(radiobtn->input_dev);
+ }
+
+ /*
+ * Check if polling has been disabled.
+ */
+ if (radiobtn->poll_delay != 0) {
+ radiobtn->poll_timer.expires =
+ jiffies + msecs_to_jiffies(radiobtn->poll_delay);
+ add_timer(&radiobtn->poll_timer);
+ }
+}
+
+int radiobtn_register_device(struct radio_button *radiobtn)
+{
+ int status;
+
+ /*
+ * Check if all mandatory fields have been set.
+ */
+ if (radiobtn->poll_delay == 0 || radiobtn->button_poll == NULL)
+ return -EINVAL;
+
+ /*
+ * Allocate, initialize and register input device.
+ */
+ radiobtn->input_dev = input_allocate_device();
+ if (!radiobtn->input_dev) {
+ printk(KERN_ERR "Failed to allocate input device %s.\n",
+ radiobtn->dev_name);
+ return -ENOMEM;
+ }
+
+ radiobtn->input_dev->name = "Radio button";
+ radiobtn->input_dev->phys = strcat("radiobtn/", radiobtn->dev_name);
+ radiobtn->input_dev->id.bustype = BUS_HOST;
+ set_bit(KEY_RADIO, radiobtn->input_dev->keybit);
+
+ status = input_register_device(radiobtn->input_dev);
+ if (status) {
+ printk(KERN_ERR "Failed to register input device %s.\n",
+ radiobtn->dev_name);
+ input_free_device(radiobtn->input_dev);
+ return status;
+ }
+
+ /*
+ * Initialize timer.
+ */
+ init_timer(&radiobtn->poll_timer);
+ radiobtn->poll_timer.function = radiobtn_poll;
+ radiobtn->poll_timer.data = (unsigned long)radiobtn;
+ radiobtn->poll_timer.expires =
+ jiffies + msecs_to_jiffies(radiobtn->poll_delay);
+ add_timer(&radiobtn->poll_timer);
+
+ printk(KERN_INFO "Created new %s: %s.\n",
+ radiobtn->input_dev->name, radiobtn->input_dev->phys);
+
+ return 0;
+}
+
+void radiobtn_unregister_device(struct radio_button *radiobtn)
+{
+ /*
+ * Stop timer.
+ */
+ radiobtn->poll_delay = 0;
+ del_timer_sync(&radiobtn->poll_timer);
+
+ /*
+ * Remove input device.
+ */
+ input_unregister_device(radiobtn->input_dev);
+ input_free_device(radiobtn->input_dev);
+}
+
+static int __init radiobtn_init(void)
+{
+ printk(KERN_INFO "Loading radio button driver.\n");
+ return 0;
+}
+
+static void __exit radiobtn_exit(void)
+{
+ printk(KERN_INFO "Unloading radio button driver.\n");
+}
+
+EXPORT_SYMBOL(radiobtn_register_device);
+EXPORT_SYMBOL(radiobtn_unregister_device);
+
+module_init(radiobtn_init);
+module_exit(radiobtn_exit);
diff -uprN wireless-dev/include/linux/radiobtn.h wireless-dev-radiobtn/include/linux/radiobtn.h
--- wireless-dev/include/linux/radiobtn.h 1970-01-01 01:00:00.000000000 +0100
+++ wireless-dev-radiobtn/include/linux/radiobtn.h 2006-05-25 15:02:33.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+ Copyright (C) 2006 Ivo van Doorn
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Radio hardware button support
+ Laptops are quite often equiped with support with a hardware button
+ to enabled and disable the radio of the integrated wireless network
+ or bluetooth interface.
+ Altough some devices will make sure that when pressed the radio
+ is disabled in hardware, other device depend on the software
+ to enabled or disable the radio accordingly.
+ This driver will create an input device and will poll registered
+ hardware frequently to listen if the button has been pressed.
+ When the device requires the software to disable or enable
+ the radio it will do so correctly, but it will also in all cases
+ send a signal to the input device to inform any listening daemon
+ the state has changed and will allow userspace to handle certain
+ tasks as well if required.
+ */
+
+#ifndef RADIOBTN_H
+#define RADIOBTN_H
+
+#include <linux/input.h>
+
+/**
+ * struct radio_button - radio hardware structure.
+ * @dev_name: Name of the interface. This will become the name
+ * of the input device created in /dev/radio/.
+ * @data: Private data which will be passed along with the radio handlers.
+ * @button_poll(unsigned long data): Handler which will be called
+ * with the poll_delay interval.
+ * @enable_radio(unsigned long data): Optional handler to enable the radio
+ * once the button has been pressed when the hardware does not do this
+ * automaticly.
+ * @disable_radio(unsigned long data): Optional handler to disable the radio
+ * once the button has been pressed when the hardware does not do this
+ * automaticly.
+ * @poll_delay: Delay in msecs between each poll.
+ * @current_state: Current state of the button.
+ * @input_dev: Pointer to input device for this radio button.
+ * (Should not be touched by driver)
+ * @poll_timer: Timer used to poll for the button status.
+ * (Should not be touched by driver)
+ */
+struct radio_button {
+ const char *dev_name;
+
+ unsigned long data;
+
+ int (*button_poll)(unsigned long data);
+ void (*enable_radio)(unsigned long data);
+ void (*disable_radio)(unsigned long data);
+
+ unsigned int poll_delay;
+
+ unsigned int current_state;
+
+ struct input_dev *input_dev;
+
+ struct timer_list poll_timer;
+}
+
+int radiobtn_register_device(struct radio_button *);
+void radiobtn_unregister_device(struct radio_button *);
+
+#endif /* RADIOBTN_H */
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [RFC PATCH 2/2] Hardware button support for Wireless cards: rt2x00
From: Ivo van Doorn @ 2006-05-25 15:16 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 13825 bytes --]
Use radiobtn interface for radio hardware button support in rt2x00
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
diff -uprN wireless-dev/drivers/net/wireless/d80211/rt2x00/Kconfig wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/Kconfig
--- wireless-dev/drivers/net/wireless/d80211/rt2x00/Kconfig 2006-05-06 21:11:03.000000000 +0200
+++ wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/Kconfig 2006-05-25 16:32:23.000000000 +0200
@@ -17,7 +17,7 @@ config RT2400PCI
config RT2400PCI_BUTTON
bool "Ralink rt2400 hardware button support"
- depends on RT2400PCI && X86
+ depends on RT2400PCI && RADIOBTN
---help---
In some notebooks the rt2400 chipset is integrated in the machine,
with this option enabled the device will periodically poll the
@@ -40,7 +40,7 @@ config RT2500PCI
config RT2500PCI_BUTTON
bool "Ralink rt2500 hardware button support"
- depends on RT2500PCI && X86
+ depends on RT2500PCI && RADIOBTN
---help---
In some notebooks the rt2500 chipset is integrated in the machine,
with this option enabled the device will periodically poll the
@@ -61,9 +61,9 @@ config RT61PCI
When compiled as a module, this driver will be called "rt61pci.ko".
-config RT2500PCI_BUTTON
+config RT61PCI_BUTTON
bool "Ralink rt61 hardware button support"
- depends on RT61PCI && X86
+ depends on RT61PCI && RADIOBTN
---help---
In some notebooks the rt61 chipset is integrated in the machine,
with this option enabled the device will periodically poll the
diff -uprN wireless-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-05-06 21:11:03.000000000 +0200
+++ wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-05-25 16:54:07.000000000 +0200
@@ -51,6 +51,7 @@
#ifdef CONFIG_RT2400PCI_BUTTON
#define CONFIG_RT2X00_BUTTON
+#include <linux/radiobtn.h>
#endif /* CONFIG_RT2400PCI_BUTTON */
#include "rt2x00.h"
@@ -364,18 +365,58 @@ rt2x00_eeprom_multiread(
/*
* Hardware button poll handler.
*/
-static void
+static int
rt2400pci_button_poll(unsigned long data)
{
struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
u32 reg;
rt2x00_register_read(rt2x00pci, GPIOCSR, ®);
- rt2x00pci_button_status(
- rt2x00pci, rt2x00_get_field32(reg, GPIOCSR_BIT0));
+ return rt2x00_get_field32(reg, GPIOCSR_BIT0);
+}
+
+static void
+rt2400pci_enable_radio(unsigned long data)
+{
+ struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
+ struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+
+ rt2400pci_open(net_dev);
+}
+
+static void
+rt2400pci_disable_radio(unsigned long data)
+{
+ struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
+ struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+
+ rt2400pci_stop(net_dev);
+}
+
+static int
+rt2400pci_button_start(struct rt2x00_pci *rt2x00pci)
+{
+ struct radio_button *button = &rt2x00pci->radio_button;
+
+ button->dev_name = "rt2400pci";
+ button->data = (unsigned long)rt2x00pci;
+ button->button_poll = rt2400pci_button_poll;
+ button->enable_radio = rt2400pci_enable_radio;
+ button->disable_radio = rt2400pci_disable_radio;
+ button->poll_delay = rt2x00_poll_delay;
+ button->current_state = button->button_poll(button->data);
+
+ return radiobtn_register_device(button);
+}
+
+static void
+rt2400pci_button_stop(struct rt2x00_pci *rt2x00pci)
+{
+ radiobtn_unregister_device(&rt2x00pci->radio_button);
}
#else /* CONFIG_RT2400PCI_BUTTON */
-static void rt2400pci_button_poll(struct rt2x00_pci *rt2x00pci){}
+static int rt2400pci_button_start(struct rt2x00_pci *rt2x00pci){return 0;}
+static void rt2400pci_button_stop(struct rt2x00_pci *rt2x00pci){}
#endif /* CONFIG_RT2400PCI_BUTTON */
/*
@@ -2471,7 +2512,7 @@ rt2400pci_initialize(struct pci_dev *pci
/*
* If required start hardware button polling.
*/
- rt2x00pci_button_start(rt2x00pci, rt2400pci_button_poll);
+ rt2400pci_button_start(rt2x00pci);
/*
* Register hardware.
@@ -2502,7 +2543,7 @@ rt2400pci_uninitialize(struct net_device
/*
* Shutdown poll_timer for hardware button.
*/
- rt2x00pci_button_stop(rt2x00pci);
+ rt2400pci_button_stop(rt2x00pci);
kfree(rt2x00pci->eeprom);
diff -uprN wireless-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-05-06 21:11:03.000000000 +0200
+++ wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-05-25 16:53:54.000000000 +0200
@@ -51,6 +51,7 @@
#ifdef CONFIG_RT2500PCI_BUTTON
#define CONFIG_RT2X00_BUTTON
+#include <linux/radiobtn.h>
#endif /* CONFIG_RT2500PCI_BUTTON */
#include "rt2x00.h"
@@ -364,18 +365,58 @@ rt2x00_eeprom_multiread(
/*
* Hardware button poll handler.
*/
-static void
+static int
rt2500pci_button_poll(unsigned long data)
{
struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
u32 reg;
rt2x00_register_read(rt2x00pci, GPIOCSR, ®);
- rt2x00pci_button_status(
- rt2x00pci, rt2x00_get_field32(reg, GPIOCSR_BIT0));
+ return rt2x00_get_field32(reg, GPIOCSR_BIT0);
+}
+
+static void
+rt2500pci_enable_radio(unsigned long data)
+{
+ struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
+ struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+
+ rt2500pci_open(net_dev);
+}
+
+static void
+rt2500pci_disable_radio(unsigned long data)
+{
+ struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
+ struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+
+ rt2500pci_stop(net_dev);
+}
+
+static int
+rt2500pci_button_start(struct rt2x00_pci *rt2x00pci)
+{
+ struct radio_button *button = &rt2x00pci->radio_button;
+
+ button->dev_name = "rt2500pci";
+ button->data = (unsigned long)rt2x00pci;
+ button->button_poll = rt2500pci_button_poll;
+ button->enable_radio = rt2500pci_enable_radio;
+ button->disable_radio = rt2500pci_disable_radio;
+ button->poll_delay = rt2x00_poll_delay;
+ button->current_state = button->button_poll(button->data);
+
+ return radiobtn_register_device(button);
+}
+
+static void
+rt2500pci_button_stop(struct rt2x00_pci *rt2x00pci)
+{
+ radiobtn_unregister_device(&rt2x00pci->radio_button);
}
#else /* CONFIG_RT2500PCI_BUTTON */
-static void rt2500pci_button_poll(struct rt2x00_pci *rt2x00pci){}
+static int rt2500pci_button_start(struct rt2x00_pci *rt2x00pci){return 0;}
+static void rt2500pci_button_stop(struct rt2x00_pci *rt2x00pci){}
#endif /* CONFIG_RT2500PCI_BUTTON */
/*
@@ -2774,7 +2815,7 @@ rt2500pci_initialize(struct pci_dev *pci
/*
* If required start hardware button polling.
*/
- rt2x00pci_button_start(rt2x00pci, rt2500pci_button_poll);
+ rt2500pci_button_start(rt2x00pci);
/*
* Register hardware.
@@ -2805,7 +2846,7 @@ rt2500pci_uninitialize(struct net_device
/*
* Shutdown poll_timer for hardware button.
*/
- rt2x00pci_button_stop(rt2x00pci);
+ rt2500pci_button_stop(rt2x00pci);
kfree(rt2x00pci->eeprom);
diff -uprN wireless-dev/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
--- wireless-dev/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h 2006-05-06 21:11:03.000000000 +0200
+++ wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h 2006-05-25 16:33:46.000000000 +0200
@@ -45,37 +45,6 @@
#define EEPROM_READ_OPCODE 0x06
/*
- * HW button structure.
- */
-#ifdef CONFIG_RT2X00_BUTTON
-#include <acpi/acpi_bus.h>
-
-struct rt2x00_button{
- /*
- * ACPI device for generation of ACPI events.
- */
- struct acpi_device acpi_dev;
-
- /*
- * Timer for register polling.
- */
- struct timer_list poll_timer;
-
- /*
- * Timer delay.
- */
- short poll_delay;
-
- /*
- * Current status of button.
- */
- short button_status:1;
- short active_poll:1;
- short __pad:14;
-};
-#endif /* CONFIG_RT2X00_BUTTON */
-
-/*
* data_entry
* The data ring is a list of data entries.
* Each entry holds a reference to the descriptor
@@ -123,7 +92,7 @@ struct rt2x00_pci{
struct pci_dev *pci_dev;
#ifdef CONFIG_RT2X00_BUTTON
- struct rt2x00_button button;
+ struct radio_button button;
#endif /* CONFIG_RT2X00_BUTTON */
/*
@@ -267,85 +236,11 @@ rt2x00pci_get_ring(struct rt2x00_pci *rt
return NULL;
}
-/*
- * HW button variables & functions.
- * The delay between each poll is set by the module parameter.
- */
#ifdef CONFIG_RT2X00_BUTTON
/*
* Module parameter.
*/
static short rt2x00_poll_delay = 0;
-
-static inline void
-rt2x00pci_button_status(struct rt2x00_pci *rt2x00pci, char status)
-{
- struct rt2x00_button *button = &rt2x00pci->button;
-
- if (!button->active_poll)
- return;
-
- if (status != button->button_status) {
- button->button_status = status;
- acpi_bus_generate_event(
- &button->acpi_dev, ACPI_TYPE_EVENT, status);
- }
-
- button->poll_timer.expires = jiffies + button->poll_delay;
-
- if (button->active_poll)
- add_timer(&button->poll_timer);
-}
-
-static inline void
-rt2x00pci_button_start(struct rt2x00_pci *rt2x00pci,
- void (*handler)(unsigned long data))
-{
- struct rt2x00_button *button = &rt2x00pci->button;
-
- /*
- * Only enable polling when the user has
- * set the poll delay module parameter,
- * and the device contains a hardware button.
- */
- if(!GET_FLAG(rt2x00pci, HARDWARE_BUTTON) || !rt2x00_poll_delay)
- return;
-
- strcpy(acpi_device_class(&button->acpi_dev), DRV_NAME "_button");
- strcpy(acpi_device_bid(&button->acpi_dev), DRV_NAME);
- strcpy(acpi_device_name(&button->acpi_dev), DRV_NAME);
-
- init_timer(&button->poll_timer);
-
- button->poll_delay = rt2x00_poll_delay * (HZ / 10);
- button->button_status = 0;
- button->active_poll = 1;
-
- button->poll_timer.function = handler;
- button->poll_timer.data = (unsigned long)rt2x00pci;
- button->poll_timer.expires = jiffies + button->poll_delay;
-
- add_timer(&button->poll_timer);
-}
-
-static inline void
-rt2x00pci_button_stop(struct rt2x00_pci *rt2x00pci)
-{
- /*
- * Shutdown poll_timer for hardware button,
- * make sure only to disable polling when
- * it was enabled in the first place.
- */
- if(!rt2x00pci->button.active_poll)
- return;
-
- rt2x00pci->button.active_poll = 0;
- del_timer_sync(&rt2x00pci->button.poll_timer);
-}
-#else /* CONFIG_RT2X00_BUTTON */
-static inline void rt2x00pci_button_start(struct rt2x00_pci *rt2x00pci,
- int (*handler)(struct rt2x00_pci *rt2x00pci)){}
-static inline void rt2x00pci_button_stop(struct rt2x00_pci *rt2x00pci){}
#endif /* CONFIG_RT2X00_BUTTON */
#endif /* RT2X00PCI_H */
diff -uprN wireless-dev/drivers/net/wireless/d80211/rt2x00/rt61pci.c wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev/drivers/net/wireless/d80211/rt2x00/rt61pci.c 2006-05-06 21:11:03.000000000 +0200
+++ wireless-dev-radiobtn/drivers/net/wireless/d80211/rt2x00/rt61pci.c 2006-05-25 16:54:30.000000000 +0200
@@ -52,6 +52,7 @@
#ifdef CONFIG_RT61PCI_BUTTON
#define CONFIG_RT2X00_BUTTON
+#include <linux/radiobtn.h>
#endif /* CONFIG_RT61PCI_BUTTON */
#include "rt2x00.h"
@@ -400,18 +401,58 @@ rt2x00_eeprom_multiread(
/*
* Hardware button poll handler.
*/
-static void
+static int
rt61pci_button_poll(unsigned long data)
{
struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
u32 reg;
rt2x00_register_read(rt2x00pci, MAC_CSR13, ®);
- rt2x00pci_button_status(
- rt2x00pci, rt2x00_get_field32(reg, MAC_CSR13_BIT5));
+ return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
+}
+
+static void
+rt61pci_enable_radio(unsigned long data)
+{
+ struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
+ struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+
+ rt61pci_open(net_dev);
+}
+
+static void
+rt61pci_disable_radio(unsigned long data)
+{
+ struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci*)data;
+ struct net_device *net_dev = pci_get_drvdata(rt2x00pci->pci_dev);
+
+ rt61pci_stop(net_dev);
+}
+
+static int
+rt61pci_button_start(struct rt2x00_pci *rt2x00pci)
+{
+ struct radio_button *button = &rt2x00pci->radio_button;
+
+ button->dev_name = "rt61pci";
+ button->data = (unsigned long)rt2x00pci;
+ button->button_poll = rt61pci_button_poll;
+ button->enable_radio = rt61pci_enable_radio;
+ button->disable_radio = rt61pci_disable_radio;
+ button->poll_delay = rt2x00_poll_delay;
+ button->current_state = button->button_poll(button->data);
+
+ return radiobtn_register_device(button);
+}
+
+static void
+rt61pci_button_stop(struct rt2x00_pci *rt2x00pci)
+{
+ radiobtn_unregister_device(&rt2x00pci->radio_button);
}
#else /* CONFIG_RT61PCI_BUTTON */
-static void rt61pci_button_poll(struct rt2x00_pci *rt2x00pci){}
+static int rt61pci_button_start(struct rt2x00_pci *rt2x00pci){return 0;}
+static void rt61pci_button_stop(struct rt2x00_pci *rt2x00pci){}
#endif /* CONFIG_RT61PCI_BUTTON */
/*
@@ -3324,7 +3365,7 @@ rt61pci_initialize(struct pci_dev *pci_d
/*
* If required start hardware button polling.
*/
- rt2x00pci_button_start(rt2x00pci, rt61pci_button_poll);
+ rt61pci_button_start(rt2x00pci);
/*
* Register hardware.
@@ -3355,7 +3396,7 @@ rt61pci_uninitialize(struct net_device *
/*
* Shutdown poll_timer for hardware button.
*/
- rt2x00pci_button_stop(rt2x00pci);
+ rt61pci_button_stop(rt2x00pci);
kfree(rt2x00pci->eeprom);
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: reminder, 2.6.18 window...
From: jamal @ 2006-05-25 15:27 UTC (permalink / raw)
To: Rick Jones; +Cc: Jeff Garzik, David Miller, netdev, Phil Dibowitz
In-Reply-To: <4474C12E.8050600@hp.com>
On Wed, 2006-24-05 at 13:25 -0700, Rick Jones wrote:
> The lanadmin (think ethtool) command of HP-UX has had a way to clear the
> statistics reported by lanadmin. I do not know however, if that affects
> the stats in the actual SNMP interface MIBs as I've never had occasion
> to look.
>
> I still suggest beforeafter to people because clearing the lanadmin
> stats requires root privs and because it may not be a kosher thing to do
> on a customer system.
>
> HP-UX does not provide a way to clear the stats reported by netstat.
Which also are snmp stats.
So far the reasoning of why this is needed has been around debugging
which is in itself reasonable as long as it doesnt break things: it
does.
For debugging: I can name about 3 ways you can achieve the counting
without touching the driver/hardware level stats. Someone needs to put
effort and create a tool to it.
[ Actually now that i spent 2 minutes looking at the patch i can
understand jgarziks concerns].
On Wed, 2006-24-05 at 16:44 -0400, Brian Haley wrote:
>So how is this different than if an SNMP station probes
> my system,then
> I reboot, then they probe again. Things will seem to have gone
> backwards, but they deal with that just fine.
>
Rick has already answered this question i hope. There are triggers that management
tools use to identify reboots.
> DEC/Compaq/HP has allowed this on Tru64 UNIX since 1999 because we had
> customers that wanted it, noone ever complained about complications with
> SNMP.
I am sure if we did things because your customer wanted it, we would approach
anarchy at best.
> We did save the last time the stats were zero'd in the struct for
> posterity, but that was never get-able via SNMP:
>
Because it is not part of the MIB i would suspect.
>
> --> netstat -I tu0 -s
>
> tu0 Ethernet counters at Wed May 24 16:30:05 2006
>
> 609415 seconds since last zeroed
> 3943458720 bytes received
> 113576310 bytes sent
> ...
>
> Maybe saving a "ztime" would make people happier?
It may be insufficient.
Management tools use the resetting as a trigger to indicate rollover of the
counters. I dont know if you can go and fix everyone out there to have this
new ztime in mind.
Can you ask internally on how openview would handle this? It carriers the
major chunk of management tools market so it may provide good insight.
On Wed, 2006-24-05 at 14:04 -0700, Rick Jones wrote:
> Phil Dibowitz wrote:
> > Well, I can show you support on my home switch (cabletron) - the network guys
> > will be a little unhappy if I clear stats on our production network (cisco)
> > without warning them:
>
> Isn't that last bit an example of why it might not be good to play-out
> that rope?-)
>
I dont mind him hanging himself, he just wants to hang us all ;->
cheers,
jamal
^ permalink raw reply
* Re: [ANNOUNCE] FLAME: external kernel module for L2.5 meshing
From: jamal @ 2006-05-25 15:38 UTC (permalink / raw)
To: Simon Oosthoek; +Cc: herman.elfrink, Stephen Hemminger, netdev
In-Reply-To: <44758CA8.2030502@fastmail.fm>
On Thu, 2006-25-05 at 12:53 +0200, Simon Oosthoek wrote:
>
> I agree with your analysis, and recently I read an interesting interview
> with her (I think it was linked from slashdot, an interview with the
> "mother of the Internet ;-) I'm not sure her work (I don't exactly
> recall the specifics) is applicable to our problem though.
>
Look at her effort ion rbridges, i think youll find theres a lot in
common.
> Regarding the scalability, I think it rather depends on the number of
> hops how usable FLAME is. I don't think it would scale well to a campus
> or city wide network, but in the case of a few mobile nodes, it has very
> little overhead both in bandwidth and delay.
You should mention this limitation in the paper.
BTW, something else: You ability to create loops of broadcast storms is
highly probable. Eventually you may have to go to L3 (TTL is of value
there) ;->
cheers,
jamal
^ permalink raw reply
* Re: reminder, 2.6.18 window...
From: Bill Fink @ 2006-05-25 16:12 UTC (permalink / raw)
To: Brent Cook; +Cc: jeff, phil, davem, netdev
In-Reply-To: <200605250805.38241.bcook@bpointsys.com>
On Thu, 25 May 2006, Brent Cook wrote:
> On Thursday 25 May 2006 02:23, Bill Fink wrote:
> > On Wed, 24 May 2006, Jeff Garzik wrote:
> > > Brent Cook wrote:
> > > > Note that this is just clearing the hardware statistics on the
> > > > interface, and would not require any kind of atomic_increment addition
> > > > for interfaces that support that. It would be kind-of awkward to
> > > > implement this on drivers that increment stats in hardware though (lo,
> > > > vlan, br, etc.) This also brings up the question of resetting the stats
> > > > for 'netstat -s'
> > >
> > > If you don't atomically clear the statistics, then you are leaving open
> > > a window where the stats could easily be corrupted, if the network
> > > interface is under load.
> > >
> > > This 'clearing' operation has implications on the rest of the statistics
> > > usage.
> > >
> > > More complexity, and breaking of apps, when we could just use the
> > > existing, working system? I'll take the "do nothing, break nothing,
> > > everything still works" route any day.
> >
> > I'll admit to not knowing all the intricacies of the kernel coding
> > involved, but I don't offhand see how zeroing the stats would be
> > significantly more complex than updating the stats during normal usage.
> > But I'll have to leave that argument to the experts.
>
> What it boils down to is that currently, a single CPU or thread ever touches
> the stats concurrently, so it doesn't have to lock them or do anything
> special to ensure that the continue incrementing. If you want to make sure
> that the statistics actually reset when you want them to, you have to account
> for this case:
>
> CPU0 reads current value from memory (increment)
> CPU1 writes 0 to current value in memory (reset)
> CPU0 writes incremented value to memory (increment complete)
>
> Check out do_add_counters() in net/ipv4/netfilter/ip_tables.c
> to see what's required to do this reliably in the kernel.
Thanks for the info. I have a possibly naive question. Would it
increase the reliability of clearing the stats using "lazy" zeroing
(no locking), if the zeroing app (ethtool) bound itself to the same
CPU that was handling interrupts for the device (assuming no sharing
of interrupts across CPUs)?
> The current patch is fine if your hardware implements the required atomicity
> itself. Otherwise, you need a locking infrastructure to extend it to all
> network devices if you want zeroing to always work. What I'm seeing here in
> response to this is that it doesn't matter if zeroing just _mostly_ works,
> which is what you would get if you didn't lock. Eh, I'm OK with that too, but
> I think people are worried about the bugs that would get filed by admins when
> just zeroing the stats on cheap NIC x only works 90% of the time, less under
> load. Or not at all (not implemented in driver.) Then you're back to the
> userspace solution or actually implement stat locking / atomic ops.
I would be fine with the "lazy" clearing of the stats (with a note
describing the limitations in the ethtool man page). Being somewhat
anal, I would always check that the stats had in fact been zeroed
successfully before proceeding. BTW I am in 100% agreement not to
do anything that would affect performance of the fast path, as I
understand proper locking would necessitate.
I will also look into the beforeafter utility that has been suggested,
to see how easy it is to use and how much extra work would be required
over just a direct visual examination of the interface statistics.
-Bill
^ permalink raw reply
* Re: [PATCH v2] bridge: fix locking and memory leak in br_add_bridge
From: Stephen Hemminger @ 2006-05-25 16:23 UTC (permalink / raw)
To: David Miller; +Cc: Jiri Benc, NetDev
In-Reply-To: <20060525161432.4cbc11ee@griffin.suse.cz>
There are several bugs in error handling in br_add_bridge:
- when dev_alloc_name fails, allocated net_device is not freed
- unregister_netdev is called when rtnl lock is held
- free_netdev is called before netdev_run_todo has a chance to be run after
unregistering net_device
This patch should fix these issues.
Minor rearrangement of to use common path of earlier patch. Dave please apply.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
--- br.orig/net/bridge/br_if.c
+++ br/net/bridge/br_if.c
@@ -301,25 +301,20 @@ int br_add_bridge(const char *name)
if (strchr(dev->name, '%')) {
ret = dev_alloc_name(dev, dev->name);
if (ret < 0)
- goto err1;
+ goto err;
}
ret = register_netdevice(dev);
if (ret)
- goto err2;
+ goto err;
ret = br_sysfs_addbr(dev);
if (ret)
- goto err3;
- rtnl_unlock();
- return 0;
-
- err3:
- unregister_netdev(dev);
- err2:
- free_netdev(dev);
- err1:
+ unregister_netdevice(dev);
+ err:
rtnl_unlock();
+ if (ret)
+ free_netdev(dev);
return ret;
}
^ permalink raw reply
* Re: [PATCH 1/9] Resending NetXen 1G/10G NIC driver patch
From: Stephen Hemminger @ 2006-05-25 16:33 UTC (permalink / raw)
To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj
In-Reply-To: <Pine.LNX.4.33.0605250347050.5844-100000@unmsrvr>
Minor nits.
On Thu, 25 May 2006 03:48:38 -0700 (PDT)
"Linsys Contractor Amit S. Kale" <amitkale@unminc.com> wrote:
> +/*
> + * Note: This change will be reflected in all the four ports as there is
> + * only one common adapter.
> + */
> +static int
> +netxen_nic_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
> +{
> + return 0;
> +}
Why not just return have no hook if you can't set parameters. Then the ioctl
will return not supported -EOPNOTSUPP
>
> +static u32 netxen_nic_get_rx_csum(struct net_device *dev)
> +{
> + return (dev->features & NETIF_F_HW_CSUM);
> +}
You got receive and transmit checksum confused. You need to separate
checksumming on output (dev->features & NETIF_F_HW_CSUM) versus receive
checksum (controlled by hardware and usually a flag in private data structure).
> +static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
> +{
> + if (data)
> + dev->features |= NETIF_F_HW_CSUM;
> + else
> + dev->features &= (~NETIF_F_HW_CSUM);
> +
> + if (netif_running(dev)) {
> + dev->stop(dev); /* verify */
> + dev->open(dev);
What if open fail fails? Then you have an "interesting" recovery
situation.
> + }
> + return 0;
> +}
>
^ permalink raw reply
* Re: [PATCH 2/9] Resending NetXen 1G/10G NIC driver patch
From: Stephen Hemminger @ 2006-05-25 16:42 UTC (permalink / raw)
To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj
In-Reply-To: <Pine.LNX.4.33.0605250349110.5844-100000@unmsrvr>
On Thu, 25 May 2006 03:51:03 -0700 (PDT)
"Linsys Contractor Amit S. Kale" <amitkale@unminc.com> wrote:
> diff -Naru linux-2.6.16.18.orig/drivers/net/netxen/netxen_nic.h linux-2.6.16.18/drivers/net/netxen/netxen_nic.h
> --- linux-2.6.16.18.orig/drivers/net/netxen/netxen_nic.h 1969-12-31 16:00:00.000000000 -0800
> +++ linux-2.6.16.18/drivers/net/netxen/netxen_nic.h 2006-05-25 02:43:22.000000000 -0700
> @@ -0,0 +1,950 @@
>
> +#define IP_ALIGNMENT_BYTES 2 /* make ip aligned on 16 bytes addr */
Please use NET_IP_ALIGN, it does the right architecture dependent
offset.
...
> +#define NETXEN_PCI_ID(X) { PCI_DEVICE(PCI_VENDOR_ID_NX, (X)) }
Nested macro's on macro's, just use PCI_DEVICE()
> +
> +#define PFX "netxen: "
> +
> +/* Note: Make sure to not call this before adapter->port is valid */
> +#if !defined(NETXEN_DEBUG)
> +#define DPRINTK(klevel, fmt, args...) do { \
> + } while (0)
> +#else
> +#define DPRINTK(klevel, fmt, args...) do { \
> + printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\
> + (adapter != NULL && adapter->port != NULL && \
> + adapter->port[0] != NULL && \
> + adapter->port[0]->netdev != NULL) ? \
> + adapter->port[0]->netdev->name : NULL, \
> + ## args); } while(0)
> +#endif
> +
Ugh. Macro with magic variable. if you need to keep this, pass adapter.
> +struct netdev_list {
> + struct netdev_list *next;
> + struct net_device *netdev;
> +};
Why not use regular list.h or simple linked list. Even better
figure out how to not need need "list of devices at all"
> +struct netxen_port_hw {
> + unsigned char mac_addr[MAX_ADDR_LEN];
> + int mtu;
> + struct pci_dev *pdev;
> + struct netxen_port *port;
> +};
Isn't mtu redundant with dev->mtu and mac_addr redundant
with dev->dev_addr
> +/* Following structure is for specific port information */
> +
> +#define NETXEN_PORT_UP 0
> +#define NETXEN_PORT_DOWN 1
> +#define NETXEN_PORT_INITIALIAZED 2
> +#define NETXEN_PORT_SUSPEND 3
Don't mirror port state with netdevice state because you risk
getting the two out of sync. Isn't this redundant with
netif_running()
^ permalink raw reply
* Re: reminder, 2.6.18 window...
From: Rick Jones @ 2006-05-25 16:43 UTC (permalink / raw)
To: hadi; +Cc: Jeff Garzik, David Miller, netdev, Phil Dibowitz
In-Reply-To: <1148570852.5283.23.camel@jzny2>
> Can you ask internally on how openview would handle this? It carriers the
> major chunk of management tools market so it may provide good insight.
I've asked the question in an internal, informal communications channel.
No guarantees it will reach any OpenView types, but if it does I'll
try to provide the gist of the replies.
rick jones
^ permalink raw reply
* Re: [PATCH 8/9] Resending NetXen 1G/10G NIC driver patch
From: Roland Dreier @ 2006-05-25 16:44 UTC (permalink / raw)
To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj
In-Reply-To: <Pine.LNX.4.33.0605250356420.5844-100000@unmsrvr>
> +static int __devinit
> +netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> +#if defined(CONFIG_PCI_MSI)
> + adapter->flags |= NETXEN_NIC_MSI_ENABLED;
> + if (pci_enable_msi(pdev)) {
> + adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
> + printk(KERN_WARNING "%s: unable to allocate MSI interrupt"
> + " error\n", netxen_nic_driver_name);
> + }
> +#endif
No need for the #ifdef -- pci_enable_msi() is stubbed out so it will
always just return failure if CONFIG_PCI_MSI is not set.
> + adapterlist[netxen_cards_found++] = adapter;
> + adapter->number = netxen_cards_found;
Having a static array of adapters is a bad idea. Just allocate a
data structure for each card as you probe it.
- R.
^ permalink raw reply
* Re: [PATCH 6/9] Resending NetXen 1G/10G NIC driver patch
From: Stephen Hemminger @ 2006-05-25 16:47 UTC (permalink / raw)
To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj
In-Reply-To: <Pine.LNX.4.33.0605250355260.5844-100000@unmsrvr>
Why is this necessary. Additional private API seems like leftover
debug code.
> +int
> +netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data,
> + struct netxen_port *port)
> +{
> + struct netxen_nic_ioctl_data data;
> + struct netxen_nic_ioctl_data *up_data;
> + int retval = 0;
> + struct netxen_statistics netxen_stats;
> +
> + up_data = (void *)u_data;
> +
> + DPRINTK(INFO, "doing ioctl for %p\n", adapter);
> + if (copy_from_user(&data, up_data, sizeof(data))) {
> + /* evil user tried to crash the kernel */
> + DPRINTK(ERR, "bad copy from userland: %d\n", (int)sizeof(data));
> + retval = -EFAULT;
> + goto error_out;
> + }
> +
> + /* Shouldn't access beyond legal limits of "char u[64];" member */
> + if (!data.ptr && (data.size > sizeof(data.u))) {
> + /* evil user tried to crash the kernel */
> + DPRINTK(ERR, "bad size: %d\n", data.size);
> + retval = -EFAULT;
> + goto error_out;
> + }
> +
> + switch (data.cmd) {
> + case netxen_nic_cmd_pci_read:
> + if ((retval = netxen_nic_hw_read_wx(adapter, data.off,
> + &(data.u), data.size)))
> + goto error_out;
> + if (copy_to_user((void *)&(up_data->u), &(data.u), data.size)) {
> + DPRINTK(ERR, "bad copy to userland: %d\n",
> + (int)sizeof(data));
> + retval = -EFAULT;
> + goto error_out;
> + }
> + data.rv = 0;
> + break;
> +
Can't you access the same registers area with ethtool.
> + case netxen_nic_cmd_pci_write:
> + data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u),
> + data.size);
> + break;
> +
> + case netxen_nic_cmd_pci_mem_read:
> + DPRINTK(INFO, "doing %s for %p\n",
> + "netxen_nic_cmd_pci_mm_rd", adapter);
> + netxen_nic_pci_mem_read(adapter, data.off, &(data.u),
> + data.size);
> + if (copy_to_user((void *)&(up_data->u), &(data.u), data.size)) {
> + DPRINTK(ERR, "bad copy to userland: %d\n",
> + (int)sizeof(data));
> + retval = -EFAULT;
> + goto error_out;
> + }
> + data.rv = 0;
> + DPRINTK(INFO, "read %lx\n", (unsigned long)data.u);
> + break;
PCI memory is accessible directly through sysfs for diagnostic tools.
> + case netxen_nic_cmd_pci_mem_write:
> + netxen_nic_pci_mem_write(adapter, data.off, &(data.u),
> + data.size);
> + data.rv = 0; /* write always succeeds */
> + break;
> +
> + case netxen_nic_cmd_pci_config_read:
> + switch (data.size) {
> + case 1:
> + data.rv = pci_read_config_byte(adapter->ahw.pdev,
> + data.off,
> + (char *)&(data.u));
> + break;
> + case 2:
> + data.rv = pci_read_config_word(adapter->ahw.pdev,
> + data.off,
> + (short *)&(data.u));
> + break;
> + case 4:
> + data.rv = pci_read_config_dword(adapter->ahw.pdev,
> + data.off,
> + (u32 *) & (data.u));
> + break;
> + }
> + if (copy_to_user((void *)&(up_data->u), &(data.u), data.size)) {
> + DPRINTK(ERR, "bad copy to userland: %d\n",
> + (int)sizeof(data));
> + retval = -EFAULT;
> + goto error_out;
> + }
> + break;
> +
> + case netxen_nic_cmd_pci_config_write:
> + switch (data.size) {
> + case 1:
> + data.rv = pci_write_config_byte(adapter->ahw.pdev,
> + data.off,
> + *(char *)&(data.u));
> + break;
> + case 2:
> + data.rv = pci_write_config_word(adapter->ahw.pdev,
> + data.off,
> + *(short *)&(data.u));
> + break;
> + case 4:
> + data.rv = pci_write_config_dword(adapter->ahw.pdev,
> + data.off,
> + *(u32 *) & (data.u));
> + break;
> + }
> + break;
> +
> + case netxen_nic_cmd_get_stats:
> + data.rv =
> + netxen_nic_fill_statistics(adapter, port, &netxen_stats);
> + if (copy_to_user
> + ((void *)(up_data->ptr), (void *)&netxen_stats,
> + sizeof(struct netxen_statistics))) {
> + DPRINTK(ERR, "bad copy to userland: %d\n",
> + (int)sizeof(netxen_stats));
> + retval = -EFAULT;
> + goto error_out;
> + }
> + up_data->rv = data.rv;
> + break;
> +
> + case netxen_nic_cmd_clear_stats:
> + data.rv = netxen_nic_clear_statistics(adapter, port);
> + up_data->rv = data.rv;
> + break;
> +
> + case netxen_nic_cmd_get_version:
> + if (copy_to_user
> + ((void *)&(up_data->u), NETXEN_NIC_LINUX_VERSIONID,
> + sizeof(NETXEN_NIC_LINUX_VERSIONID))) {
> + DPRINTK(ERR, "bad copy to userland: %d\n",
> + (int)sizeof(data));
> + retval = -EFAULT;
> + goto error_out;
> + }
> + break;
> +
> + default:
> + DPRINTK(INFO, "bad command %d for %p\n", data.cmd, adapter);
> + retval = -EOPNOTSUPP;
> + goto error_out;
> + }
> + put_user(data.rv, &(up_data->rv));
> + DPRINTK(INFO, "done ioctl for %p well.\n", adapter);
> +
> + error_out:
> + return retval;
> +}
>
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 8/9] Resending NetXen 1G/10G NIC driver patch
From: Stephen Hemminger @ 2006-05-25 17:03 UTC (permalink / raw)
To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj
In-Reply-To: <Pine.LNX.4.33.0605250356420.5844-100000@unmsrvr>
The object factoring is a mess here. You have too many allocations
and indirections. My expectation would be:
1. One PCI device maps to one board and that is the adapter structure
allocated with kzalloc. (You are doing this right)
2. An adapter can have up to four ports. Each of these should be a
netdevice and any port specific memory should be part of netdev_priv().
3. Have an array of pointers in the adapter structure for the maximum
possible value, if the board has less the memory waste for three
extra pointers is less than cost of dynamically sized array.
Something like
pci_prvdata -> adapter --> dev[0] -> netdevice { private data }
--> dev[1] ...
or
pci_privdata -> adapter -> port[0] -> private data
-> port[1]
In the later case, you need to have port->netdev pointer back to the
start of the net_device data structure.
If you do it this way, you won't need:
> + adapter->port = kcalloc(adapter->ahw.max_ports,
> + sizeof(struct netxen_adapter), GFP_KERNEL);
and
> + netlist = kzalloc(sizeof(struct netdev_list), GFP_KERNEL);
> + if (netlist == NULL)
> + goto err_out_free_dev;
Also, do you really need to have such a big TX ring that it requires
a vmalloc?
^ permalink raw reply
* Re: [PATCH 9/9] Resending NetXen 1G/10G NIC driver patch
From: Stephen Hemminger @ 2006-05-25 17:19 UTC (permalink / raw)
To: Linsys Contractor Amit S. Kale; +Cc: netdev, sanjeev, unmproj
In-Reply-To: <Pine.LNX.4.33.0605250357330.5844-100000@unmsrvr>
> +void netxen_delay(int value)
> +{
> + unsigned long remainder;
> +
> + remainder = value / 50000;
> + do {
> + if (remainder > 1000) {
> + udelay(1000);
> + remainder -= 1000;
> + } else {
> + udelay(remainder + 1);
> + remainder = 0;
> + }
> + } while (remainder > 0);
> +}
> +
Defined, but never used. Why not just use mdelay if you
really are waiting that long?
+
+
+/**
+ * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC
+ *
+ **/
+void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter,
+ long port, long enable)
+{
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x80000000);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x0000f0025);
+ netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port),
+ 0xf1ff);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB0_MII_MODE + (port << 3), 1);
+ netxen_crb_writelit_adapter(adapter,
+ (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7);
+
+ if (enable) {
+ /*
+ * Do NOT enable flow control until a suitable solution for
+ * shutting down pause frames is found.
+ */
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ 0x5);
+ }
+
>
> + if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
> + printk("<1>ERROR enabling PHY interrupts\n");
Please use KERN_ERR not <1>
> + if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
> + printk("<1>ERROR clearing PHY interrupts\n");
> +}
> +
> +long netxen_niu_gbe_init_port(struct netxen_adapter *adapter, long port)
> +{
> + long result = 0;
> + struct netxen_niu_phy_status status;
> +
> + if (0 ==
> + netxen_niu_gbe_phy_read(adapter, port,
> + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
> + (netxen_crbword_t *) & status)) {
You seem to like the style:
if (0 == foo())
It is not the current kernel fashion, but I'm okay with it.
> + if (status.link) {
> + if (status.speed == 2) {
> + netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
> + } else if ((status.speed == 1) || (status.speed == 0)) {
> + netxen_niu_gbe_set_mii_mode(adapter, port, 1);
> + } else {
> + result = -1;
> + }
> +
> + } else {
> + /* We don't have link. Cable must be unconnected. */
> + /* Enable phy interrupts so we take action when plugged in */
> + netxen_crb_writelit_adapter(adapter,
> + NETXEN_NIU_GB_MAC_CONFIG_0
> + (port), 0x80000000);
> + netxen_crb_writelit_adapter(adapter,
> + NETXEN_NIU_GB_MAC_CONFIG_0
> + (port), 0x0000f0025);
> + if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
> + printk("<1>ERROR clearing PHY interrupts\n");
> + if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
> + printk("<1>ERROR enabling PHY interrupts\n");
> + if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
> + printk("<1>ERROR clearing PHY interrupts\n");
> + result = -1;
> + }
> + } else {
> + result = -1;
> + }
> + return result;
> +}
Wouldn't this just be clearer with:
long netxen_niu_gbe_init_port(struct netxen_adapter *adapter, long port)
{
int err;
struct netxen_niu_phy_status status;
err = netxen_niu_gbe_phy_read(adapter, port,
NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
(netxen_crbword_t *) & status);
if (err)
return err;
if (status.link) {
if (status.speed == 2)
netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
else if ((status.speed == 1) || (status.speed == 0))
netxen_niu_gbe_set_mii_mode(adapter, port, 1);
else
return -EINVAL;
return 0;
}
/* We don't have link. Cable must be unconnected. */
/* Enable phy interrupts so we take action when plugged in */
netxen_crb_writelit_adapter(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0
(port), 0x80000000);
netxen_crb_writelit_adapter(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0
(port), 0x0000f0025);
if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
printk(KERN_ERR PFX "error clearing PHY interrupts\n");
if (netxen_niu_gbe_enable_phy_interrupts(adapter, port))
printk(KERN_ERR PFX "error enabling PHY interrupts\n");
if (netxen_niu_gbe_clear_phy_interrupts(adapter, port))
printk(KERN_ERR PFX "error clearing PHY interrupts\n");
return -ENOTCONNECTED;
}
> +
> +/**
> + * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts
> + * @param enable 0 means don't enable the port
> + * 1 means enable (or re-enable) the port
> + **/
> +long netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
> + long port, long enable)
> +{
> + long result = 0;
> + struct netxen_niu_phy_interrupt int_src;
> +
> + printk
> + ("<1>NETXEN: Handling PHY interrupt on port %d (device enable = %d)\n",
> + (int)port, (int)enable);
> +
> + /* The read of the PHY INT status will clear the pending interrupt status */
> + if (netxen_niu_gbe_phy_read(adapter, port,
> + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
> + (netxen_crbword_t *) & int_src) != 0)
> + result = -1;
> + else {
> + printk("<1>PHY Interrupt source = 0x%x \n", *(u32 *) & int_src);
These are debug messages, not a KERN_CRITICAL message..
> + if (int_src.jabber)
> + printk("<1>jabber Interrupt ");
> + if (int_src.polarity_changed)
> + printk("<1>polarity changed ");
> + if (int_src.energy_detect)
> + printk("<1>energy detect \n");
> + if (int_src.downshift)
> + printk("<1>downshift \n");
> + if (int_src.mdi_xover_changed)
> + printk("<1>mdi_xover_changed ");
> + if (int_src.fifo_over_underflow)
> + printk("<1>fifo_over_underflow ");
> + if (int_src.false_carrier)
> + printk("<1>false_carrier ");
> + if (int_src.symbol_error)
> + printk("<1>symbol_error ");
> + if (int_src.autoneg_completed)
> + printk("<1>autoneg_completed ");
> + if (int_src.page_received)
> + printk("<1>page_received ");
> + if (int_src.duplex_changed)
> + printk("<1>duplex_changed ");
> + if (int_src.autoneg_error)
> + printk("<1>autoneg_error ");
> + if ((int_src.speed_changed) || (int_src.link_status_changed)) {
> + struct netxen_niu_phy_status status;
> +
> + printk("<1>speed_changed or link status changed");
> + if (netxen_niu_gbe_phy_read(adapter, port,
> + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
> + (netxen_crbword_t *) &
> + status) == 0) {
> + printk("<1>\n");
> + if (status.speed == 2) {
> + printk
> + ("<1>Link speed changed to 1000 Mbps\n");
> + netxen_niu_gbe_set_gmii_mode(adapter,
> + port,
> + enable);
> + } else if (status.speed == 1) {
> + printk
> + ("<1>Link speed changed to 100 Mbps\n");
> + netxen_niu_gbe_set_mii_mode(adapter,
> + port,
> + enable);
> + } else if (status.speed == 0) {
> + printk
> + ("<1>Link speed changed to 10 Mbps\n");
> + netxen_niu_gbe_set_mii_mode(adapter,
> + port,
> + enable);
> + } else {
> + printk
> + ("<1>ERROR reading PHY status. Illegal speed.\n");
> + result = -1;
> + }
> + } else {
> + printk("<1>ERROR reading PHY status.\n");
> + result = -1;
> + }
> +
> + }
> + printk("<1>\n");
> + }
> + return result;
> +}
> +
> +/**
> + * Return the current station MAC address.
> + * Note that the passed-in value must already be in network byte order.
> + **/
> +int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
> + int phy, netxen_ethernet_macaddr_t * addr)
> +{
> + u64 result = 0;
> + struct netxen_niu_gb_station_address_high stationhigh;
> + struct netxen_niu_gb_station_address_low stationlow;
> +
> + if (addr == NULL)
> + return -1;
> + if ((phy < 0) || (phy > 3))
> + return -1;
> +
> + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
> + &stationhigh, 4))
> + return -1;
> + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
> + &stationlow, 4))
> + return -1;
> +
> + result = (u64) stationlow.address;
> + result |= (u64) stationhigh.address << 16;
> + memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
> +
> + return 0;
> +}
> +
> +/**
> + * Set the station MAC address.
> + * Note that the passed-in value must already be in network byte order.
> + **/
> +int netxen_niu_macaddr_set(struct netxen_adapter *adapter, int phy,
> + netxen_ethernet_macaddr_t addr)
> +{
> + netxen_crbword_t temp = 0;
> +
> + if ((phy < 0) || (phy > 3))
> + return -1;
> +
> + memcpy(&temp, addr, 2);
> + temp <<= 16;
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
> + &temp, 4))
> + return -1;
> +
> + temp = 0;
> +
> + memcpy(&temp, ((u8 *) addr) + 2, sizeof(netxen_crbword_t));
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
> + &temp, 4))
> + return -2;
Please use -ERRNO style returns.
> +
> + return 0;
> +}
> +
> +/* Enable a GbE interface */
> +long netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
> + long port, netxen_niu_gbe_ifmode_t mode)
> +{
> + struct netxen_niu_gb_mac_config_0_t mac_cfg0;
> + struct netxen_niu_gb_mac_config_1_t mac_cfg1;
> + struct netxen_niu_gb_mii_mgmt_config mii_cfg;
> +
> + if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
> + return -1;
> +
> + *(netxen_crbword_t *) & mac_cfg0 = 0;
> + mac_cfg0.soft_reset = 1;
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
> + &mac_cfg0, 4))
> + return -1;
> + *(netxen_crbword_t *) & mac_cfg0 = 0;
> + mac_cfg0.tx_enable = 1;
> + mac_cfg0.rx_enable = 1;
> + mac_cfg0.rx_flowctl = 0;
> + mac_cfg0.tx_reset_pb = 1;
> + mac_cfg0.rx_reset_pb = 1;
> + mac_cfg0.tx_reset_mac = 1;
> + mac_cfg0.rx_reset_mac = 1;
> +
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
> + &mac_cfg0, 4))
> + return -1;
> + *(netxen_crbword_t *) & mac_cfg1 = 0;
> + mac_cfg1.preamblelen = 0xf;
> + mac_cfg1.duplex = 1;
> + mac_cfg1.crc_enable = 1;
> + mac_cfg1.padshort = 1;
> + mac_cfg1.checklength = 1;
> + mac_cfg1.hugeframes = 1;
> +
> + if (mode == NETXEN_NIU_10_100_MB) {
> + mac_cfg1.intfmode = 1;
> + if (netxen_nic_hw_write_wx(adapter,
> + NETXEN_NIU_GB_MAC_CONFIG_1(port),
> + &mac_cfg1, 4))
> + return -1;
> +
> + /* set mii mode */
> + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
> + (port << 3), 0);
> + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
> + (port << 3), 1);
> +
> + } else if (mode == NETXEN_NIU_1000_MB) {
> + mac_cfg1.intfmode = 2;
> + if (netxen_nic_hw_write_wx(adapter,
> + NETXEN_NIU_GB_MAC_CONFIG_1(port),
> + &mac_cfg1, 4))
> + return -1;
> + /* set gmii mode */
> + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE +
> + (port << 3), 0);
> + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE +
> + (port << 3), 1);
> + }
> + *(netxen_crbword_t *) & mii_cfg = 0;
> + mii_cfg.clockselect = 7;
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
> + &mii_cfg, 4))
> + return -1;
> +
> + *(netxen_crbword_t *) & mac_cfg0 = 0;
> + mac_cfg0.tx_enable = 1;
> + mac_cfg0.rx_enable = 1;
> + mac_cfg0.tx_flowctl = 0;
> + mac_cfg0.rx_flowctl = 0;
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
> + &mac_cfg0, 4))
> + return -1;
> + return 0;
> +}
> +
> +/* Disable a GbE interface */
> +long netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, long port)
> +{
> + struct netxen_niu_gb_mac_config_0_t mac_cfg0;
> +
> + if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
> + return -1;
return -EINVAL?
> +
> + *(netxen_crbword_t *) & mac_cfg0 = 0;
> + mac_cfg0.soft_reset = 1;
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
> + &mac_cfg0, 4))
> + return -1;
> + return 0;
how about just
return netxen_nic_hw_write_wx(...)
> +}
> +
> +/* Disable an XG interface */
> +long netxen_niu_disable_xg_port(struct netxen_adapter *adapter, long port)
> +{
> + struct netxen_niu_xg_mac_config_0_t mac_cfg;
> +
> + if (port != 0)
> + return -1;
> +
> + *(netxen_crbword_t *) & mac_cfg = 0;
> + mac_cfg.soft_reset = 1;
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_CONFIG_0,
> + &mac_cfg, 4))
> + return -1;
> + return 0;
> +}
> +
> +/* Set promiscuous mode for a GbE interface */
> +long netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, long port,
> + netxen_niu_prom_mode_t mode)
> +{
> + struct netxen_niu_gb_drop_crc reg;
> + long data;
> +
> + if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
> + return -1;
> +
> + if (mode == NETXEN_NIU_PROMISCOUS_MODE)
> + data = 0;
> + else
> + data = 1;
> +
> + /* save previous contents */
> + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
> + ®, 4))
> + return -1;
> + switch (port) {
> + case 0:
> + reg.drop_gb0 = data;
> + break;
> + case 1:
> + reg.drop_gb0 = data;
> + break;
> + case 2:
> + reg.drop_gb0 = data;
> + break;
> + case 3:
> + reg.drop_gb0 = data;
> + break;
> + default:
> + return -1;
> + }
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
> + ®, 4))
> + return -1;
> + return 0;
> +}
> +
> +/**
> + * Set the MAC address for an XG port
> + * Note that the passed-in value must already be in network byte order.
> + **/
> +int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, int phy,
> + netxen_ethernet_macaddr_t addr)
> +{
> + netxen_crbword_t temp = 0;
> +
> + if ((phy < 0) || (phy > 3))
> + return -1;
> +
> + memcpy(&temp, addr, 2);
> + temp <<= 16;
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
> + &temp, 4))
> + return -1;
> +
> + temp = 0;
> +
> + memcpy(&temp, ((u8 *) addr) + 2, sizeof(netxen_crbword_t));
> + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
> + &temp, 4))
> + return -1;
> +
> + return 0;
> +}
> +
> +/**
> + * Return the current station MAC address.
> + * Note that the passed-in value must already be in network byte order.
> + **/
> +int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
> + netxen_ethernet_macaddr_t * addr)
> +{
> + netxen_crbword_t stationhigh;
> + netxen_crbword_t stationlow;
> + u64 result;
> +
> + if (addr == NULL)
> + return -1;
> + if (phy != 0)
> + return -1;
> +
> + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
> + &stationhigh, 4))
> + return -1;
> + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
> + &stationlow, 4))
> + return -1;
> +
> + result = ((u64) stationlow) >> 16;
> + result |= (u64) stationhigh << 16;
> + memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
> +
> + return 0;
> +}
> +
> +long netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
> + long port, netxen_niu_prom_mode_t mode)
> +{
> + long reg;
> +
> + if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
> + return -1;
> +
> + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_CONFIG_1, ®, 4))
> + return -1;
> + if (mode == NETXEN_NIU_PROMISCOUS_MODE)
> + reg = (reg | 0x2000UL);
> + else
> + reg = (reg & ~0x2000UL);
> +
> + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_XGE_CONFIG_1, reg);
> +
> + return 0;
> +}
>
^ permalink raw reply
* Re: reminder, 2.6.18 window...
From: Phil Dibowitz @ 2006-05-25 17:59 UTC (permalink / raw)
To: Brent Cook; +Cc: Bill Fink, Jeff Garzik, davem, netdev
In-Reply-To: <200605250805.38241.bcook@bpointsys.com>
[-- Attachment #1: Type: text/plain, Size: 1792 bytes --]
On Thu, May 25, 2006 at 08:05:37AM -0500, Brent Cook wrote:
> > I'll admit to not knowing all the intricacies of the kernel coding
> > involved, but I don't offhand see how zeroing the stats would be
> > significantly more complex than updating the stats during normal usage.
> > But I'll have to leave that argument to the experts.
> >
>
> What it boils down to is that currently, a single CPU or thread ever touches
> the stats concurrently, so it doesn't have to lock them or do anything
> special to ensure that the continue incrementing. If you want to make sure
> that the statistics actually reset when you want them to, you have to account
> for this case:
>
> CPU0 reads current value from memory (increment)
> CPU1 writes 0 to current value in memory (reset)
> CPU0 writes incremented value to memory (increment complete)
Perhaps I'm missing something here, but these counters are only incrimented
in hardware... i.e. attomically.
And the reset I do is via a command register, which should also be atomic.
Now in a driver that was keeping this all in a local struct, I could
understand that need for locking, but in the skge case, and in fact in many
drivers I've looked at, the numbers are all kept in the hardware, incremented
by the hardware, as it gets packets.
So clearing them via command registershouldn't need locking as far as I can
tell.
But please, correct me if I'm wrong.
--
Phil Dibowitz phil@ipom.com
Freeware and Technical Pages Insanity Palace of Metallica
http://www.phildev.net/ http://www.ipom.com/
"They that can give up essential liberty to obtain a little temporary
safety deserve neither liberty nor safety."
- Benjamin Franklin, 1759
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 1/9] [I/OAT] DMA memcpy subsystem
From: Olof Johansson @ 2006-05-25 17:59 UTC (permalink / raw)
To: Chris Leech; +Cc: linux-kernel, netdev
In-Reply-To: <20060524002012.19403.50151.stgit@gitlost.site>
Hi,
On Tue, May 23, 2006 at 05:20:12PM -0700, Chris Leech wrote:
> +EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
> +EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
> +EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
Is there a specific reason for why you chose to export 3 different
memcpu calls? They're all just wrapped to the same internals.
It would seem to make sense to have the client do their own
page_address(page) + offset calculations and just export one function?
-Olof
^ permalink raw reply
* Re: [PATCH 2/9] [I/OAT] Driver for the Intel(R) I/OAT DMA engine
From: Olof Johansson @ 2006-05-25 18:00 UTC (permalink / raw)
To: Chris Leech; +Cc: linux-kernel, netdev
In-Reply-To: <20060524002013.19403.57410.stgit@gitlost.site>
Hi,
Minor nitpick below:
On Tue, May 23, 2006 at 05:20:13PM -0700, Chris Leech wrote:
> +static int enumerate_dma_channels(struct ioat_device *device)
[...]
> + enumerate_dma_channels(device);
Return value is never used, might as well change the function
declaration to void.
-Olof
^ permalink raw reply
* Re: [PATCH 3/4] [IrDA] stir4200, switching to the kthread API
From: Stephen Hemminger @ 2006-05-25 18:01 UTC (permalink / raw)
To: Samuel Ortiz; +Cc: David S. Miller, netdev, irda-users, hch
In-Reply-To: <20060525061944.GC24611@sortiz.org>
On Thu, 25 May 2006 06:19:44 +0000
Samuel Ortiz <samuel@sortiz.org> wrote:
> stir4200 uses a kernel thread for its TX/RX operations, and it is now
> converted to the kernel kthread API.
> Tested on an STIR4200 based dongle.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
>
Looks fine.
^ permalink raw reply
* [PATCH] arlan: fix section mismatch warnings
From: Randy.Dunlap @ 2006-05-25 18:10 UTC (permalink / raw)
To: ismail, linville; +Cc: netdev, akpm
From: Randy Dunlap <rdunlap@xenotime.net>
Fix section mismatch warnings:
WARNING: drivers/net/wireless/arlan.o - Section mismatch: reference to
.init.text:arlan_probe from .text between 'init_module' (at offset
0x3526) and 'cleanup_module'
WARNING: drivers/net/wireless/arlan.o - Section mismatch: reference to
.init.text:init_arlan_proc from .text between 'init_module' (at offset
0x3539) and 'cleanup_module'
WARNING: drivers/net/wireless/arlan.o - Section mismatch: reference to
.exit.text:cleanup_arlan_proc from .text between 'cleanup_module' (at
offset 0x356c) and 'arlan_diagnostic_info_string'
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
---
drivers/net/wireless/arlan-main.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
--- linux-2617-rc5.orig/drivers/net/wireless/arlan-main.c
+++ linux-2617-rc5/drivers/net/wireless/arlan-main.c
@@ -1838,7 +1838,7 @@ struct net_device * __init arlan_probe(i
}
#ifdef MODULE
-int init_module(void)
+int __init init_module(void)
{
int i = 0;
@@ -1860,7 +1860,7 @@ int init_module(void)
}
-void cleanup_module(void)
+void __exit cleanup_module(void)
{
int i = 0;
struct net_device *dev;
---
^ permalink raw reply
* [PATCH] wavelan: fix section mismatch
From: Randy.Dunlap @ 2006-05-25 18:09 UTC (permalink / raw)
To: ismail, jt; +Cc: linville, netdev, akpm
From: Randy Dunlap <rdunlap@xenotime.net>
Fix section mismatch warning:
WARNING: drivers/net/wireless/wavelan.o - Section mismatch: reference to
.init.text: from .text between 'init_module' (at offset 0x371e) and
'cleanup_module'
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
---
drivers/net/wireless/wavelan.c | 2 +-
1 files changed, 1 insertion(+), 1 deletion(-)
--- linux-2617-rc5.orig/drivers/net/wireless/wavelan.c
+++ linux-2617-rc5/drivers/net/wireless/wavelan.c
@@ -4306,7 +4306,7 @@ out:
* Insertion of the module
* I'm now quite proud of the multi-device support.
*/
-int init_module(void)
+int __init init_module(void)
{
int ret = -EIO; /* Return error if no cards found */
int i;
---
^ permalink raw reply
* Re: [PATCH 1/9] [I/OAT] DMA memcpy subsystem
From: Olof Johansson @ 2006-05-25 18:09 UTC (permalink / raw)
To: Chris Leech; +Cc: linux-kernel, netdev
In-Reply-To: <20060525175940.GB9867@pb15.lixom.net>
On Thu, May 25, 2006 at 10:59:40AM -0700, Olof Johansson wrote:
> Is there a specific reason for why you chose to export 3 different
> memcpu calls? They're all just wrapped to the same internals.
>
> It would seem to make sense to have the client do their own
> page_address(page) + offset calculations and just export one function?
Nevermind. I'm too used to 64-bit environments where all memory is
always addressable to the kernel. There's obvious reasons to do it on
32-bit platforms to avoid the extra kernel mapping.
-Olof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox