Commit afe1ba38 authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/garz/repo/linus-2.5

into redhat.com:/garz/repo/net-drivers-2.5
parents 09c49f76 8d7a36f3
......@@ -18,7 +18,8 @@ dev->open:
dev->stop:
Synchronization: rtnl_lock() semaphore.
Context: process
Notes: netif_running() is guaranteed false when this is called
Note1: netif_running() is guaranteed false
Note2: dev->poll() is guaranteed to be stopped
dev->do_ioctl:
Synchronization: rtnl_lock() semaphore.
......@@ -31,10 +32,12 @@ dev->get_stats:
dev->hard_start_xmit:
Synchronization: dev->xmit_lock spinlock.
Context: BHs disabled
Notes: netif_queue_stopped() is guaranteed false
dev->tx_timeout:
Synchronization: dev->xmit_lock spinlock.
Context: BHs disabled
Notes: netif_queue_stopped() is guaranteed true
dev->set_multicast_list:
Synchronization: dev->xmit_lock spinlock.
......
......@@ -153,19 +153,5 @@ config PCMCIA_IBMTR
The module will be called ibmtr_cs. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
config AIRONET4500_CS
tristate "Aironet 4500/4800 PCMCIA support"
depends on NET_PCMCIA_RADIO && AIRONET4500 && PCMCIA
help
Say Y here if you have a PCMCIA Aironet 4500/4800 card which you
want to use with the standard PCMCIA cardservices provided by the
pcmcia-cs package.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called aironet4500_cs. If you want to
compile it as a module, say M here and read
<file:Documentation/modules.txt>.
endmenu
......@@ -13,7 +13,4 @@ obj-$(CONFIG_PCMCIA_XIRC2PS) += xirc2ps_cs.o
obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o
# 16-bit wireless client drivers
obj-$(CONFIG_AIRONET4500_CS) += aironet4500_cs.o
obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o
/*
* Aironet 4500 Pcmcia driver
*
* Elmer Joandi, Januar 1999
* Copyright Elmer Joandi, all rights restricted
*
*
* Revision 0.1 ,started 30.12.1998
*
*
*/
#define DRV_NAME "aironet4500_cs"
#define DRV_VERSION "0.1"
static const char *awc_version =
DRV_NAME ".c v" DRV_VERSION " 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ioport.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include "../aironet4500.h"
static u_int irq_mask = 0x5eF8;
static int awc_ports[] = {0x140,0x100,0xc0, 0x80 };
#if LINUX_VERSION_CODE > 0x20100
MODULE_PARM(irq_mask, "i");
#endif
#define RUN_AT(x) (jiffies+(x))
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define PC_DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"aironet4500_cs.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
#else
#define PC_DEBUG(n, args...)
#endif
/* Index of functions. */
static dev_info_t dev_info = "aironet4500_cs";
static dev_link_t *awc_attach(void);
static void awc_detach(dev_link_t *);
static void awc_release(u_long arg);
static int awc_event(event_t event, int priority,
event_callback_args_t *args);
static dev_link_t *dev_list;
static void cs_error(client_handle_t handle, int func, int ret)
{
#if CS_RELEASE_CODE < 0x2911
CardServices(ReportError, dev_info, (void *)func, (void *)ret);
#else
error_info_t err = { func, ret };
CardServices(ReportError, handle, &err);
#endif
}
#define CFG_CHECK(fn, args...) if (CardServices(fn, args) != 0) goto next_entry
static void flush_stale_links(void)
{
dev_link_t *link, *next;
for (link = dev_list; link; link = next) {
next = link->next;
if (link->state & DEV_STALE_LINK)
awc_detach(link);
}
}
/*
We never need to do anything when a awc device is "initialized"
by the net software, because we only register already-found cards.
*/
static int awc_pcmcia_init(struct net_device *dev)
{
return awc_init(dev);
}
static int awc_pcmcia_open(struct net_device *dev)
{
dev_link_t *link;
int status;
for (link = dev_list; link; link = link->next)
if (link->priv == dev) break;
if (!DEV_OK(link))
return -ENODEV;
status = awc_open(dev);
if (!status )
link->open++;
return status;
}
static int awc_pcmcia_close(struct net_device *dev)
{
// int ioaddr = dev->base_addr;
dev_link_t *link;
int ret;
for (link = dev_list; link; link = link->next)
if (link->priv == dev) break;
if (link == NULL)
return -ENODEV;
PC_DEBUG(2, "%s: closing device.\n", dev->name);
link->open--;
ret = awc_close(dev);
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = RUN_AT( HZ/20 );
link->state |= DEV_RELEASE_PENDING;
add_timer(&link->release);
}
return ret;
}
static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
{
u32 ethcmd;
/* dev_ioctl() in ../../net/core/dev.c has already checked
capable(CAP_NET_ADMIN), so don't bother with that here. */
if (get_user(ethcmd, (u32 *)useraddr))
return -EFAULT;
switch (ethcmd) {
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strcpy (info.driver, DRV_NAME);
strcpy (info.version, DRV_VERSION);
sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);
if (copy_to_user (useraddr, &info, sizeof (info)))
return -EFAULT;
return 0;
}
#ifdef PCMCIA_DEBUG
/* get message-level */
case ETHTOOL_GMSGLVL: {
struct ethtool_value edata = {ETHTOOL_GMSGLVL};
edata.data = pc_debug;
if (copy_to_user(useraddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
/* set message-level */
case ETHTOOL_SMSGLVL: {
struct ethtool_value edata;
if (copy_from_user(&edata, useraddr, sizeof(edata)))
return -EFAULT;
pc_debug = edata.data;
return 0;
}
#endif
default:
break;
}
return -EOPNOTSUPP;
}
static int awc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
switch (cmd) {
case SIOCETHTOOL:
return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
default:
return -EOPNOTSUPP;
}
return 0;
}
/*
awc_attach() creates an "instance" of the driver, allocating
local data structures for one device. The device is registered
with Card Services.
*/
static dev_link_t *awc_attach(void)
{
client_reg_t client_reg;
dev_link_t *link = NULL;
struct net_device *dev = NULL;
int ret;
PC_DEBUG(0, "awc_attach()\n");
flush_stale_links();
/* Create the PC card device object. */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link)
return NULL;
memset(link, 0, sizeof(struct dev_link_t));
link->dev = kmalloc(sizeof(struct dev_node_t), GFP_KERNEL);
if (!link->dev) {
kfree(link);
return NULL;
}
memset(link->dev, 0, sizeof(struct dev_node_t));
init_timer(&link->release);
link->release.function = &awc_release;
link->release.data = (u_long)link;
// link->io.NumPorts1 = 32;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
// link->io.IOAddrLines = 5;
link->irq.Attributes = IRQ_HANDLE_PRESENT ; // |IRQ_TYPE_EXCLUSIVE ;
link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
link->irq.IRQInfo2 = irq_mask;
link->irq.Handler = &awc_interrupt;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
/* Create the network device object. */
dev = kmalloc(sizeof(struct net_device ), GFP_KERNEL);
// dev = init_etherdev(0, sizeof(struct awc_private) );
if (!dev ) {
printk(KERN_CRIT "out of mem on dev alloc \n");
kfree(link->dev);
kfree(link);
return NULL;
};
memset(dev,0,sizeof(struct net_device));
dev->priv = kmalloc(sizeof(struct awc_private), GFP_KERNEL);
if (!dev->priv ) {printk(KERN_CRIT "out of mem on dev priv alloc \n"); return NULL;};
memset(dev->priv,0,sizeof(struct awc_private));
// link->dev->minor = dev->minor;
// link->dev->major = dev->major;
/* The 4500-specific entries in the device structure. */
// dev->tx_queue_len = tx_queue_len;
dev->hard_start_xmit = &awc_start_xmit;
// dev->set_config = &awc_config_misiganes,aga mitte awc_config;
dev->get_stats = &awc_get_stats;
// dev->set_multicast_list = &awc_set_multicast_list;
dev->do_ioctl = &awc_ioctl;
strcpy(dev->name, ((struct awc_private *)dev->priv)->node.dev_name);
ether_setup(dev);
dev->init = &awc_pcmcia_init;
dev->open = &awc_pcmcia_open;
dev->stop = &awc_pcmcia_close;
link->priv = dev;
#if CS_RELEASE_CODE > 0x2911
link->irq.Instance = dev;
#endif
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.event_handler = &awc_event;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = CardServices(RegisterClient, &link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
awc_detach(link);
return NULL;
}
return link;
} /* awc_attach */
/*
This deletes a driver "instance". The device is de-registered
with Card Services. If it has been released, all local data
structures are freed. Otherwise, the structures will be freed
when the device is released.
*/
static void awc_detach(dev_link_t *link)
{
dev_link_t **linkp;
unsigned long flags;
int i=0;
DEBUG(0, "awc_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
save_flags(flags);
cli();
if (link->state & DEV_RELEASE_PENDING) {
del_timer(&link->release);
link->state &= ~DEV_RELEASE_PENDING;
}
restore_flags(flags);
if (link->state & DEV_CONFIG) {
awc_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
if (link->handle)
CardServices(DeregisterClient, link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
i=0;
while ( i < MAX_AWCS) {
if (!aironet4500_devices[i])
{i++; continue;}
if (aironet4500_devices[i] == link->priv){
if (awc_proc_unset_fun)
awc_proc_unset_fun(i);
aironet4500_devices[i]=0;
}
i++;
}
if (link->priv) {
//struct net_device *dev = link->priv;
// dam dam damn mif (dev->priv)
// kfree(dev->priv);
kfree(link->priv);
}
kfree(link->dev);
kfree(link);
} /* awc_detach */
/*
awc_pcmcia_config() is scheduled to run after a CARD_INSERTION event
is received, to configure the PCMCIA socket, and to make the
ethernet device available to the system.
*/
#define CS_CHECK(fn, args...) \
while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
static void awc_pcmcia_config(dev_link_t *link)
{
client_handle_t handle;
struct net_device *dev;
struct awc_private *lp;
tuple_t tuple;
int ii;
cisparse_t parse;
u_short buf[64];
int last_fn, last_ret, i = 0;
// int ioaddr;
u16 *phys_addr;
int retval;
handle = link->handle;
dev = link->priv;
phys_addr = (u16 *)dev->dev_addr;
PC_DEBUG(0, "awc_pcmcia_config(0x%p)\n", link);
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, handle, &tuple);
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
CS_CHECK(GetTupleData, handle, &tuple);
CS_CHECK(ParseTuple, handle, &tuple, &parse);
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Configure card */
link->state |= DEV_CONFIG;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, handle, &tuple);
while (1) {
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
CFG_CHECK(GetTupleData, handle, &tuple);
CFG_CHECK(ParseTuple, handle, &tuple, &parse);
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
if (cfg->index == 0) goto next_entry;
link->conf.ConfigIndex = cfg->index;
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vpp1 = link->conf.Vpp2 =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vpp1 = link->conf.Vpp2 =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* Do we need to allocate an interrupt? */
if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
link->conf.Attributes |= CONF_ENABLE_IRQ;
/* IO window settings */
link->io.NumPorts1 = link->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(io->flags & CISTPL_IO_8BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(io->flags & CISTPL_IO_16BIT)) {
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
printk(KERN_CRIT "8-bit IO not supported on this aironet 4500 driver \n");
}
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
if (io->nwin > 1) {
link->io.Attributes2 = link->io.Attributes1;
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
}
ii = 0;
last_fn = RequestIO;
while ((last_ret = CardServices(RequestIO, link->handle, &link->io)) ){
if (ii > 4)
goto cs_failed;
link->io.BasePort1 = awc_ports[ii];
ii++;
};
break;
next_entry:
if (CardServices(GetNextTuple, handle, &tuple))
break;
}
if (link->conf.Attributes & CONF_ENABLE_IRQ){
ii = 0; last_fn = RequestIRQ;
while ((last_ret = CardServices(RequestIRQ, link->handle, &link->irq)) ){
ii++;
while (!(irq_mask & (1 << ii) ) && ii < 15)
ii++;
link->irq.IRQInfo2 = 1 << ii;
if(ii > 15)
goto cs_failed;
printk("trying irq %d , mask %x \n",ii, link->irq.IRQInfo2);
};
}
CS_CHECK(RequestConfiguration, link->handle, &link->conf);
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
awc_private_init( dev);
retval = register_netdev(dev);
if (retval != 0) {
printk(KERN_NOTICE "awc_cs: register_netdev() failed for dev %x retval %x\n",(unsigned int)dev,retval);
goto failed;
}
if(awc_pcmcia_init(dev)) goto failed;
i=0;
while (aironet4500_devices[i] && i < MAX_AWCS-1) i++;
if (!aironet4500_devices[i]){
aironet4500_devices[i]=dev;
if (awc_proc_set_fun)
awc_proc_set_fun(i);
}
link->state &= ~DEV_CONFIG_PENDING;
lp = (struct awc_private *)dev->priv;
DEBUG(1,"pcmcia config complete on port %x \n",(unsigned int)dev->base_addr);
return;
cs_failed:
cs_error(link->handle, last_fn, last_ret);
link->dev=NULL;
failed:
awc_release((u_long)link);
return;
} /* awc_pcmcia_config */
/*
After a card is removed, awc_release() will unregister the net
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
*/
static void awc_release(u_long arg)
{
dev_link_t *link = (dev_link_t *)arg;
struct net_device *dev = link->priv;
DEBUG(0, "awc_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "awc_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
CardServices(ReleaseWindow, link->win);
if (link->dev)
unregister_netdev(dev);
// link->dev = NULL;
link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK)
awc_detach(link);
} /* awc_release */
/*
The card status event handler. Mostly, this schedules other
stuff to run after an event is received. A CARD_REMOVAL event
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
*/
static int awc_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
struct net_device *dev = link->priv;
PC_DEBUG(1, "awc_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(dev);
link->release.expires = RUN_AT( HZ/20 );
add_timer(&link->release);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
awc_pcmcia_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
CardServices(ReleaseConfiguration, link->handle);
}
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
// awc_reset(dev);
netif_device_attach(dev);
}
}
break;
}
return 0;
} /* awc_event */
static int __init aironet_cs_init(void)
{
servinfo_t serv;
/* Always emit the version, before any failure. */
printk(KERN_INFO"%s", awc_version);
PC_DEBUG(0, "%s\n", version);
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "awc_cs: Card Services release "
"does not match!\n");
return -1;
}
register_pcmcia_driver(&dev_info, &awc_attach, &awc_detach);
return 0;
}
static void __exit aironet_cs_exit(void)
{
DEBUG(0, "awc_cs: unloading %c ",'\n');
unregister_pcmcia_driver(&dev_info);
while (dev_list != NULL) {
if (dev_list->state & DEV_CONFIG)
awc_release((u_long)dev_list);
awc_detach(dev_list);
}
// while (dev_list != NULL)
// awc_detach(dev_list);
}
module_init(aironet_cs_init);
module_exit(aironet_cs_exit);
MODULE_LICENSE("GPL");
......@@ -25,6 +25,7 @@
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/workqueue.h>
#include <asm/system.h>
#include <asm/io.h>
......@@ -54,8 +55,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.4"
#define DRV_MODULE_RELDATE "Feb 1, 2003"
#define DRV_MODULE_VERSION "1.4c"
#define DRV_MODULE_RELDATE "Feb 18, 2003"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
......@@ -216,6 +217,12 @@ static void tg3_disable_ints(struct tg3 *tp)
tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
}
static inline void tg3_cond_int(struct tg3 *tp)
{
if (tp->hw_status->status & SD_STATUS_UPDATED)
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
}
static void tg3_enable_ints(struct tg3 *tp)
{
tw32(TG3PCI_MISC_HOST_CTRL,
......@@ -223,9 +230,55 @@ static void tg3_enable_ints(struct tg3 *tp)
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
if (tp->hw_status->status & SD_STATUS_UPDATED)
tw32(GRC_LOCAL_CTRL,
tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
tg3_cond_int(tp);
}
/* these netif_xxx funcs should be moved into generic net layer */
static void netif_poll_disable(struct net_device *dev)
{
while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(1);
}
}
static inline void netif_poll_enable(struct net_device *dev)
{
clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
}
/* same as netif_rx_complete, except that local_irq_save(flags)
* has already been issued
*/
static inline void __netif_rx_complete(struct net_device *dev)
{
if (!test_bit(__LINK_STATE_RX_SCHED, &dev->state)) BUG();
list_del(&dev->poll_list);
clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
}
static inline void netif_tx_disable(struct net_device *dev)
{
spin_lock_bh(&dev->xmit_lock);
netif_stop_queue(dev);
spin_unlock_bh(&dev->xmit_lock);
}
static inline void tg3_netif_stop(struct tg3 *tp)
{
netif_poll_disable(tp->dev);
netif_tx_disable(tp->dev);
}
static inline void tg3_netif_start(struct tg3 *tp)
{
netif_wake_queue(tp->dev);
/* NOTE: unconditional netif_wake_queue is only appropriate
* so long as all callers are assured to have free tx slots
* (such as after tg3_init_hw)
*/
netif_poll_enable(tp->dev);
tg3_cond_int(tp);
}
static void tg3_switch_clocks(struct tg3 *tp)
......@@ -387,7 +440,6 @@ static int tg3_phy_reset(struct tg3 *tp, int force)
}
static int tg3_setup_phy(struct tg3 *);
static int tg3_halt(struct tg3 *);
static int tg3_set_power_state(struct tg3 *tp, int state)
{
......@@ -458,8 +510,6 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
tg3_setup_phy(tp);
}
tg3_halt(tp);
pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
......@@ -2044,7 +2094,12 @@ static int tg3_poll(struct net_device *netdev, int *budget)
spin_unlock(&tp->tx_lock);
}
/* run RX thread, within the bounds set by NAPI */
spin_unlock_irqrestore(&tp->lock, flags);
/* run RX thread, within the bounds set by NAPI.
* All RX "locking" is done by ensuring outside
* code synchronizes with dev->poll()
*/
done = 1;
if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
int orig_budget = *budget;
......@@ -2064,12 +2119,12 @@ static int tg3_poll(struct net_device *netdev, int *budget)
/* if no more work, tell net stack and NIC we're done */
if (done) {
netif_rx_complete(netdev);
spin_lock_irqsave(&tp->lock, flags);
__netif_rx_complete(netdev);
tg3_enable_ints(tp);
spin_unlock_irqrestore(&tp->lock, flags);
}
spin_unlock_irqrestore(&tp->lock, flags);
return (done ? 0 : 1);
}
......@@ -2136,17 +2191,21 @@ static void tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void tg3_init_rings(struct tg3 *);
static int tg3_init_hw(struct tg3 *);
static int tg3_halt(struct tg3 *);
static void tg3_tx_timeout(struct net_device *dev)
static void tg3_reset_task(void *_data)
{
struct tg3 *tp = dev->priv;
struct tg3 *tp = _data;
unsigned int restart_timer;
printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
dev->name);
tg3_netif_stop(tp);
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
tg3_halt(tp);
tg3_init_rings(tp);
tg3_init_hw(tp);
......@@ -2154,7 +2213,20 @@ static void tg3_tx_timeout(struct net_device *dev)
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
netif_wake_queue(dev);
tg3_netif_start(tp);
if (restart_timer)
mod_timer(&tp->timer, jiffies + 1);
}
static void tg3_tx_timeout(struct net_device *dev)
{
struct tg3 *tp = dev->priv;
printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
dev->name);
schedule_work(&tp->reset_task);
}
#if !PCI_DMA_BUS_IS_PHYS
......@@ -2686,6 +2758,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
tg3_netif_stop(tp);
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
......@@ -2698,6 +2771,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0;
}
......@@ -3073,6 +3147,7 @@ static int tg3_abort_hw(struct tg3 *tp)
static void tg3_chip_reset(struct tg3 *tp)
{
u32 val;
u32 flags_save;
/* Force NVRAM to settle.
* This deals with a chip bug which can result in EEPROM
......@@ -3089,8 +3164,21 @@ static void tg3_chip_reset(struct tg3 *tp)
}
}
/*
* We must avoid the readl() that normally takes place.
* It locks machines, causes machine checks, and other
* fun things. So, temporarily disable the 5701
* hardware workaround, while we do the reset.
*/
flags_save = tp->tg3_flags;
tp->tg3_flags &= ~TG3_FLAG_5701_REG_WRITE_BUG;
/* do the reset */
tw32(GRC_MISC_CFG, GRC_MISC_CFG_CORECLK_RESET);
/* restore 5701 hardware bug workaround flag */
tp->tg3_flags = flags_save;
/* Flush PCI posted writes. The normal MMIO registers
* are inaccessible at this time so this is the only
* way to make this reliably. I tried to use indirect
......@@ -4394,9 +4482,11 @@ static void tg3_timer(unsigned long __opaque)
}
if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
tg3_halt(tp);
tg3_init_rings(tp);
tg3_init_hw(tp);
tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
spin_unlock(&tp->tx_lock);
spin_unlock_irqrestore(&tp->lock, flags);
schedule_work(&tp->reset_task);
return;
}
/* This part only runs once per second. */
......@@ -4527,8 +4617,6 @@ static int tg3_open(struct net_device *dev)
return err;
}
netif_start_queue(dev);
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
......@@ -4537,6 +4625,8 @@ static int tg3_open(struct net_device *dev)
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
netif_start_queue(dev);
return 0;
}
......@@ -5302,6 +5392,7 @@ static int tg3_ethtool_ioctl (struct net_device *dev, void *useraddr)
(ering.tx_pending > TG3_TX_RING_SIZE - 1))
return -EINVAL;
tg3_netif_stop(tp);
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
......@@ -5315,6 +5406,7 @@ static int tg3_ethtool_ioctl (struct net_device *dev, void *useraddr)
netif_wake_queue(tp->dev);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0;
}
......@@ -5337,6 +5429,7 @@ static int tg3_ethtool_ioctl (struct net_device *dev, void *useraddr)
if (copy_from_user(&epause, useraddr, sizeof(epause)))
return -EFAULT;
tg3_netif_stop(tp);
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
if (epause.autoneg)
......@@ -5356,6 +5449,7 @@ static int tg3_ethtool_ioctl (struct net_device *dev, void *useraddr)
tg3_init_hw(tp);
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0;
}
......@@ -6710,6 +6804,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
spin_lock_init(&tp->lock);
spin_lock_init(&tp->tx_lock);
spin_lock_init(&tp->indirect_lock);
PREPARE_WORK(&tp->reset_task, tg3_reset_task, tp);
tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);
if (tp->regs == 0UL) {
......@@ -6851,6 +6946,8 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state)
if (!netif_running(dev))
return 0;
tg3_netif_stop(tp);
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
tg3_disable_ints(tp);
......@@ -6877,6 +6974,7 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state)
spin_unlock_irq(&tp->lock);
netif_device_attach(dev);
tg3_netif_start(tp);
}
return err;
......@@ -6907,6 +7005,8 @@ static int tg3_resume(struct pci_dev *pdev)
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
tg3_netif_start(tp);
return 0;
}
......
......@@ -1821,6 +1821,8 @@ struct tg3 {
#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
#define TG3_FLAG_SPLIT_MODE 0x40000000
#define TG3_FLAG_INIT_COMPLETE 0x80000000
u32 tg3_flags2;
#define TG3_FLG2_RESTART_TIMER 0x00000001
u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3
......@@ -1889,6 +1891,7 @@ struct tg3 {
struct tg3_hw_stats *hw_stats;
dma_addr_t stats_mapping;
struct work_struct reset_task;
};
#endif /* !(_T3_H) */
......@@ -6,13 +6,13 @@ menu "Wireless LAN (non-hamradio)"
depends on NETDEVICES
config NET_RADIO
bool "Wireless LAN (non-hamradio)"
bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions"
---help---
Support for wireless LANs and everything having to do with radio,
but not with amateur radio or FM broadcasting.
Saying Y here also enables the Wireless Extensions (creates
/proc/net/wireless and enables ifconfig access). The Wireless
/proc/net/wireless and enables iwconfig access). The Wireless
Extension is a generic API allowing a driver to expose to the user
space configuration and statistics specific to common Wireless LANs.
The beauty of it is that a single set of tool can support all the
......@@ -28,6 +28,11 @@ config NET_RADIO
special kernel support are available from
<ftp://shadow.cabi.net/pub/Linux/>.
# Note : the cards are obsolete (can't buy them anymore), but the drivers
# are not, as people are still using them...
comment "Obsolete Wireless cards support (pre-802.11)"
depends on NET_RADIO && (INET || ISA || PCMCIA)
config STRIP
tristate "STRIP (Metricom starmode radio IP)"
depends on NET_RADIO && INET
......@@ -68,10 +73,6 @@ config ARLAN
On some computers the card ends up in non-valid state after some
time. Use a ping-reset script to clear it.
comment "Wireless ISA/PCI cards support"
depends on NET_RADIO && (ISA || PCI || ALL_PPC || PCMCIA)
# Good old obsolete Wavelan.
config WAVELAN
tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
depends on NET_RADIO && ISA
......@@ -102,7 +103,54 @@ config WAVELAN
module, say M here and read <file:Documentation/modules.txt> as well
as <file:Documentation/networking/net-modules.txt>.
# 802.11b cards
config PCMCIA_WAVELAN
tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support"
depends on NET_RADIO && PCMCIA
help
Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA
(PC-card) wireless Ethernet networking card to your computer. This
driver is for the non-IEEE-802.11 Wavelan cards.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called wavelan_cs. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
If unsure, say N.
config PCMCIA_NETWAVE
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
depends on NET_RADIO && PCMCIA
help
Say Y here if you intend to attach this type of PCMCIA (PC-card)
wireless Ethernet networking card to your computer.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called netwave_cs. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
If unsure, say N.
comment "Wireless 802.11 Frequency Hopping cards support"
depends on NET_RADIO && PCMCIA
config PCMCIA_RAYCS
tristate "Aviator/Raytheon 2.4MHz wireless support"
depends on NET_RADIO && PCMCIA
---help---
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
(PC-card) wireless Ethernet networking card to your computer.
Please read the file <file:Documentation/networking/ray_cs.txt> for
details.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ray_cs. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. If
unsure, say N.
comment "Wireless 802.11b ISA/PCI cards support"
depends on NET_RADIO && (ISA || PCI || ALL_PPC || PCMCIA)
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
depends on NET_RADIO && (ISA || PCI)
......@@ -175,41 +223,12 @@ config PCI_HERMES
this variety.
# If Pcmcia is compiled in, offer Pcmcia cards...
comment "Wireless Pcmcia/Cardbus cards support"
depends on NET_RADIO && PCMCIA
# Obsolete cards
config PCMCIA_NETWAVE
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
depends on NET_RADIO && PCMCIA
help
Say Y here if you intend to attach this type of PCMCIA (PC-card)
wireless Ethernet networking card to your computer.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called netwave_cs. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
If unsure, say N.
config PCMCIA_WAVELAN
tristate "AT&T/Lucent old Wavelan Pcmcia wireless support"
comment "Wireless 802.11b Pcmcia/Cardbus cards support"
depends on NET_RADIO && PCMCIA
help
Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA
(PC-card) wireless Ethernet networking card to your computer. This
driver is for the non-IEEE-802.11 Wavelan cards.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called wavelan_cs. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
If unsure, say N.
# 802.11b cards
config PCMCIA_HERMES
tristate "Hermes PCMCIA card support"
depends on PCMCIA!=n && HERMES
depends on NET_RADIO && PCMCIA && HERMES
---help---
A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
......@@ -249,34 +268,6 @@ config AIRO_CS
for location). You also want to check out the PCMCIA-HOWTO,
available from <http://www.linuxdoc.org/docs.html#howto>.
config NET_PCMCIA_RADIO
bool "PCMCIA Wireless LAN"
depends on NET_PCMCIA
help
Say Y here if you would like to use a PCMCIA (PC-card) device to
connect to a wireless local area network. Then say Y to the driver
for your particular card below.
To use your PC-cards, you will need supporting software from David
Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
for location). You also want to check out the PCMCIA-HOWTO,
available from <http://www.linuxdoc.org/docs.html#howto>.
config PCMCIA_RAYCS
tristate "Aviator/Raytheon 2.4MHz wireless support"
depends on NET_PCMCIA_RADIO && PCMCIA
---help---
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
(PC-card) wireless Ethernet networking card to your computer.
Please read the file <file:Documentation/networking/ray_cs.txt> for
details.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called ray_cs. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. If
unsure, say N.
# yes, this works even when no drivers are selected
config NET_WIRELESS
bool
......
......@@ -2,28 +2,14 @@
-------------
1) Bring other kernel Wireless LAN drivers here
Already done :
o hermes.c/orinoco.c -> Wavelan IEEE driver + Airport driver
o airo.c/airo_cs.c -> Ben's Aironet driver
o wavelan.c -> old Wavelan ISA driver
o wavelan_cs.c -> old Wavelan Pcmcia driver
o netwave_cs.c -> Netwave Pcmcia driver
Drivers likely to go :
o ray_cs.c -> Raytheon/Aviator driver (maintainer MIA)
Drivers I have absolutely no control over :
o arlan.c -> old Aironet Arlan 655 (need to ask Elmer)
o aironet4500_xxx.c -> Elmer's Aironet driver (need to ask Elmer)
o strip.c -> Metricom's stuff. Not a wlan. Hum...
ETA : Kernel 2.5.X
Completed
2) Bring new Wireless LAN driver not yet in the kernel there
See my web page for details
In particular : HostAP
3) Misc
o Mark wavelan, wavelan_cs, netwave_cs drivers as obsolete
o Maybe arlan.c, ray_cs.c and strip.c also deserve to be obsolete
o Use new Probe/module stuff in wavelan.c
o New Wireless Extension API (pending)
Jean II
......@@ -19,5 +19,3 @@ obj-$(CONFIG_NET_DIVERT) += dv.o
obj-$(CONFIG_NET_PROFILE) += profile.o
obj-$(CONFIG_NET_PKTGEN) += pktgen.o
obj-$(CONFIG_NET_RADIO) += wireless.o
# Ugly. I wish all wireless drivers were moved in drivers/net/wireless
obj-$(CONFIG_NET_PCMCIA_RADIO) += wireless.o
......@@ -107,10 +107,10 @@
#include <linux/kmod.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
#include <net/iw_handler.h>
#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
#endif /* CONFIG_NET_RADIO */
#ifdef CONFIG_PLIP
extern int plip_init(void);
#endif
......
......@@ -646,12 +646,12 @@ EXPORT_SYMBOL(register_gifconf);
EXPORT_SYMBOL(softnet_data);
#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
#ifdef CONFIG_NET_RADIO
/* Don't include the whole header mess for a single function */
union iwreq_data;
extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra);
EXPORT_SYMBOL(wireless_send_event);
#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
#endif /* CONFIG_NET_RADIO */
EXPORT_SYMBOL(linkwatch_fire_event);
......
......@@ -83,9 +83,9 @@
#include <linux/kmod.h>
#endif
#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
#endif /* CONFIG_NET_RADIO */
#include <asm/uaccess.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment