mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 08:49:45 +00:00
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (33 commits) [PATCH] myri10ge - drop workaround pci_save_state() disabling MSI [PATCH] myri10ge - drop workaround for the missing AER ext cap on nVidia CK804 via-velocity: the link is not correctly detected when the device starts [PATCH] add b44 to maintainers [PATCH] WAN: ioremap() failure checks in drivers [PATCH] WAN: register_hdlc_device() doesn't need dev_alloc_name() [PATCH] skb_padto()-area fixes in 8390, wavelan [PATCH] make drivers/net/forcedeth.c:nv_update_pause() static [PATCH] network driver for Hilscher netx [PATCH] Dereference in tokenring/olympic.c [PATCH] Array overrun in drivers/net/wireless/wavelan.c [PATCH] Remove useless check in drivers/net/pcmcia/xirc2ps_cs.c [PATCH] 8139cp: add ethtool eeprom support [PATCH] 8139cp: fix eeprom read command length [PATCH] b44: update b44 Kconfig entry [PATCH] b44: update version to 1.01 [PATCH] b44: add wol for old nic [PATCH] b44: add parameter [PATCH] b44: add wol [PATCH] b44: fix manual speed/duplex/autoneg settings ...
This commit is contained in:
commit
065a3e17ba
39 changed files with 1609 additions and 354 deletions
|
@ -574,6 +574,12 @@ L: linuxppc-dev@ozlabs.org
|
|||
W: http://www.penguinppc.org/ppc64/
|
||||
S: Supported
|
||||
|
||||
BROADCOM B44 10/100 ETHERNET DRIVER
|
||||
P: Gary Zambrano
|
||||
M: zambrano@broadcom.com
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
|
||||
BROADCOM BNX2 GIGABIT ETHERNET DRIVER
|
||||
P: Michael Chan
|
||||
M: mchan@broadcom.com
|
||||
|
|
|
@ -401,6 +401,11 @@ static void cp_clean_rings (struct cp_private *cp);
|
|||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void cp_poll_controller(struct net_device *dev);
|
||||
#endif
|
||||
static int cp_get_eeprom_len(struct net_device *dev);
|
||||
static int cp_get_eeprom(struct net_device *dev,
|
||||
struct ethtool_eeprom *eeprom, u8 *data);
|
||||
static int cp_set_eeprom(struct net_device *dev,
|
||||
struct ethtool_eeprom *eeprom, u8 *data);
|
||||
|
||||
static struct pci_device_id cp_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
|
||||
|
@ -1577,6 +1582,9 @@ static struct ethtool_ops cp_ethtool_ops = {
|
|||
.get_strings = cp_get_strings,
|
||||
.get_ethtool_stats = cp_get_ethtool_stats,
|
||||
.get_perm_addr = ethtool_op_get_perm_addr,
|
||||
.get_eeprom_len = cp_get_eeprom_len,
|
||||
.get_eeprom = cp_get_eeprom,
|
||||
.set_eeprom = cp_set_eeprom,
|
||||
};
|
||||
|
||||
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
|
@ -1612,24 +1620,32 @@ static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
|
|||
#define eeprom_delay() readl(ee_addr)
|
||||
|
||||
/* The EEPROM commands include the alway-set leading bit. */
|
||||
#define EE_EXTEND_CMD (4)
|
||||
#define EE_WRITE_CMD (5)
|
||||
#define EE_READ_CMD (6)
|
||||
#define EE_ERASE_CMD (7)
|
||||
|
||||
static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
|
||||
{
|
||||
int i;
|
||||
unsigned retval = 0;
|
||||
void __iomem *ee_addr = ioaddr + Cfg9346;
|
||||
int read_cmd = location | (EE_READ_CMD << addr_len);
|
||||
#define EE_EWDS_ADDR (0)
|
||||
#define EE_WRAL_ADDR (1)
|
||||
#define EE_ERAL_ADDR (2)
|
||||
#define EE_EWEN_ADDR (3)
|
||||
|
||||
#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139
|
||||
|
||||
static void eeprom_cmd_start(void __iomem *ee_addr)
|
||||
{
|
||||
writeb (EE_ENB & ~EE_CS, ee_addr);
|
||||
writeb (EE_ENB, ee_addr);
|
||||
eeprom_delay ();
|
||||
}
|
||||
|
||||
/* Shift the read command bits out. */
|
||||
for (i = 4 + addr_len; i >= 0; i--) {
|
||||
int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
|
||||
static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Shift the command bits out. */
|
||||
for (i = cmd_len - 1; i >= 0; i--) {
|
||||
int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
|
||||
writeb (EE_ENB | dataval, ee_addr);
|
||||
eeprom_delay ();
|
||||
writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
|
||||
|
@ -1637,6 +1653,33 @@ static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
|
|||
}
|
||||
writeb (EE_ENB, ee_addr);
|
||||
eeprom_delay ();
|
||||
}
|
||||
|
||||
static void eeprom_cmd_end(void __iomem *ee_addr)
|
||||
{
|
||||
writeb (~EE_CS, ee_addr);
|
||||
eeprom_delay ();
|
||||
}
|
||||
|
||||
static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd,
|
||||
int addr_len)
|
||||
{
|
||||
int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2));
|
||||
|
||||
eeprom_cmd_start(ee_addr);
|
||||
eeprom_cmd(ee_addr, cmd, 3 + addr_len);
|
||||
eeprom_cmd_end(ee_addr);
|
||||
}
|
||||
|
||||
static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len)
|
||||
{
|
||||
int i;
|
||||
u16 retval = 0;
|
||||
void __iomem *ee_addr = ioaddr + Cfg9346;
|
||||
int read_cmd = location | (EE_READ_CMD << addr_len);
|
||||
|
||||
eeprom_cmd_start(ee_addr);
|
||||
eeprom_cmd(ee_addr, read_cmd, 3 + addr_len);
|
||||
|
||||
for (i = 16; i > 0; i--) {
|
||||
writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
|
||||
|
@ -1648,13 +1691,125 @@ static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
|
|||
eeprom_delay ();
|
||||
}
|
||||
|
||||
/* Terminate the EEPROM access. */
|
||||
writeb (~EE_CS, ee_addr);
|
||||
eeprom_delay ();
|
||||
eeprom_cmd_end(ee_addr);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void write_eeprom(void __iomem *ioaddr, int location, u16 val,
|
||||
int addr_len)
|
||||
{
|
||||
int i;
|
||||
void __iomem *ee_addr = ioaddr + Cfg9346;
|
||||
int write_cmd = location | (EE_WRITE_CMD << addr_len);
|
||||
|
||||
eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len);
|
||||
|
||||
eeprom_cmd_start(ee_addr);
|
||||
eeprom_cmd(ee_addr, write_cmd, 3 + addr_len);
|
||||
eeprom_cmd(ee_addr, val, 16);
|
||||
eeprom_cmd_end(ee_addr);
|
||||
|
||||
eeprom_cmd_start(ee_addr);
|
||||
for (i = 0; i < 20000; i++)
|
||||
if (readb(ee_addr) & EE_DATA_READ)
|
||||
break;
|
||||
eeprom_cmd_end(ee_addr);
|
||||
|
||||
eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len);
|
||||
}
|
||||
|
||||
static int cp_get_eeprom_len(struct net_device *dev)
|
||||
{
|
||||
struct cp_private *cp = netdev_priv(dev);
|
||||
int size;
|
||||
|
||||
spin_lock_irq(&cp->lock);
|
||||
size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128;
|
||||
spin_unlock_irq(&cp->lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int cp_get_eeprom(struct net_device *dev,
|
||||
struct ethtool_eeprom *eeprom, u8 *data)
|
||||
{
|
||||
struct cp_private *cp = netdev_priv(dev);
|
||||
unsigned int addr_len;
|
||||
u16 val;
|
||||
u32 offset = eeprom->offset >> 1;
|
||||
u32 len = eeprom->len;
|
||||
u32 i = 0;
|
||||
|
||||
eeprom->magic = CP_EEPROM_MAGIC;
|
||||
|
||||
spin_lock_irq(&cp->lock);
|
||||
|
||||
addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
|
||||
|
||||
if (eeprom->offset & 1) {
|
||||
val = read_eeprom(cp->regs, offset, addr_len);
|
||||
data[i++] = (u8)(val >> 8);
|
||||
offset++;
|
||||
}
|
||||
|
||||
while (i < len - 1) {
|
||||
val = read_eeprom(cp->regs, offset, addr_len);
|
||||
data[i++] = (u8)val;
|
||||
data[i++] = (u8)(val >> 8);
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (i < len) {
|
||||
val = read_eeprom(cp->regs, offset, addr_len);
|
||||
data[i] = (u8)val;
|
||||
}
|
||||
|
||||
spin_unlock_irq(&cp->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cp_set_eeprom(struct net_device *dev,
|
||||
struct ethtool_eeprom *eeprom, u8 *data)
|
||||
{
|
||||
struct cp_private *cp = netdev_priv(dev);
|
||||
unsigned int addr_len;
|
||||
u16 val;
|
||||
u32 offset = eeprom->offset >> 1;
|
||||
u32 len = eeprom->len;
|
||||
u32 i = 0;
|
||||
|
||||
if (eeprom->magic != CP_EEPROM_MAGIC)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irq(&cp->lock);
|
||||
|
||||
addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
|
||||
|
||||
if (eeprom->offset & 1) {
|
||||
val = read_eeprom(cp->regs, offset, addr_len) & 0xff;
|
||||
val |= (u16)data[i++] << 8;
|
||||
write_eeprom(cp->regs, offset, val, addr_len);
|
||||
offset++;
|
||||
}
|
||||
|
||||
while (i < len - 1) {
|
||||
val = (u16)data[i++];
|
||||
val |= (u16)data[i++] << 8;
|
||||
write_eeprom(cp->regs, offset, val, addr_len);
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (i < len) {
|
||||
val = read_eeprom(cp->regs, offset, addr_len) & 0xff00;
|
||||
val |= (u16)data[i];
|
||||
write_eeprom(cp->regs, offset, val, addr_len);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&cp->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Put the board into D3cold state and wait for WakeUp signal */
|
||||
static void cp_set_d3_state (struct cp_private *cp)
|
||||
{
|
||||
|
|
|
@ -275,12 +275,14 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
|
||||
int send_length = skb->len, output_page;
|
||||
unsigned long flags;
|
||||
char buf[ETH_ZLEN];
|
||||
char *data = skb->data;
|
||||
|
||||
if (skb->len < ETH_ZLEN) {
|
||||
skb = skb_padto(skb, ETH_ZLEN);
|
||||
if (skb == NULL)
|
||||
return 0;
|
||||
memset(buf, 0, ETH_ZLEN); /* more efficient than doing just the needed bits */
|
||||
memcpy(buf, data, skb->len);
|
||||
send_length = ETH_ZLEN;
|
||||
data = buf;
|
||||
}
|
||||
|
||||
/* Mask interrupts from the ethercard.
|
||||
|
@ -347,7 +349,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
* trigger the send later, upon receiving a Tx done interrupt.
|
||||
*/
|
||||
|
||||
ei_block_output(dev, send_length, skb->data, output_page);
|
||||
ei_block_output(dev, send_length, data, output_page);
|
||||
|
||||
if (! ei_local->txing)
|
||||
{
|
||||
|
|
|
@ -854,6 +854,17 @@ config SMC9194
|
|||
<file:Documentation/networking/net-modules.txt>. The module
|
||||
will be called smc9194.
|
||||
|
||||
config NET_NETX
|
||||
tristate "NetX Ethernet support"
|
||||
select MII
|
||||
depends on NET_ETHERNET && ARCH_NETX
|
||||
help
|
||||
This is support for the Hilscher netX builtin Ethernet ports
|
||||
|
||||
To compile this driver as a module, choose M here and read
|
||||
<file:Documentation/networking/net-modules.txt>. The module
|
||||
will be called netx-eth.
|
||||
|
||||
config DM9000
|
||||
tristate "DM9000 support"
|
||||
depends on (ARM || MIPS) && NET_ETHERNET
|
||||
|
@ -1376,8 +1387,8 @@ config APRICOT
|
|||
called apricot.
|
||||
|
||||
config B44
|
||||
tristate "Broadcom 4400 ethernet support (EXPERIMENTAL)"
|
||||
depends on NET_PCI && PCI && EXPERIMENTAL
|
||||
tristate "Broadcom 4400 ethernet support"
|
||||
depends on NET_PCI && PCI
|
||||
select MII
|
||||
help
|
||||
If you have a network (Ethernet) controller of this type, say Y and
|
||||
|
|
|
@ -187,6 +187,7 @@ obj-$(CONFIG_MACSONIC) += macsonic.o
|
|||
obj-$(CONFIG_MACMACE) += macmace.o
|
||||
obj-$(CONFIG_MAC89x0) += mac89x0.o
|
||||
obj-$(CONFIG_TUN) += tun.o
|
||||
obj-$(CONFIG_NET_NETX) += netx-eth.o
|
||||
obj-$(CONFIG_DL2K) += dl2k.o
|
||||
obj-$(CONFIG_R8169) += r8169.o
|
||||
obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
#define DRV_VERSION "1.0"
|
||||
|
||||
static struct net_device *at91_dev;
|
||||
static struct clk *ether_clk;
|
||||
|
||||
static struct timer_list check_timer;
|
||||
#define LINK_POLL_INTERVAL (HZ)
|
||||
|
||||
/* ..................................................................... */
|
||||
|
||||
|
@ -143,7 +145,7 @@ static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int
|
|||
* MAC accordingly.
|
||||
* If no link or auto-negotiation is busy, then no changes are made.
|
||||
*/
|
||||
static void update_linkspeed(struct net_device *dev)
|
||||
static void update_linkspeed(struct net_device *dev, int silent)
|
||||
{
|
||||
struct at91_private *lp = (struct at91_private *) dev->priv;
|
||||
unsigned int bmsr, bmcr, lpa, mac_cfg;
|
||||
|
@ -151,7 +153,8 @@ static void update_linkspeed(struct net_device *dev)
|
|||
|
||||
if (!mii_link_ok(&lp->mii)) { /* no link */
|
||||
netif_carrier_off(dev);
|
||||
printk(KERN_INFO "%s: Link down.\n", dev->name);
|
||||
if (!silent)
|
||||
printk(KERN_INFO "%s: Link down.\n", dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -186,7 +189,8 @@ static void update_linkspeed(struct net_device *dev)
|
|||
}
|
||||
at91_emac_write(AT91_EMAC_CFG, mac_cfg);
|
||||
|
||||
printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
|
||||
if (!silent)
|
||||
printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
|
||||
netif_carrier_on(dev);
|
||||
}
|
||||
|
||||
|
@ -226,7 +230,7 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs
|
|||
goto done;
|
||||
}
|
||||
|
||||
update_linkspeed(dev);
|
||||
update_linkspeed(dev, 0);
|
||||
|
||||
done:
|
||||
disable_mdi();
|
||||
|
@ -243,14 +247,17 @@ static void enable_phyirq(struct net_device *dev)
|
|||
unsigned int dsintr, irq_number;
|
||||
int status;
|
||||
|
||||
if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */
|
||||
return;
|
||||
if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */
|
||||
return;
|
||||
if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */
|
||||
return;
|
||||
|
||||
irq_number = lp->board_data.phy_irq_pin;
|
||||
if (!irq_number) {
|
||||
/*
|
||||
* PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
|
||||
* or board does not have it connected.
|
||||
*/
|
||||
check_timer.expires = jiffies + LINK_POLL_INTERVAL;
|
||||
add_timer(&check_timer);
|
||||
return;
|
||||
}
|
||||
|
||||
status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
|
||||
if (status) {
|
||||
printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
|
||||
|
@ -292,12 +299,11 @@ static void disable_phyirq(struct net_device *dev)
|
|||
unsigned int dsintr;
|
||||
unsigned int irq_number;
|
||||
|
||||
if (lp->phy_type == MII_RTL8201_ID) /* RTL8201 does not have an interrupt */
|
||||
return;
|
||||
if (lp->phy_type == MII_DP83847_ID) /* DP83847 does not have an interrupt */
|
||||
return;
|
||||
if (lp->phy_type == MII_AC101L_ID) /* AC101L interrupt not supported yet */
|
||||
irq_number = lp->board_data.phy_irq_pin;
|
||||
if (!irq_number) {
|
||||
del_timer_sync(&check_timer);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irq(&lp->lock);
|
||||
enable_mdi();
|
||||
|
@ -326,7 +332,6 @@ static void disable_phyirq(struct net_device *dev)
|
|||
disable_mdi();
|
||||
spin_unlock_irq(&lp->lock);
|
||||
|
||||
irq_number = lp->board_data.phy_irq_pin;
|
||||
free_irq(irq_number, dev); /* Free interrupt handler */
|
||||
}
|
||||
|
||||
|
@ -355,6 +360,18 @@ static void reset_phy(struct net_device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void at91ether_check_link(unsigned long dev_id)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) dev_id;
|
||||
|
||||
enable_mdi();
|
||||
update_linkspeed(dev, 1);
|
||||
disable_mdi();
|
||||
|
||||
check_timer.expires = jiffies + LINK_POLL_INTERVAL;
|
||||
add_timer(&check_timer);
|
||||
}
|
||||
|
||||
/* ......................... ADDRESS MANAGEMENT ........................ */
|
||||
|
||||
/*
|
||||
|
@ -501,7 +518,7 @@ static int hash_get_index(__u8 *addr)
|
|||
hash_index |= (bitval << j);
|
||||
}
|
||||
|
||||
return hash_index;
|
||||
return hash_index;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -557,10 +574,8 @@ static void at91ether_set_rx_mode(struct net_device *dev)
|
|||
at91_emac_write(AT91_EMAC_CFG, cfg);
|
||||
}
|
||||
|
||||
|
||||
/* ......................... ETHTOOL SUPPORT ........................... */
|
||||
|
||||
|
||||
static int mdio_read(struct net_device *dev, int phy_id, int location)
|
||||
{
|
||||
unsigned int value;
|
||||
|
@ -642,6 +657,22 @@ static struct ethtool_ops at91ether_ethtool_ops = {
|
|||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
||||
static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
{
|
||||
struct at91_private *lp = (struct at91_private *) dev->priv;
|
||||
int res;
|
||||
|
||||
if (!netif_running(dev))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irq(&lp->lock);
|
||||
enable_mdi();
|
||||
res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
|
||||
disable_mdi();
|
||||
spin_unlock_irq(&lp->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* ................................ MAC ................................ */
|
||||
|
||||
|
@ -685,10 +716,10 @@ static int at91ether_open(struct net_device *dev)
|
|||
struct at91_private *lp = (struct at91_private *) dev->priv;
|
||||
unsigned long ctl;
|
||||
|
||||
if (!is_valid_ether_addr(dev->dev_addr))
|
||||
return -EADDRNOTAVAIL;
|
||||
if (!is_valid_ether_addr(dev->dev_addr))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
clk_enable(ether_clk); /* Re-enable Peripheral clock */
|
||||
clk_enable(lp->ether_clk); /* Re-enable Peripheral clock */
|
||||
|
||||
/* Clear internal statistics */
|
||||
ctl = at91_emac_read(AT91_EMAC_CTL);
|
||||
|
@ -708,7 +739,7 @@ static int at91ether_open(struct net_device *dev)
|
|||
/* Determine current link speed */
|
||||
spin_lock_irq(&lp->lock);
|
||||
enable_mdi();
|
||||
update_linkspeed(dev);
|
||||
update_linkspeed(dev, 0);
|
||||
disable_mdi();
|
||||
spin_unlock_irq(&lp->lock);
|
||||
|
||||
|
@ -722,6 +753,7 @@ static int at91ether_open(struct net_device *dev)
|
|||
*/
|
||||
static int at91ether_close(struct net_device *dev)
|
||||
{
|
||||
struct at91_private *lp = (struct at91_private *) dev->priv;
|
||||
unsigned long ctl;
|
||||
|
||||
/* Disable Receiver and Transmitter */
|
||||
|
@ -738,7 +770,7 @@ static int at91ether_close(struct net_device *dev)
|
|||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
clk_disable(ether_clk); /* Disable Peripheral clock */
|
||||
clk_disable(lp->ether_clk); /* Disable Peripheral clock */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -870,7 +902,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id, struct pt_regs *re
|
|||
if (intstatus & AT91_EMAC_RCOM) /* Receive complete */
|
||||
at91ether_rx(dev);
|
||||
|
||||
if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */
|
||||
if (intstatus & AT91_EMAC_TCOM) { /* Transmit complete */
|
||||
/* The TCOM bit is set even if the transmission failed. */
|
||||
if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
|
||||
lp->stats.tx_errors += 1;
|
||||
|
@ -899,7 +931,8 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id, struct pt_regs *re
|
|||
/*
|
||||
* Initialize the ethernet interface
|
||||
*/
|
||||
static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, struct platform_device *pdev)
|
||||
static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address,
|
||||
struct platform_device *pdev, struct clk *ether_clk)
|
||||
{
|
||||
struct at91_eth_data *board_data = pdev->dev.platform_data;
|
||||
struct net_device *dev;
|
||||
|
@ -933,6 +966,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
|
|||
return -ENOMEM;
|
||||
}
|
||||
lp->board_data = *board_data;
|
||||
lp->ether_clk = ether_clk;
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
spin_lock_init(&lp->lock);
|
||||
|
@ -945,6 +979,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
|
|||
dev->set_multicast_list = at91ether_set_rx_mode;
|
||||
dev->set_mac_address = set_mac_address;
|
||||
dev->ethtool_ops = &at91ether_ethtool_ops;
|
||||
dev->do_ioctl = at91ether_ioctl;
|
||||
|
||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||
|
||||
|
@ -975,6 +1010,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
|
|||
lp->mii.dev = dev; /* Support for ethtool */
|
||||
lp->mii.mdio_read = mdio_read;
|
||||
lp->mii.mdio_write = mdio_write;
|
||||
lp->mii.phy_id = phy_address;
|
||||
lp->mii.phy_id_mask = 0x1f;
|
||||
lp->mii.reg_num_mask = 0x1f;
|
||||
|
||||
lp->phy_type = phy_type; /* Type of PHY connected */
|
||||
lp->phy_address = phy_address; /* MDI address of PHY */
|
||||
|
@ -992,11 +1030,18 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
|
|||
/* Determine current link speed */
|
||||
spin_lock_irq(&lp->lock);
|
||||
enable_mdi();
|
||||
update_linkspeed(dev);
|
||||
update_linkspeed(dev, 0);
|
||||
disable_mdi();
|
||||
spin_unlock_irq(&lp->lock);
|
||||
netif_carrier_off(dev); /* will be enabled in open() */
|
||||
|
||||
/* If board has no PHY IRQ, use a timer to poll the PHY */
|
||||
if (!lp->board_data.phy_irq_pin) {
|
||||
init_timer(&check_timer);
|
||||
check_timer.data = (unsigned long)dev;
|
||||
check_timer.function = at91ether_check_link;
|
||||
}
|
||||
|
||||
/* Display ethernet banner */
|
||||
printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n",
|
||||
dev->name, (uint) dev->base_addr, dev->irq,
|
||||
|
@ -1005,7 +1050,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
|
|||
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
|
||||
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
|
||||
if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
|
||||
printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
|
||||
printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
|
||||
else if (phy_type == MII_LXT971A_ID)
|
||||
printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
|
||||
else if (phy_type == MII_RTL8201_ID)
|
||||
|
@ -1031,9 +1076,10 @@ static int __init at91ether_probe(struct platform_device *pdev)
|
|||
int detected = -1;
|
||||
unsigned long phy_id;
|
||||
unsigned short phy_address = 0;
|
||||
struct clk *ether_clk;
|
||||
|
||||
ether_clk = clk_get(&pdev->dev, "ether_clk");
|
||||
if (!ether_clk) {
|
||||
if (IS_ERR(ether_clk)) {
|
||||
printk(KERN_ERR "at91_ether: no clock defined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -1056,7 +1102,7 @@ static int __init at91ether_probe(struct platform_device *pdev)
|
|||
case MII_DP83847_ID: /* National Semiconductor DP83847: */
|
||||
case MII_AC101L_ID: /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
|
||||
case MII_KS8721_ID: /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
|
||||
detected = at91ether_setup(phy_id, phy_address, pdev);
|
||||
detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1075,17 +1121,61 @@ static int __devexit at91ether_remove(struct platform_device *pdev)
|
|||
unregister_netdev(at91_dev);
|
||||
free_irq(at91_dev->irq, at91_dev);
|
||||
dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
|
||||
clk_put(ether_clk);
|
||||
clk_put(lp->ether_clk);
|
||||
|
||||
free_netdev(at91_dev);
|
||||
at91_dev = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
|
||||
{
|
||||
struct at91_private *lp = (struct at91_private *) at91_dev->priv;
|
||||
struct net_device *net_dev = platform_get_drvdata(pdev);
|
||||
int phy_irq = lp->board_data.phy_irq_pin;
|
||||
|
||||
if (netif_running(net_dev)) {
|
||||
if (phy_irq)
|
||||
disable_irq(phy_irq);
|
||||
|
||||
netif_stop_queue(net_dev);
|
||||
netif_device_detach(net_dev);
|
||||
|
||||
clk_disable(lp->ether_clk);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at91ether_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct at91_private *lp = (struct at91_private *) at91_dev->priv;
|
||||
struct net_device *net_dev = platform_get_drvdata(pdev);
|
||||
int phy_irq = lp->board_data.phy_irq_pin;
|
||||
|
||||
if (netif_running(net_dev)) {
|
||||
clk_enable(lp->ether_clk);
|
||||
|
||||
netif_device_attach(net_dev);
|
||||
netif_start_queue(net_dev);
|
||||
|
||||
if (phy_irq)
|
||||
enable_irq(phy_irq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define at91ether_suspend NULL
|
||||
#define at91ether_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver at91ether_driver = {
|
||||
.probe = at91ether_probe,
|
||||
.remove = __devexit_p(at91ether_remove),
|
||||
/* FIXME: support suspend and resume */
|
||||
.suspend = at91ether_suspend,
|
||||
.resume = at91ether_resume,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -80,6 +80,7 @@ struct at91_private
|
|||
struct net_device_stats stats;
|
||||
struct mii_if_info mii; /* ethtool support */
|
||||
struct at91_eth_data board_data; /* board-specific configuration */
|
||||
struct clk *ether_clk; /* clock */
|
||||
|
||||
/* PHY */
|
||||
unsigned long phy_type; /* type of PHY (PHY_ID) */
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
#define DRV_MODULE_NAME "b44"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "1.00"
|
||||
#define DRV_MODULE_RELDATE "Apr 7, 2006"
|
||||
#define DRV_MODULE_VERSION "1.01"
|
||||
#define DRV_MODULE_RELDATE "Jun 16, 2006"
|
||||
|
||||
#define B44_DEF_MSG_ENABLE \
|
||||
(NETIF_MSG_DRV | \
|
||||
|
@ -75,6 +75,15 @@
|
|||
/* minimum number of free TX descriptors required to wake up TX process */
|
||||
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
|
||||
|
||||
/* b44 internal pattern match filter info */
|
||||
#define B44_PATTERN_BASE 0x400
|
||||
#define B44_PATTERN_SIZE 0x80
|
||||
#define B44_PMASK_BASE 0x600
|
||||
#define B44_PMASK_SIZE 0x10
|
||||
#define B44_MAX_PATTERNS 16
|
||||
#define B44_ETHIPV6UDP_HLEN 62
|
||||
#define B44_ETHIPV4UDP_HLEN 42
|
||||
|
||||
static char version[] __devinitdata =
|
||||
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
|
||||
|
||||
|
@ -101,7 +110,7 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
|
|||
|
||||
static void b44_halt(struct b44 *);
|
||||
static void b44_init_rings(struct b44 *);
|
||||
static void b44_init_hw(struct b44 *);
|
||||
static void b44_init_hw(struct b44 *, int);
|
||||
|
||||
static int dma_desc_align_mask;
|
||||
static int dma_desc_sync_size;
|
||||
|
@ -873,7 +882,7 @@ static int b44_poll(struct net_device *netdev, int *budget)
|
|||
spin_lock_irq(&bp->lock);
|
||||
b44_halt(bp);
|
||||
b44_init_rings(bp);
|
||||
b44_init_hw(bp);
|
||||
b44_init_hw(bp, 1);
|
||||
netif_wake_queue(bp->dev);
|
||||
spin_unlock_irq(&bp->lock);
|
||||
done = 1;
|
||||
|
@ -942,7 +951,7 @@ static void b44_tx_timeout(struct net_device *dev)
|
|||
|
||||
b44_halt(bp);
|
||||
b44_init_rings(bp);
|
||||
b44_init_hw(bp);
|
||||
b44_init_hw(bp, 1);
|
||||
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
|
@ -1059,7 +1068,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
|
|||
b44_halt(bp);
|
||||
dev->mtu = new_mtu;
|
||||
b44_init_rings(bp);
|
||||
b44_init_hw(bp);
|
||||
b44_init_hw(bp, 1);
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
b44_enable_ints(bp);
|
||||
|
@ -1356,13 +1365,15 @@ static int b44_set_mac_addr(struct net_device *dev, void *p)
|
|||
* packet processing. Invoked with bp->lock held.
|
||||
*/
|
||||
static void __b44_set_rx_mode(struct net_device *);
|
||||
static void b44_init_hw(struct b44 *bp)
|
||||
static void b44_init_hw(struct b44 *bp, int full_reset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
b44_chip_reset(bp);
|
||||
b44_phy_reset(bp);
|
||||
b44_setup_phy(bp);
|
||||
if (full_reset) {
|
||||
b44_phy_reset(bp);
|
||||
b44_setup_phy(bp);
|
||||
}
|
||||
|
||||
/* Enable CRC32, set proper LED modes and power on PHY */
|
||||
bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
|
||||
|
@ -1376,16 +1387,21 @@ static void b44_init_hw(struct b44 *bp)
|
|||
bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
|
||||
|
||||
bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
|
||||
bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
|
||||
bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
|
||||
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
|
||||
(bp->rx_offset << DMARX_CTRL_ROSHIFT)));
|
||||
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
|
||||
if (full_reset) {
|
||||
bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
|
||||
bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
|
||||
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
|
||||
(bp->rx_offset << DMARX_CTRL_ROSHIFT)));
|
||||
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
|
||||
|
||||
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
|
||||
bp->rx_prod = bp->rx_pending;
|
||||
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
|
||||
bp->rx_prod = bp->rx_pending;
|
||||
|
||||
bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
|
||||
bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
|
||||
} else {
|
||||
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
|
||||
(bp->rx_offset << DMARX_CTRL_ROSHIFT)));
|
||||
}
|
||||
|
||||
val = br32(bp, B44_ENET_CTRL);
|
||||
bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
|
||||
|
@ -1401,7 +1417,7 @@ static int b44_open(struct net_device *dev)
|
|||
goto out;
|
||||
|
||||
b44_init_rings(bp);
|
||||
b44_init_hw(bp);
|
||||
b44_init_hw(bp, 1);
|
||||
|
||||
b44_check_phy(bp);
|
||||
|
||||
|
@ -1450,6 +1466,140 @@ static void b44_poll_controller(struct net_device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset)
|
||||
{
|
||||
u32 i;
|
||||
u32 *pattern = (u32 *) pp;
|
||||
|
||||
for (i = 0; i < bytes; i += sizeof(u32)) {
|
||||
bw32(bp, B44_FILT_ADDR, table_offset + i);
|
||||
bw32(bp, B44_FILT_DATA, pattern[i / sizeof(u32)]);
|
||||
}
|
||||
}
|
||||
|
||||
static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
|
||||
{
|
||||
int magicsync = 6;
|
||||
int k, j, len = offset;
|
||||
int ethaddr_bytes = ETH_ALEN;
|
||||
|
||||
memset(ppattern + offset, 0xff, magicsync);
|
||||
for (j = 0; j < magicsync; j++)
|
||||
set_bit(len++, (unsigned long *) pmask);
|
||||
|
||||
for (j = 0; j < B44_MAX_PATTERNS; j++) {
|
||||
if ((B44_PATTERN_SIZE - len) >= ETH_ALEN)
|
||||
ethaddr_bytes = ETH_ALEN;
|
||||
else
|
||||
ethaddr_bytes = B44_PATTERN_SIZE - len;
|
||||
if (ethaddr_bytes <=0)
|
||||
break;
|
||||
for (k = 0; k< ethaddr_bytes; k++) {
|
||||
ppattern[offset + magicsync +
|
||||
(j * ETH_ALEN) + k] = macaddr[k];
|
||||
len++;
|
||||
set_bit(len, (unsigned long *) pmask);
|
||||
}
|
||||
}
|
||||
return len - 1;
|
||||
}
|
||||
|
||||
/* Setup magic packet patterns in the b44 WOL
|
||||
* pattern matching filter.
|
||||
*/
|
||||
static void b44_setup_pseudo_magicp(struct b44 *bp)
|
||||
{
|
||||
|
||||
u32 val;
|
||||
int plen0, plen1, plen2;
|
||||
u8 *pwol_pattern;
|
||||
u8 pwol_mask[B44_PMASK_SIZE];
|
||||
|
||||
pwol_pattern = kmalloc(B44_PATTERN_SIZE, GFP_KERNEL);
|
||||
if (!pwol_pattern) {
|
||||
printk(KERN_ERR PFX "Memory not available for WOL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ipv4 magic packet pattern - pattern 0.*/
|
||||
memset(pwol_pattern, 0, B44_PATTERN_SIZE);
|
||||
memset(pwol_mask, 0, B44_PMASK_SIZE);
|
||||
plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
|
||||
B44_ETHIPV4UDP_HLEN);
|
||||
|
||||
bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, B44_PATTERN_BASE);
|
||||
bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, B44_PMASK_BASE);
|
||||
|
||||
/* Raw ethernet II magic packet pattern - pattern 1 */
|
||||
memset(pwol_pattern, 0, B44_PATTERN_SIZE);
|
||||
memset(pwol_mask, 0, B44_PMASK_SIZE);
|
||||
plen1 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
|
||||
ETH_HLEN);
|
||||
|
||||
bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE,
|
||||
B44_PATTERN_BASE + B44_PATTERN_SIZE);
|
||||
bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE,
|
||||
B44_PMASK_BASE + B44_PMASK_SIZE);
|
||||
|
||||
/* Ipv6 magic packet pattern - pattern 2 */
|
||||
memset(pwol_pattern, 0, B44_PATTERN_SIZE);
|
||||
memset(pwol_mask, 0, B44_PMASK_SIZE);
|
||||
plen2 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
|
||||
B44_ETHIPV6UDP_HLEN);
|
||||
|
||||
bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE,
|
||||
B44_PATTERN_BASE + B44_PATTERN_SIZE + B44_PATTERN_SIZE);
|
||||
bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE,
|
||||
B44_PMASK_BASE + B44_PMASK_SIZE + B44_PMASK_SIZE);
|
||||
|
||||
kfree(pwol_pattern);
|
||||
|
||||
/* set these pattern's lengths: one less than each real length */
|
||||
val = plen0 | (plen1 << 8) | (plen2 << 16) | WKUP_LEN_ENABLE_THREE;
|
||||
bw32(bp, B44_WKUP_LEN, val);
|
||||
|
||||
/* enable wakeup pattern matching */
|
||||
val = br32(bp, B44_DEVCTRL);
|
||||
bw32(bp, B44_DEVCTRL, val | DEVCTRL_PFE);
|
||||
|
||||
}
|
||||
|
||||
static void b44_setup_wol(struct b44 *bp)
|
||||
{
|
||||
u32 val;
|
||||
u16 pmval;
|
||||
|
||||
bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI);
|
||||
|
||||
if (bp->flags & B44_FLAG_B0_ANDLATER) {
|
||||
|
||||
bw32(bp, B44_WKUP_LEN, WKUP_LEN_DISABLE);
|
||||
|
||||
val = bp->dev->dev_addr[2] << 24 |
|
||||
bp->dev->dev_addr[3] << 16 |
|
||||
bp->dev->dev_addr[4] << 8 |
|
||||
bp->dev->dev_addr[5];
|
||||
bw32(bp, B44_ADDR_LO, val);
|
||||
|
||||
val = bp->dev->dev_addr[0] << 8 |
|
||||
bp->dev->dev_addr[1];
|
||||
bw32(bp, B44_ADDR_HI, val);
|
||||
|
||||
val = br32(bp, B44_DEVCTRL);
|
||||
bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE);
|
||||
|
||||
} else {
|
||||
b44_setup_pseudo_magicp(bp);
|
||||
}
|
||||
|
||||
val = br32(bp, B44_SBTMSLOW);
|
||||
bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE);
|
||||
|
||||
pci_read_config_word(bp->pdev, SSB_PMCSR, &pmval);
|
||||
pci_write_config_word(bp->pdev, SSB_PMCSR, pmval | SSB_PE);
|
||||
|
||||
}
|
||||
|
||||
static int b44_close(struct net_device *dev)
|
||||
{
|
||||
struct b44 *bp = netdev_priv(dev);
|
||||
|
@ -1475,6 +1625,11 @@ static int b44_close(struct net_device *dev)
|
|||
|
||||
netif_poll_enable(dev);
|
||||
|
||||
if (bp->flags & B44_FLAG_WOL_ENABLE) {
|
||||
b44_init_hw(bp, 0);
|
||||
b44_setup_wol(bp);
|
||||
}
|
||||
|
||||
b44_free_consistent(bp);
|
||||
|
||||
return 0;
|
||||
|
@ -1620,8 +1775,6 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
|||
{
|
||||
struct b44 *bp = netdev_priv(dev);
|
||||
|
||||
if (!netif_running(dev))
|
||||
return -EAGAIN;
|
||||
cmd->supported = (SUPPORTED_Autoneg);
|
||||
cmd->supported |= (SUPPORTED_100baseT_Half |
|
||||
SUPPORTED_100baseT_Full |
|
||||
|
@ -1649,6 +1802,12 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
|||
XCVR_INTERNAL : XCVR_EXTERNAL;
|
||||
cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
|
||||
AUTONEG_DISABLE : AUTONEG_ENABLE;
|
||||
if (cmd->autoneg == AUTONEG_ENABLE)
|
||||
cmd->advertising |= ADVERTISED_Autoneg;
|
||||
if (!netif_running(dev)){
|
||||
cmd->speed = 0;
|
||||
cmd->duplex = 0xff;
|
||||
}
|
||||
cmd->maxtxpkt = 0;
|
||||
cmd->maxrxpkt = 0;
|
||||
return 0;
|
||||
|
@ -1658,9 +1817,6 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
|||
{
|
||||
struct b44 *bp = netdev_priv(dev);
|
||||
|
||||
if (!netif_running(dev))
|
||||
return -EAGAIN;
|
||||
|
||||
/* We do not support gigabit. */
|
||||
if (cmd->autoneg == AUTONEG_ENABLE) {
|
||||
if (cmd->advertising &
|
||||
|
@ -1677,28 +1833,39 @@ static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
|||
spin_lock_irq(&bp->lock);
|
||||
|
||||
if (cmd->autoneg == AUTONEG_ENABLE) {
|
||||
bp->flags &= ~B44_FLAG_FORCE_LINK;
|
||||
bp->flags &= ~(B44_FLAG_ADV_10HALF |
|
||||
bp->flags &= ~(B44_FLAG_FORCE_LINK |
|
||||
B44_FLAG_100_BASE_T |
|
||||
B44_FLAG_FULL_DUPLEX |
|
||||
B44_FLAG_ADV_10HALF |
|
||||
B44_FLAG_ADV_10FULL |
|
||||
B44_FLAG_ADV_100HALF |
|
||||
B44_FLAG_ADV_100FULL);
|
||||
if (cmd->advertising & ADVERTISE_10HALF)
|
||||
bp->flags |= B44_FLAG_ADV_10HALF;
|
||||
if (cmd->advertising & ADVERTISE_10FULL)
|
||||
bp->flags |= B44_FLAG_ADV_10FULL;
|
||||
if (cmd->advertising & ADVERTISE_100HALF)
|
||||
bp->flags |= B44_FLAG_ADV_100HALF;
|
||||
if (cmd->advertising & ADVERTISE_100FULL)
|
||||
bp->flags |= B44_FLAG_ADV_100FULL;
|
||||
if (cmd->advertising == 0) {
|
||||
bp->flags |= (B44_FLAG_ADV_10HALF |
|
||||
B44_FLAG_ADV_10FULL |
|
||||
B44_FLAG_ADV_100HALF |
|
||||
B44_FLAG_ADV_100FULL);
|
||||
} else {
|
||||
if (cmd->advertising & ADVERTISED_10baseT_Half)
|
||||
bp->flags |= B44_FLAG_ADV_10HALF;
|
||||
if (cmd->advertising & ADVERTISED_10baseT_Full)
|
||||
bp->flags |= B44_FLAG_ADV_10FULL;
|
||||
if (cmd->advertising & ADVERTISED_100baseT_Half)
|
||||
bp->flags |= B44_FLAG_ADV_100HALF;
|
||||
if (cmd->advertising & ADVERTISED_100baseT_Full)
|
||||
bp->flags |= B44_FLAG_ADV_100FULL;
|
||||
}
|
||||
} else {
|
||||
bp->flags |= B44_FLAG_FORCE_LINK;
|
||||
bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX);
|
||||
if (cmd->speed == SPEED_100)
|
||||
bp->flags |= B44_FLAG_100_BASE_T;
|
||||
if (cmd->duplex == DUPLEX_FULL)
|
||||
bp->flags |= B44_FLAG_FULL_DUPLEX;
|
||||
}
|
||||
|
||||
b44_setup_phy(bp);
|
||||
if (netif_running(dev))
|
||||
b44_setup_phy(bp);
|
||||
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
|
@ -1734,7 +1901,7 @@ static int b44_set_ringparam(struct net_device *dev,
|
|||
|
||||
b44_halt(bp);
|
||||
b44_init_rings(bp);
|
||||
b44_init_hw(bp);
|
||||
b44_init_hw(bp, 1);
|
||||
netif_wake_queue(bp->dev);
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
|
@ -1777,7 +1944,7 @@ static int b44_set_pauseparam(struct net_device *dev,
|
|||
if (bp->flags & B44_FLAG_PAUSE_AUTO) {
|
||||
b44_halt(bp);
|
||||
b44_init_rings(bp);
|
||||
b44_init_hw(bp);
|
||||
b44_init_hw(bp, 1);
|
||||
} else {
|
||||
__b44_set_flow_ctrl(bp, bp->flags);
|
||||
}
|
||||
|
@ -1819,12 +1986,40 @@ static void b44_get_ethtool_stats(struct net_device *dev,
|
|||
spin_unlock_irq(&bp->lock);
|
||||
}
|
||||
|
||||
static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct b44 *bp = netdev_priv(dev);
|
||||
|
||||
wol->supported = WAKE_MAGIC;
|
||||
if (bp->flags & B44_FLAG_WOL_ENABLE)
|
||||
wol->wolopts = WAKE_MAGIC;
|
||||
else
|
||||
wol->wolopts = 0;
|
||||
memset(&wol->sopass, 0, sizeof(wol->sopass));
|
||||
}
|
||||
|
||||
static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct b44 *bp = netdev_priv(dev);
|
||||
|
||||
spin_lock_irq(&bp->lock);
|
||||
if (wol->wolopts & WAKE_MAGIC)
|
||||
bp->flags |= B44_FLAG_WOL_ENABLE;
|
||||
else
|
||||
bp->flags &= ~B44_FLAG_WOL_ENABLE;
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ethtool_ops b44_ethtool_ops = {
|
||||
.get_drvinfo = b44_get_drvinfo,
|
||||
.get_settings = b44_get_settings,
|
||||
.set_settings = b44_set_settings,
|
||||
.nway_reset = b44_nway_reset,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_wol = b44_get_wol,
|
||||
.set_wol = b44_set_wol,
|
||||
.get_ringparam = b44_get_ringparam,
|
||||
.set_ringparam = b44_set_ringparam,
|
||||
.get_pauseparam = b44_get_pauseparam,
|
||||
|
@ -1903,6 +2098,10 @@ static int __devinit b44_get_invariants(struct b44 *bp)
|
|||
/* XXX - really required?
|
||||
bp->flags |= B44_FLAG_BUGGY_TXPTR;
|
||||
*/
|
||||
|
||||
if (ssb_get_core_rev(bp) >= 7)
|
||||
bp->flags |= B44_FLAG_B0_ANDLATER;
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -2103,6 +2302,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
free_irq(dev->irq, dev);
|
||||
if (bp->flags & B44_FLAG_WOL_ENABLE) {
|
||||
b44_init_hw(bp, 0);
|
||||
b44_setup_wol(bp);
|
||||
}
|
||||
pci_disable_device(pdev);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2125,7 +2328,7 @@ static int b44_resume(struct pci_dev *pdev)
|
|||
spin_lock_irq(&bp->lock);
|
||||
|
||||
b44_init_rings(bp);
|
||||
b44_init_hw(bp);
|
||||
b44_init_hw(bp, 1);
|
||||
netif_device_attach(bp->dev);
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#define WKUP_LEN_P3_MASK 0x7f000000 /* Pattern 3 */
|
||||
#define WKUP_LEN_P3_SHIFT 24
|
||||
#define WKUP_LEN_D3 0x80000000
|
||||
#define WKUP_LEN_DISABLE 0x80808080
|
||||
#define WKUP_LEN_ENABLE_TWO 0x80800000
|
||||
#define WKUP_LEN_ENABLE_THREE 0x80000000
|
||||
#define B44_ISTAT 0x0020UL /* Interrupt Status */
|
||||
#define ISTAT_LS 0x00000020 /* Link Change (B0 only) */
|
||||
#define ISTAT_PME 0x00000040 /* Power Management Event */
|
||||
|
@ -264,6 +267,8 @@
|
|||
#define SBIDHIGH_VC_SHIFT 16
|
||||
|
||||
/* SSB PCI config space registers. */
|
||||
#define SSB_PMCSR 0x44
|
||||
#define SSB_PE 0x100
|
||||
#define SSB_BAR0_WIN 0x80
|
||||
#define SSB_BAR1_WIN 0x84
|
||||
#define SSB_SPROM_CONTROL 0x88
|
||||
|
@ -420,6 +425,7 @@ struct b44 {
|
|||
|
||||
u32 dma_offset;
|
||||
u32 flags;
|
||||
#define B44_FLAG_B0_ANDLATER 0x00000001
|
||||
#define B44_FLAG_BUGGY_TXPTR 0x00000002
|
||||
#define B44_FLAG_REORDER_BUG 0x00000004
|
||||
#define B44_FLAG_PAUSE_AUTO 0x00008000
|
||||
|
@ -435,6 +441,7 @@ struct b44 {
|
|||
#define B44_FLAG_INTERNAL_PHY 0x10000000
|
||||
#define B44_FLAG_RX_RING_HACK 0x20000000
|
||||
#define B44_FLAG_TX_RING_HACK 0x40000000
|
||||
#define B44_FLAG_WOL_ENABLE 0x80000000
|
||||
|
||||
u32 rx_offset;
|
||||
|
||||
|
|
|
@ -2076,7 +2076,7 @@ static void nv_set_multicast(struct net_device *dev)
|
|||
spin_unlock_irq(&np->lock);
|
||||
}
|
||||
|
||||
void nv_update_pause(struct net_device *dev, u32 pause_flags)
|
||||
static void nv_update_pause(struct net_device *dev, u32 pause_flags)
|
||||
{
|
||||
struct fe_priv *np = netdev_priv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
|
|
@ -145,7 +145,7 @@ static inline struct sk_buff * ioc3_alloc_skb(unsigned long length,
|
|||
static inline unsigned long ioc3_map(void *ptr, unsigned long vdev)
|
||||
{
|
||||
#ifdef CONFIG_SGI_IP27
|
||||
vdev <<= 58; /* Shift to PCI64_ATTR_VIRTUAL */
|
||||
vdev <<= 57; /* Shift to PCI64_ATTR_VIRTUAL */
|
||||
|
||||
return vdev | (0xaUL << PCI64_ATTR_TARG_SHFT) | PCI64_ATTR_PREF |
|
||||
((unsigned long)ptr & TO_PHYS_MASK);
|
||||
|
|
|
@ -2251,12 +2251,6 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
|
|||
}
|
||||
|
||||
cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR);
|
||||
/* nvidia ext cap is not always linked in ext cap chain */
|
||||
if (!cap
|
||||
&& bridge->vendor == PCI_VENDOR_ID_NVIDIA
|
||||
&& bridge->device == PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_PCIE)
|
||||
cap = 0x160;
|
||||
|
||||
if (!cap)
|
||||
return;
|
||||
|
||||
|
@ -2732,8 +2726,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
/* Save configuration space to be restored if the
|
||||
* nic resets due to a parity error */
|
||||
myri10ge_save_state(mgp);
|
||||
/* Restore state immediately since pci_save_msi_state disables MSI */
|
||||
myri10ge_restore_state(mgp);
|
||||
|
||||
/* Setup the watchdog timer */
|
||||
setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
|
||||
|
|
516
drivers/net/netx-eth.c
Normal file
516
drivers/net/netx-eth.c
Normal file
|
@ -0,0 +1,516 @@
|
|||
/*
|
||||
* drivers/net/netx-eth.c
|
||||
*
|
||||
* Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/mii.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/netx-regs.h>
|
||||
#include <asm/arch/pfifo.h>
|
||||
#include <asm/arch/xc.h>
|
||||
#include <asm/arch/eth.h>
|
||||
|
||||
/* XC Fifo Offsets */
|
||||
#define EMPTY_PTR_FIFO(xcno) (0 + ((xcno) << 3)) /* Index of the empty pointer FIFO */
|
||||
#define IND_FIFO_PORT_HI(xcno) (1 + ((xcno) << 3)) /* Index of the FIFO where received */
|
||||
/* Data packages are indicated by XC */
|
||||
#define IND_FIFO_PORT_LO(xcno) (2 + ((xcno) << 3)) /* Index of the FIFO where received */
|
||||
/* Data packages are indicated by XC */
|
||||
#define REQ_FIFO_PORT_HI(xcno) (3 + ((xcno) << 3)) /* Index of the FIFO where Data packages */
|
||||
/* have to be indicated by ARM which */
|
||||
/* shall be sent */
|
||||
#define REQ_FIFO_PORT_LO(xcno) (4 + ((xcno) << 3)) /* Index of the FIFO where Data packages */
|
||||
/* have to be indicated by ARM which shall */
|
||||
/* be sent */
|
||||
#define CON_FIFO_PORT_HI(xcno) (5 + ((xcno) << 3)) /* Index of the FIFO where sent Data packages */
|
||||
/* are confirmed */
|
||||
#define CON_FIFO_PORT_LO(xcno) (6 + ((xcno) << 3)) /* Index of the FIFO where sent Data */
|
||||
/* packages are confirmed */
|
||||
#define PFIFO_MASK(xcno) (0x7f << (xcno*8))
|
||||
|
||||
#define FIFO_PTR_FRAMELEN_SHIFT 0
|
||||
#define FIFO_PTR_FRAMELEN_MASK (0x7ff << 0)
|
||||
#define FIFO_PTR_FRAMELEN(len) (((len) << 0) & FIFO_PTR_FRAMELEN_MASK)
|
||||
#define FIFO_PTR_TIMETRIG (1<<11)
|
||||
#define FIFO_PTR_MULTI_REQ
|
||||
#define FIFO_PTR_ORIGIN (1<<14)
|
||||
#define FIFO_PTR_VLAN (1<<15)
|
||||
#define FIFO_PTR_FRAMENO_SHIFT 16
|
||||
#define FIFO_PTR_FRAMENO_MASK (0x3f << 16)
|
||||
#define FIFO_PTR_FRAMENO(no) (((no) << 16) & FIFO_PTR_FRAMENO_MASK)
|
||||
#define FIFO_PTR_SEGMENT_SHIFT 22
|
||||
#define FIFO_PTR_SEGMENT_MASK (0xf << 22)
|
||||
#define FIFO_PTR_SEGMENT(seg) (((seg) & 0xf) << 22)
|
||||
#define FIFO_PTR_ERROR_SHIFT 28
|
||||
#define FIFO_PTR_ERROR_MASK (0xf << 28)
|
||||
|
||||
#define ISR_LINK_STATUS_CHANGE (1<<4)
|
||||
#define ISR_IND_LO (1<<3)
|
||||
#define ISR_CON_LO (1<<2)
|
||||
#define ISR_IND_HI (1<<1)
|
||||
#define ISR_CON_HI (1<<0)
|
||||
|
||||
#define ETH_MAC_LOCAL_CONFIG 0x1560
|
||||
#define ETH_MAC_4321 0x1564
|
||||
#define ETH_MAC_65 0x1568
|
||||
|
||||
#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16
|
||||
#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT)
|
||||
#define MAC_TRAFFIC_CLASS_ARRANGEMENT(x) (((x)<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) & MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK)
|
||||
#define LOCAL_CONFIG_LINK_STATUS_IRQ_EN (1<<24)
|
||||
#define LOCAL_CONFIG_CON_LO_IRQ_EN (1<<23)
|
||||
#define LOCAL_CONFIG_CON_HI_IRQ_EN (1<<22)
|
||||
#define LOCAL_CONFIG_IND_LO_IRQ_EN (1<<21)
|
||||
#define LOCAL_CONFIG_IND_HI_IRQ_EN (1<<20)
|
||||
|
||||
#define CARDNAME "netx-eth"
|
||||
|
||||
/* LSB must be zero */
|
||||
#define INTERNAL_PHY_ADR 0x1c
|
||||
|
||||
struct netx_eth_priv {
|
||||
void __iomem *sram_base, *xpec_base, *xmac_base;
|
||||
int id;
|
||||
struct net_device_stats stats;
|
||||
struct mii_if_info mii;
|
||||
u32 msg_enable;
|
||||
struct xc *xc;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static void netx_eth_set_multicast_list(struct net_device *ndev)
|
||||
{
|
||||
/* implement me */
|
||||
}
|
||||
|
||||
static int
|
||||
netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
{
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
unsigned char *buf = skb->data;
|
||||
unsigned int len = skb->len;
|
||||
|
||||
spin_lock_irq(&priv->lock);
|
||||
memcpy_toio(priv->sram_base + 1560, (void *)buf, len);
|
||||
if (len < 60) {
|
||||
memset_io(priv->sram_base + 1560 + len, 0, 60 - len);
|
||||
len = 60;
|
||||
}
|
||||
|
||||
pfifo_push(REQ_FIFO_PORT_LO(priv->id),
|
||||
FIFO_PTR_SEGMENT(priv->id) |
|
||||
FIFO_PTR_FRAMENO(1) |
|
||||
FIFO_PTR_FRAMELEN(len));
|
||||
|
||||
ndev->trans_start = jiffies;
|
||||
priv->stats.tx_packets++;
|
||||
priv->stats.tx_bytes += skb->len;
|
||||
|
||||
netif_stop_queue(ndev);
|
||||
spin_unlock_irq(&priv->lock);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void netx_eth_receive(struct net_device *ndev)
|
||||
{
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
unsigned int val, frameno, seg, len;
|
||||
unsigned char *data;
|
||||
struct sk_buff *skb;
|
||||
|
||||
val = pfifo_pop(IND_FIFO_PORT_LO(priv->id));
|
||||
|
||||
frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT;
|
||||
seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT;
|
||||
len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT;
|
||||
|
||||
skb = dev_alloc_skb(len);
|
||||
if (unlikely(skb == NULL)) {
|
||||
printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
|
||||
ndev->name);
|
||||
priv->stats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
|
||||
data = skb_put(skb, len);
|
||||
|
||||
memcpy_fromio(data, priv->sram_base + frameno * 1560, len);
|
||||
|
||||
pfifo_push(EMPTY_PTR_FIFO(priv->id),
|
||||
FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno));
|
||||
|
||||
ndev->last_rx = jiffies;
|
||||
skb->dev = ndev;
|
||||
skb->protocol = eth_type_trans(skb, ndev);
|
||||
netif_rx(skb);
|
||||
priv->stats.rx_packets++;
|
||||
priv->stats.rx_bytes += len;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
netx_eth_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct net_device *ndev = dev_id;
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
int status;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
|
||||
while (status) {
|
||||
int fill_level;
|
||||
writel(status, NETX_PFIFO_XPEC_ISR(priv->id));
|
||||
|
||||
if ((status & ISR_CON_HI) || (status & ISR_IND_HI))
|
||||
printk("%s: unexpected status: 0x%08x\n",
|
||||
__FUNCTION__, status);
|
||||
|
||||
fill_level =
|
||||
readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id)));
|
||||
while (fill_level--)
|
||||
netx_eth_receive(ndev);
|
||||
|
||||
if (status & ISR_CON_LO)
|
||||
netif_wake_queue(ndev);
|
||||
|
||||
if (status & ISR_LINK_STATUS_CHANGE)
|
||||
mii_check_media(&priv->mii, netif_msg_link(priv), 1);
|
||||
|
||||
status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct net_device_stats *netx_eth_query_statistics(struct net_device *ndev)
|
||||
{
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
return &priv->stats;
|
||||
}
|
||||
|
||||
static int netx_eth_open(struct net_device *ndev)
|
||||
{
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
|
||||
if (request_irq
|
||||
(ndev->irq, &netx_eth_interrupt, SA_SHIRQ, ndev->name, ndev))
|
||||
return -EAGAIN;
|
||||
|
||||
writel(ndev->dev_addr[0] |
|
||||
ndev->dev_addr[1]<<8 |
|
||||
ndev->dev_addr[2]<<16 |
|
||||
ndev->dev_addr[3]<<24,
|
||||
priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
|
||||
writel(ndev->dev_addr[4] |
|
||||
ndev->dev_addr[5]<<8,
|
||||
priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65);
|
||||
|
||||
writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN |
|
||||
LOCAL_CONFIG_CON_LO_IRQ_EN |
|
||||
LOCAL_CONFIG_CON_HI_IRQ_EN |
|
||||
LOCAL_CONFIG_IND_LO_IRQ_EN |
|
||||
LOCAL_CONFIG_IND_HI_IRQ_EN,
|
||||
priv->xpec_base + NETX_XPEC_RAM_START_OFS +
|
||||
ETH_MAC_LOCAL_CONFIG);
|
||||
|
||||
mii_check_media(&priv->mii, netif_msg_link(priv), 1);
|
||||
netif_start_queue(ndev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netx_eth_close(struct net_device *ndev)
|
||||
{
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
writel(0,
|
||||
priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_LOCAL_CONFIG);
|
||||
|
||||
free_irq(ndev->irq, ndev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void netx_eth_timeout(struct net_device *ndev)
|
||||
{
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
int i;
|
||||
|
||||
printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name);
|
||||
|
||||
spin_lock_irq(&priv->lock);
|
||||
|
||||
xc_reset(priv->xc);
|
||||
xc_start(priv->xc);
|
||||
|
||||
for (i=2; i<=18; i++)
|
||||
pfifo_push(EMPTY_PTR_FIFO(priv->id),
|
||||
FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id));
|
||||
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
netif_wake_queue(ndev);
|
||||
}
|
||||
|
||||
static int
|
||||
netx_eth_phy_read(struct net_device *ndev, int phy_id, int reg)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) |
|
||||
MIIMU_REGADDR(reg) | MIIMU_PHY_NRES;
|
||||
|
||||
writel(val, NETX_MIIMU);
|
||||
while (readl(NETX_MIIMU) & MIIMU_SNRDY);
|
||||
|
||||
return readl(NETX_MIIMU) >> 16;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) |
|
||||
MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE |
|
||||
MIIMU_DATA(value);
|
||||
|
||||
writel(val, NETX_MIIMU);
|
||||
while (readl(NETX_MIIMU) & MIIMU_SNRDY);
|
||||
}
|
||||
|
||||
static int netx_eth_enable(struct net_device *ndev)
|
||||
{
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
unsigned int mac4321, mac65;
|
||||
int running, i;
|
||||
|
||||
ether_setup(ndev);
|
||||
|
||||
ndev->open = netx_eth_open;
|
||||
ndev->stop = netx_eth_close;
|
||||
ndev->hard_start_xmit = netx_eth_hard_start_xmit;
|
||||
ndev->tx_timeout = netx_eth_timeout;
|
||||
ndev->watchdog_timeo = msecs_to_jiffies(5000);
|
||||
ndev->get_stats = netx_eth_query_statistics;
|
||||
ndev->set_multicast_list = netx_eth_set_multicast_list;
|
||||
|
||||
priv->msg_enable = NETIF_MSG_LINK;
|
||||
priv->mii.phy_id_mask = 0x1f;
|
||||
priv->mii.reg_num_mask = 0x1f;
|
||||
priv->mii.force_media = 0;
|
||||
priv->mii.full_duplex = 0;
|
||||
priv->mii.dev = ndev;
|
||||
priv->mii.mdio_read = netx_eth_phy_read;
|
||||
priv->mii.mdio_write = netx_eth_phy_write;
|
||||
priv->mii.phy_id = INTERNAL_PHY_ADR + priv->id;
|
||||
|
||||
running = xc_running(priv->xc);
|
||||
xc_stop(priv->xc);
|
||||
|
||||
/* if the xc engine is already running, assume the bootloader has
|
||||
* loaded the firmware for us
|
||||
*/
|
||||
if (running) {
|
||||
/* get Node Address from hardware */
|
||||
mac4321 = readl(priv->xpec_base +
|
||||
NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
|
||||
mac65 = readl(priv->xpec_base +
|
||||
NETX_XPEC_RAM_START_OFS + ETH_MAC_65);
|
||||
|
||||
ndev->dev_addr[0] = mac4321 & 0xff;
|
||||
ndev->dev_addr[1] = (mac4321 >> 8) & 0xff;
|
||||
ndev->dev_addr[2] = (mac4321 >> 16) & 0xff;
|
||||
ndev->dev_addr[3] = (mac4321 >> 24) & 0xff;
|
||||
ndev->dev_addr[4] = mac65 & 0xff;
|
||||
ndev->dev_addr[5] = (mac65 >> 8) & 0xff;
|
||||
} else {
|
||||
if (xc_request_firmware(priv->xc)) {
|
||||
printk(CARDNAME ": requesting firmware failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
xc_reset(priv->xc);
|
||||
xc_start(priv->xc);
|
||||
|
||||
if (!is_valid_ether_addr(ndev->dev_addr))
|
||||
printk("%s: Invalid ethernet MAC address. Please "
|
||||
"set using ifconfig\n", ndev->name);
|
||||
|
||||
for (i=2; i<=18; i++)
|
||||
pfifo_push(EMPTY_PTR_FIFO(priv->id),
|
||||
FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id));
|
||||
|
||||
return register_netdev(ndev);
|
||||
|
||||
}
|
||||
|
||||
static int netx_eth_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct netx_eth_priv *priv;
|
||||
struct net_device *ndev;
|
||||
struct netxeth_platform_data *pdata;
|
||||
int ret;
|
||||
|
||||
ndev = alloc_etherdev(sizeof (struct netx_eth_priv));
|
||||
if (!ndev) {
|
||||
printk("%s: could not allocate device.\n", CARDNAME);
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
SET_MODULE_OWNER(ndev);
|
||||
SET_NETDEV_DEV(ndev, &pdev->dev);
|
||||
|
||||
platform_set_drvdata(pdev, ndev);
|
||||
|
||||
priv = netdev_priv(ndev);
|
||||
|
||||
pdata = (struct netxeth_platform_data *)pdev->dev.platform_data;
|
||||
priv->xc = request_xc(pdata->xcno, &pdev->dev);
|
||||
if (!priv->xc) {
|
||||
dev_err(&pdev->dev, "unable to request xc engine\n");
|
||||
ret = -ENODEV;
|
||||
goto exit_free_netdev;
|
||||
}
|
||||
|
||||
ndev->irq = priv->xc->irq;
|
||||
priv->id = pdev->id;
|
||||
priv->xpec_base = priv->xc->xpec_base;
|
||||
priv->xmac_base = priv->xc->xmac_base;
|
||||
priv->sram_base = priv->xc->sram_base;
|
||||
|
||||
ret = pfifo_request(PFIFO_MASK(priv->id));
|
||||
if (ret) {
|
||||
printk("unable to request PFIFO\n");
|
||||
goto exit_free_xc;
|
||||
}
|
||||
|
||||
ret = netx_eth_enable(ndev);
|
||||
if (ret)
|
||||
goto exit_free_pfifo;
|
||||
|
||||
return 0;
|
||||
exit_free_pfifo:
|
||||
pfifo_free(PFIFO_MASK(priv->id));
|
||||
exit_free_xc:
|
||||
free_xc(priv->xc);
|
||||
exit_free_netdev:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
free_netdev(ndev);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int netx_eth_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct net_device *ndev = dev_get_drvdata(&pdev->dev);
|
||||
struct netx_eth_priv *priv = netdev_priv(ndev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
unregister_netdev(ndev);
|
||||
xc_stop(priv->xc);
|
||||
free_xc(priv->xc);
|
||||
free_netdev(ndev);
|
||||
pfifo_free(PFIFO_MASK(priv->id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netx_eth_drv_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
dev_err(&pdev->dev, "suspend not implemented\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netx_eth_drv_resume(struct platform_device *pdev)
|
||||
{
|
||||
dev_err(&pdev->dev, "resume not implemented\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver netx_eth_driver = {
|
||||
.probe = netx_eth_drv_probe,
|
||||
.remove = netx_eth_drv_remove,
|
||||
.suspend = netx_eth_drv_suspend,
|
||||
.resume = netx_eth_drv_resume,
|
||||
.driver = {
|
||||
.name = CARDNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init netx_eth_init(void)
|
||||
{
|
||||
unsigned int phy_control, val;
|
||||
|
||||
printk("NetX Ethernet driver\n");
|
||||
|
||||
phy_control = PHY_CONTROL_PHY_ADDRESS(INTERNAL_PHY_ADR>>1) |
|
||||
PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) |
|
||||
PHY_CONTROL_PHY1_AUTOMDIX |
|
||||
PHY_CONTROL_PHY1_EN |
|
||||
PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) |
|
||||
PHY_CONTROL_PHY0_AUTOMDIX |
|
||||
PHY_CONTROL_PHY0_EN |
|
||||
PHY_CONTROL_CLK_XLATIN;
|
||||
|
||||
val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
|
||||
writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
|
||||
|
||||
writel(phy_control | PHY_CONTROL_RESET, NETX_SYSTEM_PHY_CONTROL);
|
||||
udelay(100);
|
||||
|
||||
val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
|
||||
writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
|
||||
|
||||
writel(phy_control, NETX_SYSTEM_PHY_CONTROL);
|
||||
|
||||
return platform_driver_register(&netx_eth_driver);
|
||||
}
|
||||
|
||||
static void __exit netx_eth_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&netx_eth_driver);
|
||||
}
|
||||
|
||||
module_init(netx_eth_init);
|
||||
module_exit(netx_eth_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1359,7 +1359,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
kio_addr_t ioaddr = dev->base_addr;
|
||||
int okay;
|
||||
unsigned freespace;
|
||||
unsigned pktlen = skb? skb->len : 0;
|
||||
unsigned pktlen = skb->len;
|
||||
|
||||
DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",
|
||||
skb, dev, pktlen);
|
||||
|
|
|
@ -2626,6 +2626,50 @@ static int s2io_poll(struct net_device *dev, int *budget)
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* s2io_netpoll - Rx interrupt service handler for netpoll support
|
||||
* @dev : pointer to the device structure.
|
||||
* Description:
|
||||
* Polling 'interrupt' - used by things like netconsole to send skbs
|
||||
* without having to re-enable interrupts. It's not called while
|
||||
* the interrupt routine is executing.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void s2io_netpoll(struct net_device *dev)
|
||||
{
|
||||
nic_t *nic = dev->priv;
|
||||
mac_info_t *mac_control;
|
||||
struct config_param *config;
|
||||
XENA_dev_config_t __iomem *bar0 = nic->bar0;
|
||||
u64 val64;
|
||||
int i;
|
||||
|
||||
disable_irq(dev->irq);
|
||||
|
||||
atomic_inc(&nic->isr_cnt);
|
||||
mac_control = &nic->mac_control;
|
||||
config = &nic->config;
|
||||
|
||||
val64 = readq(&bar0->rx_traffic_int);
|
||||
writeq(val64, &bar0->rx_traffic_int);
|
||||
|
||||
for (i = 0; i < config->rx_ring_num; i++)
|
||||
rx_intr_handler(&mac_control->rings[i]);
|
||||
|
||||
for (i = 0; i < config->rx_ring_num; i++) {
|
||||
if (fill_rx_buffers(nic, i) == -ENOMEM) {
|
||||
DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name);
|
||||
DBG_PRINT(ERR_DBG, " in Rx Netpoll!!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
atomic_dec(&nic->isr_cnt);
|
||||
enable_irq(dev->irq);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* rx_intr_handler - Rx interrupt handler
|
||||
* @nic: device private variable.
|
||||
|
@ -6967,6 +7011,10 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
|
|||
dev->weight = 32;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
dev->poll_controller = s2io_netpoll;
|
||||
#endif
|
||||
|
||||
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
|
||||
if (sp->high_dma_flag == TRUE)
|
||||
dev->features |= NETIF_F_HIGHDMA;
|
||||
|
|
|
@ -94,11 +94,13 @@
|
|||
Version LK1.10 (Philippe De Muyter phdm@macqel.be):
|
||||
- Make 'unblock interface after Tx underrun' work
|
||||
|
||||
Version LK1.11 (Pedro Alejandro Lopez-Valencia palopezv at gmail.com):
|
||||
- Add support for IC Plus Corporation IP100A chipset
|
||||
*/
|
||||
|
||||
#define DRV_NAME "sundance"
|
||||
#define DRV_VERSION "1.01+LK1.10"
|
||||
#define DRV_RELDATE "28-Oct-2005"
|
||||
#define DRV_VERSION "1.01+LK1.11"
|
||||
#define DRV_RELDATE "14-Jun-2006"
|
||||
|
||||
|
||||
/* The user-configurable values.
|
||||
|
@ -287,6 +289,7 @@ static struct pci_device_id sundance_pci_tbl[] = {
|
|||
{0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3},
|
||||
{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
|
||||
{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
|
||||
{0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
|
||||
{0,}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
|
||||
|
@ -305,6 +308,7 @@ static const struct pci_id_info pci_id_tbl[] = {
|
|||
{"D-Link DFE-530TXS FAST Ethernet Adapter"},
|
||||
{"D-Link DL10050-based FAST Ethernet Adapter"},
|
||||
{"Sundance Technology Alta"},
|
||||
{"IC Plus Corporation IP100A FAST Ethernet Adapter"},
|
||||
{NULL,}, /* 0 terminated list. */
|
||||
};
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device
|
|||
dev = alloc_trdev(sizeof(struct olympic_private)) ;
|
||||
if (!dev) {
|
||||
i = -ENOMEM;
|
||||
goto op_free_dev;
|
||||
goto op_release_dev;
|
||||
}
|
||||
|
||||
olympic_priv = dev->priv ;
|
||||
|
@ -282,8 +282,8 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device
|
|||
if (olympic_priv->olympic_lap)
|
||||
iounmap(olympic_priv->olympic_lap);
|
||||
|
||||
op_free_dev:
|
||||
free_netdev(dev);
|
||||
op_release_dev:
|
||||
pci_release_regions(pdev);
|
||||
|
||||
op_disable_dev:
|
||||
|
|
|
@ -248,6 +248,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr);
|
|||
static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *);
|
||||
static int velocity_soft_reset(struct velocity_info *vptr);
|
||||
static void mii_init(struct velocity_info *vptr, u32 mii_status);
|
||||
static u32 velocity_get_link(struct net_device *dev);
|
||||
static u32 velocity_get_opt_media_mode(struct velocity_info *vptr);
|
||||
static void velocity_print_link_status(struct velocity_info *vptr);
|
||||
static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs);
|
||||
|
@ -798,6 +799,9 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
|
|||
if (ret < 0)
|
||||
goto err_iounmap;
|
||||
|
||||
if (velocity_get_link(dev))
|
||||
netif_carrier_off(dev);
|
||||
|
||||
velocity_print_info(vptr);
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
|
@ -1653,8 +1657,10 @@ static void velocity_error(struct velocity_info *vptr, int status)
|
|||
|
||||
if (linked) {
|
||||
vptr->mii_status &= ~VELOCITY_LINK_FAIL;
|
||||
netif_carrier_on(vptr->dev);
|
||||
} else {
|
||||
vptr->mii_status |= VELOCITY_LINK_FAIL;
|
||||
netif_carrier_off(vptr->dev);
|
||||
}
|
||||
|
||||
velocity_print_link_status(vptr);
|
||||
|
|
|
@ -326,21 +326,21 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
|
|||
if (request_irq(irq, sca_intr, 0, devname, card)) {
|
||||
printk(KERN_ERR "c101: could not allocate IRQ\n");
|
||||
c101_destroy_card(card);
|
||||
return(-EBUSY);
|
||||
return -EBUSY;
|
||||
}
|
||||
card->irq = irq;
|
||||
|
||||
if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
|
||||
printk(KERN_ERR "c101: could not request RAM window\n");
|
||||
c101_destroy_card(card);
|
||||
return(-EBUSY);
|
||||
return -EBUSY;
|
||||
}
|
||||
card->phy_winbase = winbase;
|
||||
card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
|
||||
if (!card->win0base) {
|
||||
printk(KERN_ERR "c101: could not map I/O address\n");
|
||||
c101_destroy_card(card);
|
||||
return -EBUSY;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
card->tx_ring_buffers = TX_RING_BUFFERS;
|
||||
|
|
|
@ -259,7 +259,7 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|||
}
|
||||
}
|
||||
|
||||
static void hdlc_setup(struct net_device *dev)
|
||||
void hdlc_setup(struct net_device *dev)
|
||||
{
|
||||
hdlc_device *hdlc = dev_to_hdlc(dev);
|
||||
|
||||
|
@ -288,26 +288,6 @@ struct net_device *alloc_hdlcdev(void *priv)
|
|||
return dev;
|
||||
}
|
||||
|
||||
int register_hdlc_device(struct net_device *dev)
|
||||
{
|
||||
int result = dev_alloc_name(dev, "hdlc%d");
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
result = register_netdev(dev);
|
||||
if (result != 0)
|
||||
return -EIO;
|
||||
|
||||
#if 0
|
||||
if (netif_carrier_ok(dev))
|
||||
netif_carrier_off(dev); /* no carrier until DCD goes up */
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void unregister_hdlc_device(struct net_device *dev)
|
||||
{
|
||||
rtnl_lock();
|
||||
|
@ -326,8 +306,8 @@ EXPORT_SYMBOL(hdlc_open);
|
|||
EXPORT_SYMBOL(hdlc_close);
|
||||
EXPORT_SYMBOL(hdlc_set_carrier);
|
||||
EXPORT_SYMBOL(hdlc_ioctl);
|
||||
EXPORT_SYMBOL(hdlc_setup);
|
||||
EXPORT_SYMBOL(alloc_hdlcdev);
|
||||
EXPORT_SYMBOL(register_hdlc_device);
|
||||
EXPORT_SYMBOL(unregister_hdlc_device);
|
||||
|
||||
static struct packet_type hdlc_packet_type = {
|
||||
|
|
|
@ -387,6 +387,11 @@ static int __init n2_run(unsigned long io, unsigned long irq,
|
|||
}
|
||||
card->phy_winbase = winbase;
|
||||
card->winbase = ioremap(winbase, USE_WINDOWSIZE);
|
||||
if (!card->winbase) {
|
||||
printk(KERN_ERR "n2: ioremap() failed\n");
|
||||
n2_destroy_card(card);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
outb(0, io + N2_PCR);
|
||||
outb(winbase >> 12, io + N2_BAR);
|
||||
|
|
|
@ -354,6 +354,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
|
|||
card->rambase == NULL) {
|
||||
printk(KERN_ERR "pci200syn: ioremap() failed\n");
|
||||
pci200_pci_remove_one(pdev);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Reset PLX */
|
||||
|
|
|
@ -634,7 +634,13 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
|
|||
|
||||
/* set up PLX mapping */
|
||||
plx_phy = pci_resource_start(pdev, 0);
|
||||
|
||||
card->plx = ioremap_nocache(plx_phy, 0x70);
|
||||
if (!card->plx) {
|
||||
printk(KERN_ERR "wanxl: ioremap() failed\n");
|
||||
wanxl_pci_remove_one(pdev);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
#if RESET_WHILE_LOADING
|
||||
wanxl_reset(card);
|
||||
|
@ -700,6 +706,12 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware));
|
||||
if (!mem) {
|
||||
printk(KERN_ERR "wanxl: ioremap() failed\n");
|
||||
wanxl_pci_remove_one(pdev);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(firmware); i += 4)
|
||||
writel(htonl(*(u32*)(firmware + i)), mem + PDM_OFFSET + i);
|
||||
|
||||
|
|
|
@ -636,6 +636,17 @@ struct bcm43xx_key {
|
|||
u8 algorithm;
|
||||
};
|
||||
|
||||
/* Driver initialization status. */
|
||||
enum {
|
||||
BCM43xx_STAT_UNINIT, /* Uninitialized. */
|
||||
BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */
|
||||
BCM43xx_STAT_INITIALIZED, /* Fully operational. */
|
||||
BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */
|
||||
BCM43xx_STAT_RESTARTING, /* controller_restart() called. */
|
||||
};
|
||||
#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
|
||||
#define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat))
|
||||
|
||||
struct bcm43xx_private {
|
||||
struct ieee80211_device *ieee;
|
||||
struct ieee80211softmac_device *softmac;
|
||||
|
@ -646,18 +657,17 @@ struct bcm43xx_private {
|
|||
|
||||
void __iomem *mmio_addr;
|
||||
|
||||
/* Do not use the lock directly. Use the bcm43xx_lock* helper
|
||||
* functions, to be MMIO-safe. */
|
||||
spinlock_t _lock;
|
||||
/* Locking, see "theory of locking" text below. */
|
||||
spinlock_t irq_lock;
|
||||
struct mutex mutex;
|
||||
|
||||
/* Driver status flags. */
|
||||
u32 initialized:1, /* init_board() succeed */
|
||||
was_initialized:1, /* for PCI suspend/resume. */
|
||||
shutting_down:1, /* free_board() in progress */
|
||||
/* Driver initialization status BCM43xx_STAT_*** */
|
||||
atomic_t init_status;
|
||||
|
||||
u16 was_initialized:1, /* for PCI suspend/resume. */
|
||||
__using_pio:1, /* Internal, use bcm43xx_using_pio(). */
|
||||
bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
|
||||
reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
|
||||
powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */
|
||||
short_preamble:1, /* TRUE, if short preamble is enabled. */
|
||||
firmware_norelease:1; /* Do not release the firmware. Used on suspend. */
|
||||
|
||||
|
@ -721,7 +731,7 @@ struct bcm43xx_private {
|
|||
struct tasklet_struct isr_tasklet;
|
||||
|
||||
/* Periodic tasks */
|
||||
struct timer_list periodic_tasks;
|
||||
struct work_struct periodic_work;
|
||||
unsigned int periodic_state;
|
||||
|
||||
struct work_struct restart_work;
|
||||
|
@ -746,21 +756,55 @@ struct bcm43xx_private {
|
|||
#endif
|
||||
};
|
||||
|
||||
/* bcm43xx_(un)lock() protect struct bcm43xx_private.
|
||||
* Note that _NO_ MMIO writes are allowed. If you want to
|
||||
* write to the device through MMIO in the critical section, use
|
||||
* the *_mmio lock functions.
|
||||
* MMIO read-access is allowed, though.
|
||||
|
||||
/* *** THEORY OF LOCKING ***
|
||||
*
|
||||
* We have two different locks in the bcm43xx driver.
|
||||
* => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
|
||||
* and the device registers.
|
||||
* => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
|
||||
*
|
||||
* We have three types of helper function pairs to utilize these locks.
|
||||
* (Always use the helper functions.)
|
||||
* 1) bcm43xx_{un}lock_noirq():
|
||||
* Takes bcm->mutex. Does _not_ protect against IRQ concurrency,
|
||||
* so it is almost always unsafe, if device IRQs are enabled.
|
||||
* So only use this, if device IRQs are masked.
|
||||
* Locking may sleep.
|
||||
* You can sleep within the critical section.
|
||||
* 2) bcm43xx_{un}lock_irqonly():
|
||||
* Takes bcm->irq_lock. Does _not_ protect against
|
||||
* bcm43xx_lock_noirq() critical sections.
|
||||
* Does only protect against the IRQ handler path and other
|
||||
* irqonly() critical sections.
|
||||
* Locking does not sleep.
|
||||
* You must not sleep within the critical section.
|
||||
* 3) bcm43xx_{un}lock_irqsafe():
|
||||
* This is the cummulative lock and takes both, mutex and irq_lock.
|
||||
* Protects against noirq() and irqonly() critical sections (and
|
||||
* the IRQ handler path).
|
||||
* Locking may sleep.
|
||||
* You must not sleep within the critical section.
|
||||
*/
|
||||
#define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags)
|
||||
#define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags)
|
||||
/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO.
|
||||
* MMIO write-access to the device is allowed.
|
||||
* All MMIO writes are flushed on unlock, so it is guaranteed to not
|
||||
* interfere with other threads writing MMIO registers.
|
||||
*/
|
||||
#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags)
|
||||
#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0)
|
||||
|
||||
/* Lock type 1 */
|
||||
#define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex)
|
||||
#define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex)
|
||||
/* Lock type 2 */
|
||||
#define bcm43xx_lock_irqonly(bcm, flags) \
|
||||
spin_lock_irqsave(&(bcm)->irq_lock, flags)
|
||||
#define bcm43xx_unlock_irqonly(bcm, flags) \
|
||||
spin_unlock_irqrestore(&(bcm)->irq_lock, flags)
|
||||
/* Lock type 3 */
|
||||
#define bcm43xx_lock_irqsafe(bcm, flags) do { \
|
||||
bcm43xx_lock_noirq(bcm); \
|
||||
bcm43xx_lock_irqonly(bcm, flags); \
|
||||
} while (0)
|
||||
#define bcm43xx_unlock_irqsafe(bcm, flags) do { \
|
||||
bcm43xx_unlock_irqonly(bcm, flags); \
|
||||
bcm43xx_unlock_noirq(bcm); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static inline
|
||||
struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
|
||||
|
@ -843,16 +887,6 @@ struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
|
|||
return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
|
||||
}
|
||||
|
||||
/* Are we running in init_board() context? */
|
||||
static inline
|
||||
int bcm43xx_is_initializing(struct bcm43xx_private *bcm)
|
||||
{
|
||||
if (bcm->initialized)
|
||||
return 0;
|
||||
if (bcm->shutting_down)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
|
||||
|
|
|
@ -77,8 +77,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
|
|||
|
||||
down(&big_buffer_sem);
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (!bcm->initialized) {
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
|
||||
fappend("Board not initialized.\n");
|
||||
goto out;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
|
|||
fappend("\n");
|
||||
|
||||
out:
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
up(&big_buffer_sem);
|
||||
return res;
|
||||
|
@ -159,8 +159,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
|
|||
unsigned long flags;
|
||||
|
||||
down(&big_buffer_sem);
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (!bcm->initialized) {
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
|
||||
fappend("Board not initialized.\n");
|
||||
goto out;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
|
|||
fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
|
||||
|
||||
out:
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
up(&big_buffer_sem);
|
||||
return res;
|
||||
|
@ -188,8 +188,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
|
|||
u64 tsf;
|
||||
|
||||
down(&big_buffer_sem);
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (!bcm->initialized) {
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
|
||||
fappend("Board not initialized.\n");
|
||||
goto out;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
|
|||
(unsigned int)(tsf & 0xFFFFFFFFULL));
|
||||
|
||||
out:
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
up(&big_buffer_sem);
|
||||
return res;
|
||||
|
@ -221,8 +221,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
|
|||
res = -EFAULT;
|
||||
goto out_up;
|
||||
}
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (!bcm->initialized) {
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
|
||||
printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
|
||||
res = -EFAULT;
|
||||
goto out_unlock;
|
||||
|
@ -233,10 +233,11 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
|
|||
goto out_unlock;
|
||||
}
|
||||
bcm43xx_tsf_write(bcm, tsf);
|
||||
mmiowb();
|
||||
res = buf_size;
|
||||
|
||||
out_unlock:
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
out_up:
|
||||
up(&big_buffer_sem);
|
||||
return res;
|
||||
|
@ -257,7 +258,7 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
|
|||
int i, cnt, j = 0;
|
||||
|
||||
down(&big_buffer_sem);
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
|
||||
fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
|
||||
BCM43xx_NR_LOGGED_XMITSTATUS);
|
||||
|
@ -293,14 +294,14 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
|
|||
i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
|
||||
}
|
||||
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (*ppos == pos) {
|
||||
/* Done. Drop the copied data. */
|
||||
e->xmitstatus_printing = 0;
|
||||
}
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
up(&big_buffer_sem);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d)
|
|||
struct bcm43xx_private *bcm = led->bcm;
|
||||
unsigned long flags;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqonly(bcm, flags);
|
||||
if (led->blink_interval) {
|
||||
bcm43xx_led_changestate(led);
|
||||
mod_timer(&led->blink_timer, jiffies + led->blink_interval);
|
||||
}
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
}
|
||||
|
||||
static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
|
||||
|
|
|
@ -498,20 +498,31 @@ static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mas
|
|||
return old_mask;
|
||||
}
|
||||
|
||||
/* Synchronize IRQ top- and bottom-half.
|
||||
* IRQs must be masked before calling this.
|
||||
* This must not be called with the irq_lock held.
|
||||
*/
|
||||
static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
|
||||
{
|
||||
synchronize_irq(bcm->irq);
|
||||
tasklet_disable(&bcm->isr_tasklet);
|
||||
}
|
||||
|
||||
/* Make sure we don't receive more data from the device. */
|
||||
static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
|
||||
{
|
||||
u32 old;
|
||||
unsigned long flags;
|
||||
u32 old;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) {
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqonly(bcm, flags);
|
||||
if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
|
||||
tasklet_disable(&bcm->isr_tasklet);
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
bcm43xx_synchronize_irq(bcm);
|
||||
|
||||
if (oldstate)
|
||||
*oldstate = old;
|
||||
|
||||
|
@ -1389,7 +1400,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
|
|||
bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
|
||||
#endif
|
||||
}
|
||||
if (bcm->shutting_down) {
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
|
||||
bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
|
||||
bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
|
||||
& ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
|
||||
|
@ -1709,7 +1720,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
|
|||
# define bcmirq_handled(irq) do { /* nothing */ } while (0)
|
||||
#endif /* CONFIG_BCM43XX_DEBUG*/
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqonly(bcm, flags);
|
||||
reason = bcm->irq_reason;
|
||||
dma_reason[0] = bcm->dma_reason[0];
|
||||
dma_reason[1] = bcm->dma_reason[1];
|
||||
|
@ -1734,7 +1745,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
|
|||
dma_reason[0], dma_reason[1],
|
||||
dma_reason[2], dma_reason[3]);
|
||||
bcm43xx_controller_restart(bcm, "DMA error");
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
mmiowb();
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
return;
|
||||
}
|
||||
if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
|
||||
|
@ -1821,7 +1833,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
|
|||
if (!modparam_noleds)
|
||||
bcm43xx_leds_update(bcm, activity);
|
||||
bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
mmiowb();
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
}
|
||||
|
||||
static void pio_irq_workaround(struct bcm43xx_private *bcm,
|
||||
|
@ -1870,7 +1883,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
|
|||
if (!bcm)
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock(&bcm->_lock);
|
||||
spin_lock(&bcm->irq_lock);
|
||||
|
||||
reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
|
||||
if (reason == 0xffffffff) {
|
||||
|
@ -1899,7 +1912,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
|
|||
* completely, but some careful work is needed to fix this. I think it
|
||||
* is best to stay with this cheap workaround for now... .
|
||||
*/
|
||||
if (likely(bcm->initialized)) {
|
||||
if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
|
||||
/* disable all IRQs. They are enabled again in the bottom half. */
|
||||
bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
|
||||
/* save the reason code and call our bottom half. */
|
||||
|
@ -1909,7 +1922,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
|
|||
|
||||
out:
|
||||
mmiowb();
|
||||
spin_unlock(&bcm->_lock);
|
||||
spin_unlock(&bcm->irq_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2133,6 +2146,13 @@ static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
|
|||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCM947XX
|
||||
static struct pci_device_id bcm43xx_47xx_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
|
||||
{ 0 }
|
||||
};
|
||||
#endif
|
||||
|
||||
static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
|
||||
{
|
||||
int res;
|
||||
|
@ -2142,11 +2162,15 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
|
|||
bcm->irq = bcm->pci_dev->irq;
|
||||
#ifdef CONFIG_BCM947XX
|
||||
if (bcm->pci_dev->bus->number == 0) {
|
||||
struct pci_dev *d = NULL;
|
||||
/* FIXME: we will probably need more device IDs here... */
|
||||
d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
|
||||
if (d != NULL) {
|
||||
bcm->irq = d->irq;
|
||||
struct pci_dev *d;
|
||||
struct pci_device_id *id;
|
||||
for (id = bcm43xx_47xx_ids; id->vendor; id++) {
|
||||
d = pci_get_device(id->vendor, id->device, NULL);
|
||||
if (d != NULL) {
|
||||
bcm->irq = d->irq;
|
||||
pci_dev_put(d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -3106,15 +3130,10 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
|
|||
//TODO for APHY (temperature?)
|
||||
}
|
||||
|
||||
static void bcm43xx_periodic_task_handler(unsigned long d)
|
||||
static void do_periodic_work(struct bcm43xx_private *bcm)
|
||||
{
|
||||
struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
|
||||
unsigned long flags;
|
||||
unsigned int state;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
|
||||
assert(bcm->initialized);
|
||||
state = bcm->periodic_state;
|
||||
if (state % 8 == 0)
|
||||
bcm43xx_periodic_every120sec(bcm);
|
||||
|
@ -3122,29 +3141,93 @@ static void bcm43xx_periodic_task_handler(unsigned long d)
|
|||
bcm43xx_periodic_every60sec(bcm);
|
||||
if (state % 2 == 0)
|
||||
bcm43xx_periodic_every30sec(bcm);
|
||||
bcm43xx_periodic_every15sec(bcm);
|
||||
if (state % 1 == 0)
|
||||
bcm43xx_periodic_every15sec(bcm);
|
||||
bcm->periodic_state = state + 1;
|
||||
|
||||
mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
|
||||
schedule_delayed_work(&bcm->periodic_work, HZ * 15);
|
||||
}
|
||||
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
/* Estimate a "Badness" value based on the periodic work
|
||||
* state-machine state. "Badness" is worse (bigger), if the
|
||||
* periodic work will take longer.
|
||||
*/
|
||||
static int estimate_periodic_work_badness(unsigned int state)
|
||||
{
|
||||
int badness = 0;
|
||||
|
||||
if (state % 8 == 0) /* every 120 sec */
|
||||
badness += 10;
|
||||
if (state % 4 == 0) /* every 60 sec */
|
||||
badness += 5;
|
||||
if (state % 2 == 0) /* every 30 sec */
|
||||
badness += 1;
|
||||
if (state % 1 == 0) /* every 15 sec */
|
||||
badness += 1;
|
||||
|
||||
#define BADNESS_LIMIT 4
|
||||
return badness;
|
||||
}
|
||||
|
||||
static void bcm43xx_periodic_work_handler(void *d)
|
||||
{
|
||||
struct bcm43xx_private *bcm = d;
|
||||
unsigned long flags;
|
||||
u32 savedirqs = 0;
|
||||
int badness;
|
||||
|
||||
badness = estimate_periodic_work_badness(bcm->periodic_state);
|
||||
if (badness > BADNESS_LIMIT) {
|
||||
/* Periodic work will take a long time, so we want it to
|
||||
* be preemtible.
|
||||
*/
|
||||
bcm43xx_lock_irqonly(bcm, flags);
|
||||
netif_stop_queue(bcm->net_dev);
|
||||
if (bcm43xx_using_pio(bcm))
|
||||
bcm43xx_pio_freeze_txqueues(bcm);
|
||||
savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
bcm43xx_lock_noirq(bcm);
|
||||
bcm43xx_synchronize_irq(bcm);
|
||||
} else {
|
||||
/* Periodic work should take short time, so we want low
|
||||
* locking overhead.
|
||||
*/
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
}
|
||||
|
||||
do_periodic_work(bcm);
|
||||
|
||||
if (badness > BADNESS_LIMIT) {
|
||||
bcm43xx_lock_irqonly(bcm, flags);
|
||||
if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
|
||||
tasklet_enable(&bcm->isr_tasklet);
|
||||
bcm43xx_interrupt_enable(bcm, savedirqs);
|
||||
if (bcm43xx_using_pio(bcm))
|
||||
bcm43xx_pio_thaw_txqueues(bcm);
|
||||
}
|
||||
netif_wake_queue(bcm->net_dev);
|
||||
mmiowb();
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
bcm43xx_unlock_noirq(bcm);
|
||||
} else {
|
||||
mmiowb();
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
|
||||
{
|
||||
del_timer_sync(&bcm->periodic_tasks);
|
||||
cancel_rearming_delayed_work(&bcm->periodic_work);
|
||||
}
|
||||
|
||||
static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
|
||||
{
|
||||
struct timer_list *timer = &(bcm->periodic_tasks);
|
||||
struct work_struct *work = &(bcm->periodic_work);
|
||||
|
||||
assert(bcm->initialized);
|
||||
setup_timer(timer,
|
||||
bcm43xx_periodic_task_handler,
|
||||
(unsigned long)bcm);
|
||||
timer->expires = jiffies;
|
||||
add_timer(timer);
|
||||
assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
|
||||
INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
|
||||
schedule_work(work);
|
||||
}
|
||||
|
||||
static void bcm43xx_security_init(struct bcm43xx_private *bcm)
|
||||
|
@ -3158,16 +3241,12 @@ static void bcm43xx_security_init(struct bcm43xx_private *bcm)
|
|||
static void bcm43xx_free_board(struct bcm43xx_private *bcm)
|
||||
{
|
||||
int i, err;
|
||||
unsigned long flags;
|
||||
|
||||
bcm43xx_lock_noirq(bcm);
|
||||
bcm43xx_sysfs_unregister(bcm);
|
||||
|
||||
bcm43xx_periodic_tasks_delete(bcm);
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm->initialized = 0;
|
||||
bcm->shutting_down = 1;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
|
||||
|
||||
for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
|
||||
if (!bcm->core_80211[i].available)
|
||||
|
@ -3182,23 +3261,19 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm)
|
|||
|
||||
bcm43xx_pctl_set_crystal(bcm, 0);
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm->shutting_down = 0;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
|
||||
bcm43xx_unlock_noirq(bcm);
|
||||
}
|
||||
|
||||
static int bcm43xx_init_board(struct bcm43xx_private *bcm)
|
||||
{
|
||||
int i, err;
|
||||
int connect_phy;
|
||||
unsigned long flags;
|
||||
|
||||
might_sleep();
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm->initialized = 0;
|
||||
bcm->shutting_down = 0;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_lock_noirq(bcm);
|
||||
bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
|
||||
|
||||
err = bcm43xx_pctl_set_crystal(bcm, 1);
|
||||
if (err)
|
||||
|
@ -3265,9 +3340,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
|
|||
}
|
||||
|
||||
/* Initialization of the board is done. Flag it as such. */
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm->initialized = 1;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
|
||||
|
||||
bcm43xx_periodic_tasks_setup(bcm);
|
||||
bcm43xx_sysfs_register(bcm);
|
||||
|
@ -3278,6 +3351,8 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
|
|||
|
||||
assert(err == 0);
|
||||
out:
|
||||
bcm43xx_unlock_noirq(bcm);
|
||||
|
||||
return err;
|
||||
|
||||
err_80211_unwind:
|
||||
|
@ -3534,8 +3609,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
|
|||
struct bcm43xx_radioinfo *radio;
|
||||
unsigned long flags;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (bcm->initialized) {
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
|
||||
bcm43xx_mac_suspend(bcm);
|
||||
bcm43xx_radio_selectchannel(bcm, channel, 0);
|
||||
bcm43xx_mac_enable(bcm);
|
||||
|
@ -3543,7 +3618,7 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
|
|||
radio = bcm43xx_current_radio(bcm);
|
||||
radio->initial_channel = channel;
|
||||
}
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
}
|
||||
|
||||
/* set_security() callback in struct ieee80211_device */
|
||||
|
@ -3557,7 +3632,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
|
|||
|
||||
dprintk(KERN_INFO PFX "set security called");
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
|
||||
for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
|
||||
if (sec->flags & (1<<keyidx)) {
|
||||
|
@ -3587,7 +3662,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
|
|||
dprintk(", .encrypt = %d", sec->encrypt);
|
||||
}
|
||||
dprintk("\n");
|
||||
if (bcm->initialized && !bcm->ieee->host_encrypt) {
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
|
||||
!bcm->ieee->host_encrypt) {
|
||||
if (secinfo->enabled) {
|
||||
/* upload WEP keys to hardware */
|
||||
char null_address[6] = { 0 };
|
||||
|
@ -3621,7 +3697,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
|
|||
} else
|
||||
bcm43xx_clear_keys(bcm);
|
||||
}
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
}
|
||||
|
||||
/* hard_start_xmit() callback in struct ieee80211_device */
|
||||
|
@ -3633,10 +3709,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
|
|||
int err = -ENODEV;
|
||||
unsigned long flags;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (likely(bcm->initialized))
|
||||
bcm43xx_lock_irqonly(bcm, flags);
|
||||
if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
|
||||
err = bcm43xx_tx(bcm, txb);
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -3651,9 +3727,9 @@ static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
|
|||
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
|
||||
unsigned long flags;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqonly(bcm, flags);
|
||||
bcm43xx_controller_restart(bcm, "TX timeout");
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
|
@ -3678,9 +3754,11 @@ static int bcm43xx_net_open(struct net_device *net_dev)
|
|||
static int bcm43xx_net_stop(struct net_device *net_dev)
|
||||
{
|
||||
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
|
||||
int err;
|
||||
|
||||
ieee80211softmac_stop(net_dev);
|
||||
bcm43xx_disable_interrupts_sync(bcm, NULL);
|
||||
err = bcm43xx_disable_interrupts_sync(bcm, NULL);
|
||||
assert(!err);
|
||||
bcm43xx_free_board(bcm);
|
||||
|
||||
return 0;
|
||||
|
@ -3692,6 +3770,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
|
|||
{
|
||||
int err;
|
||||
|
||||
bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
|
||||
bcm->ieee = netdev_priv(net_dev);
|
||||
bcm->softmac = ieee80211_priv(net_dev);
|
||||
bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
|
||||
|
@ -3700,7 +3779,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
|
|||
bcm->pci_dev = pci_dev;
|
||||
bcm->net_dev = net_dev;
|
||||
bcm->bad_frames_preempt = modparam_bad_frames_preempt;
|
||||
spin_lock_init(&bcm->_lock);
|
||||
spin_lock_init(&bcm->irq_lock);
|
||||
mutex_init(&bcm->mutex);
|
||||
tasklet_init(&bcm->isr_tasklet,
|
||||
(void (*)(unsigned long))bcm43xx_interrupt_tasklet,
|
||||
(unsigned long)bcm);
|
||||
|
@ -3831,7 +3911,7 @@ static void bcm43xx_chip_reset(void *_bcm)
|
|||
struct net_device *net_dev = bcm->net_dev;
|
||||
struct pci_dev *pci_dev = bcm->pci_dev;
|
||||
int err;
|
||||
int was_initialized = bcm->initialized;
|
||||
int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
|
||||
|
||||
netif_stop_queue(bcm->net_dev);
|
||||
tasklet_disable(&bcm->isr_tasklet);
|
||||
|
@ -3866,6 +3946,7 @@ static void bcm43xx_chip_reset(void *_bcm)
|
|||
*/
|
||||
void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
|
||||
{
|
||||
bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
|
||||
bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
|
||||
bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
|
||||
printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
|
||||
|
@ -3884,11 +3965,11 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
|
||||
dprintk(KERN_INFO PFX "Suspending...\n");
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm->was_initialized = bcm->initialized;
|
||||
if (bcm->initialized)
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
|
||||
if (bcm->was_initialized)
|
||||
try_to_shutdown = 1;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
netif_device_detach(net_dev);
|
||||
if (try_to_shutdown) {
|
||||
|
|
|
@ -1410,7 +1410,10 @@ static inline
|
|||
u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
|
||||
{
|
||||
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
|
||||
u16 ret;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (phy->connected) {
|
||||
bcm43xx_phy_write(bcm, 0x15, 0xE300);
|
||||
control <<= 8;
|
||||
|
@ -1430,8 +1433,10 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
|
|||
bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
|
||||
udelay(8);
|
||||
}
|
||||
ret = bcm43xx_phy_read(bcm, 0x002D);
|
||||
local_irq_restore(flags);
|
||||
|
||||
return bcm43xx_phy_read(bcm, 0x002D);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
|
||||
|
@ -1648,7 +1653,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
|
|||
void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
|
||||
{
|
||||
static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
|
||||
const int is_initializing = bcm43xx_is_initializing(bcm);
|
||||
const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
|
||||
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
|
||||
struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
|
||||
u16 h, i, oldi = 0, j;
|
||||
|
|
|
@ -262,8 +262,10 @@ static void tx_tasklet(unsigned long d)
|
|||
int err;
|
||||
u16 txctl;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqonly(bcm, flags);
|
||||
|
||||
if (queue->tx_frozen)
|
||||
goto out_unlock;
|
||||
txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
|
||||
if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
|
||||
goto out_unlock;
|
||||
|
@ -298,7 +300,7 @@ static void tx_tasklet(unsigned long d)
|
|||
continue;
|
||||
}
|
||||
out_unlock:
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqonly(bcm, flags);
|
||||
}
|
||||
|
||||
static void setup_txqueues(struct bcm43xx_pioqueue *queue)
|
||||
|
@ -374,7 +376,6 @@ static void cancel_transfers(struct bcm43xx_pioqueue *queue)
|
|||
struct bcm43xx_pio_txpacket *packet, *tmp_packet;
|
||||
|
||||
netif_tx_disable(queue->bcm->net_dev);
|
||||
assert(queue->bcm->shutting_down);
|
||||
tasklet_disable(&queue->txtask);
|
||||
|
||||
list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
|
||||
|
@ -634,5 +635,40 @@ void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
|
|||
bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
|
||||
& ~BCM43xx_PIO_TXCTL_SUSPEND);
|
||||
bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
|
||||
tasklet_schedule(&queue->txtask);
|
||||
if (!list_empty(&queue->txqueue))
|
||||
tasklet_schedule(&queue->txtask);
|
||||
}
|
||||
|
||||
void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
|
||||
{
|
||||
struct bcm43xx_pio *pio;
|
||||
|
||||
assert(bcm43xx_using_pio(bcm));
|
||||
pio = bcm43xx_current_pio(bcm);
|
||||
pio->queue0->tx_frozen = 1;
|
||||
pio->queue1->tx_frozen = 1;
|
||||
pio->queue2->tx_frozen = 1;
|
||||
pio->queue3->tx_frozen = 1;
|
||||
}
|
||||
|
||||
void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
|
||||
{
|
||||
struct bcm43xx_pio *pio;
|
||||
|
||||
assert(bcm43xx_using_pio(bcm));
|
||||
pio = bcm43xx_current_pio(bcm);
|
||||
pio->queue0->tx_frozen = 0;
|
||||
pio->queue1->tx_frozen = 0;
|
||||
pio->queue2->tx_frozen = 0;
|
||||
pio->queue3->tx_frozen = 0;
|
||||
if (!list_empty(&pio->queue0->txqueue))
|
||||
tasklet_schedule(&pio->queue0->txtask);
|
||||
if (!list_empty(&pio->queue1->txqueue))
|
||||
tasklet_schedule(&pio->queue1->txtask);
|
||||
if (!list_empty(&pio->queue2->txqueue))
|
||||
tasklet_schedule(&pio->queue2->txtask);
|
||||
if (!list_empty(&pio->queue3->txqueue))
|
||||
tasklet_schedule(&pio->queue3->txtask);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ struct bcm43xx_pioqueue {
|
|||
u16 mmio_base;
|
||||
|
||||
u8 tx_suspended:1,
|
||||
tx_frozen:1,
|
||||
need_workarounds:1; /* Workarounds needed for core.rev < 3 */
|
||||
|
||||
/* Adjusted size of the device internal TX buffer. */
|
||||
|
@ -108,8 +109,12 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
|
|||
struct bcm43xx_xmitstatus *status);
|
||||
void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
|
||||
|
||||
/* Suspend a TX queue on hardware level. */
|
||||
void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
|
||||
void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
|
||||
/* Suspend (freeze) the TX tasklet (software level). */
|
||||
void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
|
||||
void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
|
||||
|
||||
#else /* CONFIG_BCM43XX_PIO */
|
||||
|
||||
|
@ -145,6 +150,14 @@ static inline
|
|||
void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BCM43XX_PIO */
|
||||
#endif /* BCM43xx_PIO_H_ */
|
||||
|
|
|
@ -120,12 +120,12 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
|
|||
GFP_KERNEL);
|
||||
if (!sprom)
|
||||
return -ENOMEM;
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
assert(bcm->initialized);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
err = bcm43xx_sprom_read(bcm, sprom);
|
||||
if (!err)
|
||||
err = sprom2hex(sprom, buf, PAGE_SIZE);
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
mmiowb();
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
kfree(sprom);
|
||||
|
||||
return err;
|
||||
|
@ -150,10 +150,10 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
|
|||
err = hex2sprom(sprom, buf, count);
|
||||
if (err)
|
||||
goto out_kfree;
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
assert(bcm->initialized);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
err = bcm43xx_sprom_write(bcm, sprom);
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
mmiowb();
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
out_kfree:
|
||||
kfree(sprom);
|
||||
|
||||
|
@ -170,15 +170,13 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
struct bcm43xx_private *bcm = dev_to_bcm(dev);
|
||||
unsigned long flags;
|
||||
int err;
|
||||
ssize_t count = 0;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
assert(bcm->initialized);
|
||||
bcm43xx_lock_noirq(bcm);
|
||||
|
||||
switch (bcm43xx_current_radio(bcm)->interfmode) {
|
||||
case BCM43xx_RADIO_INTERFMODE_NONE:
|
||||
|
@ -195,7 +193,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
|
|||
}
|
||||
err = 0;
|
||||
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_noirq(bcm);
|
||||
|
||||
return err ? err : count;
|
||||
|
||||
|
@ -231,16 +229,15 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
assert(bcm->initialized);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
|
||||
err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Interference Mitigation not "
|
||||
"supported by device\n");
|
||||
}
|
||||
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
mmiowb();
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err ? err : count;
|
||||
}
|
||||
|
@ -254,15 +251,13 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
struct bcm43xx_private *bcm = dev_to_bcm(dev);
|
||||
unsigned long flags;
|
||||
int err;
|
||||
ssize_t count;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
assert(bcm->initialized);
|
||||
bcm43xx_lock_noirq(bcm);
|
||||
|
||||
if (bcm->short_preamble)
|
||||
count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
|
||||
|
@ -270,7 +265,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
|
|||
count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
|
||||
|
||||
err = 0;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_noirq(bcm);
|
||||
|
||||
return err ? err : count;
|
||||
}
|
||||
|
@ -290,13 +285,12 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
|
|||
value = get_boolean(buf, count);
|
||||
if (value < 0)
|
||||
return value;
|
||||
bcm43xx_lock(bcm, flags);
|
||||
assert(bcm->initialized);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
|
||||
bcm->short_preamble = !!value;
|
||||
|
||||
err = 0;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err ? err : count;
|
||||
}
|
||||
|
@ -310,7 +304,7 @@ int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
|
|||
struct device *dev = &bcm->pci_dev->dev;
|
||||
int err;
|
||||
|
||||
assert(bcm->initialized);
|
||||
assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
|
||||
|
||||
err = device_create_file(dev, &dev_attr_sprom);
|
||||
if (err)
|
||||
|
|
|
@ -55,13 +55,13 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev,
|
|||
char *extra)
|
||||
{
|
||||
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
|
||||
unsigned long flags;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct bcm43xx_phyinfo *phy;
|
||||
char suffix[7] = { 0 };
|
||||
int have_a = 0, have_b = 0, have_g = 0;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
for (i = 0; i < bcm->nr_80211_available; i++) {
|
||||
phy = &(bcm->core_80211_ext[i].phy);
|
||||
switch (phy->type) {
|
||||
|
@ -77,7 +77,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev,
|
|||
assert(0);
|
||||
}
|
||||
}
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
i = 0;
|
||||
if (have_a) {
|
||||
|
@ -111,7 +111,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
|
|||
int freq;
|
||||
int err = -EINVAL;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
|
||||
channel = data->freq.m;
|
||||
freq = bcm43xx_channel_to_freq(bcm, channel);
|
||||
|
@ -121,7 +121,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
|
|||
}
|
||||
if (!bcm43xx_is_valid_channel(bcm, channel))
|
||||
goto out_unlock;
|
||||
if (bcm->initialized) {
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
|
||||
//ieee80211softmac_disassoc(softmac, $REASON);
|
||||
bcm43xx_mac_suspend(bcm);
|
||||
err = bcm43xx_radio_selectchannel(bcm, channel, 0);
|
||||
|
@ -131,7 +131,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
|
|||
err = 0;
|
||||
}
|
||||
out_unlock:
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -147,11 +147,10 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
|
|||
int err = -ENODEV;
|
||||
u16 channel;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
radio = bcm43xx_current_radio(bcm);
|
||||
channel = radio->channel;
|
||||
if (channel == 0xFF) {
|
||||
assert(!bcm->initialized);
|
||||
channel = radio->initial_channel;
|
||||
if (channel == 0xFF)
|
||||
goto out_unlock;
|
||||
|
@ -163,7 +162,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
|
|||
|
||||
err = 0;
|
||||
out_unlock:
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -181,13 +180,13 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev,
|
|||
if (mode == IW_MODE_AUTO)
|
||||
mode = BCM43xx_INITIAL_IWMODE;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (bcm->initialized) {
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
|
||||
if (bcm->ieee->iw_mode != mode)
|
||||
bcm43xx_set_iwmode(bcm, mode);
|
||||
} else
|
||||
bcm->ieee->iw_mode = mode;
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -200,9 +199,9 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev,
|
|||
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
|
||||
unsigned long flags;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
data->mode = bcm->ieee->iw_mode;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -255,7 +254,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
|
|||
IW_ENC_CAPA_CIPHER_TKIP |
|
||||
IW_ENC_CAPA_CIPHER_CCMP;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
phy = bcm43xx_current_phy(bcm);
|
||||
|
||||
range->num_bitrates = 0;
|
||||
|
@ -302,7 +301,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
|
|||
}
|
||||
range->num_frequency = j;
|
||||
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -313,14 +312,13 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev,
|
|||
char *extra)
|
||||
{
|
||||
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
|
||||
unsigned long flags;
|
||||
size_t len;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_noirq(bcm);
|
||||
len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
|
||||
memcpy(bcm->nick, extra, len);
|
||||
bcm->nick[len] = '\0';
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_noirq(bcm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -331,15 +329,14 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev,
|
|||
char *extra)
|
||||
{
|
||||
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
|
||||
unsigned long flags;
|
||||
size_t len;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_noirq(bcm);
|
||||
len = strlen(bcm->nick) + 1;
|
||||
memcpy(extra, bcm->nick, len);
|
||||
data->data.length = (__u16)len;
|
||||
data->data.flags = 1;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_noirq(bcm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -353,7 +350,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev,
|
|||
unsigned long flags;
|
||||
int err = -EINVAL;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (data->rts.disabled) {
|
||||
bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
|
||||
err = 0;
|
||||
|
@ -364,7 +361,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev,
|
|||
err = 0;
|
||||
}
|
||||
}
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -377,11 +374,11 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev,
|
|||
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
|
||||
unsigned long flags;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
data->rts.value = bcm->rts_threshold;
|
||||
data->rts.fixed = 0;
|
||||
data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -395,7 +392,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev,
|
|||
unsigned long flags;
|
||||
int err = -EINVAL;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (data->frag.disabled) {
|
||||
bcm->ieee->fts = MAX_FRAG_THRESHOLD;
|
||||
err = 0;
|
||||
|
@ -406,7 +403,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev,
|
|||
err = 0;
|
||||
}
|
||||
}
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -419,11 +416,11 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev,
|
|||
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
|
||||
unsigned long flags;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
data->frag.value = bcm->ieee->fts;
|
||||
data->frag.fixed = 0;
|
||||
data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -445,8 +442,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (!bcm->initialized)
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
|
||||
goto out_unlock;
|
||||
radio = bcm43xx_current_radio(bcm);
|
||||
phy = bcm43xx_current_phy(bcm);
|
||||
|
@ -469,7 +466,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
|
|||
err = 0;
|
||||
|
||||
out_unlock:
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -484,8 +481,8 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
|
|||
unsigned long flags;
|
||||
int err = -ENODEV;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
if (!bcm->initialized)
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
|
||||
goto out_unlock;
|
||||
radio = bcm43xx_current_radio(bcm);
|
||||
/* desired dBm value is in Q5.2 */
|
||||
|
@ -496,7 +493,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
|
|||
|
||||
err = 0;
|
||||
out_unlock:
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -583,8 +580,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (bcm->initialized) {
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
|
||||
err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Interference Mitigation not "
|
||||
|
@ -598,7 +595,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
|
|||
} else
|
||||
bcm43xx_current_radio(bcm)->interfmode = mode;
|
||||
}
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -612,9 +609,9 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
|
|||
unsigned long flags;
|
||||
int mode;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
mode = bcm43xx_current_radio(bcm)->interfmode;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
switch (mode) {
|
||||
case BCM43xx_RADIO_INTERFMODE_NONE:
|
||||
|
@ -644,9 +641,9 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
|
|||
int on;
|
||||
|
||||
on = *((int *)extra);
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
bcm->short_preamble = !!on;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -660,9 +657,9 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
|
|||
unsigned long flags;
|
||||
int on;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
on = bcm->short_preamble;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
if (on)
|
||||
strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
|
||||
|
@ -684,11 +681,11 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
|
|||
|
||||
on = *((int *)extra);
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
bcm->ieee->host_encrypt = !!on;
|
||||
bcm->ieee->host_decrypt = !!on;
|
||||
bcm->ieee->host_build_iv = !on;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -702,9 +699,9 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
|
|||
unsigned long flags;
|
||||
int on;
|
||||
|
||||
bcm43xx_lock(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
on = bcm->ieee->host_encrypt;
|
||||
bcm43xx_unlock(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
|
||||
if (on)
|
||||
strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
|
||||
|
@ -767,11 +764,11 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
|
|||
if (!sprom)
|
||||
goto out;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
err = -ENODEV;
|
||||
if (bcm->initialized)
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
|
||||
err = bcm43xx_sprom_read(bcm, sprom);
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
if (!err)
|
||||
data->data.length = sprom2hex(sprom, extra);
|
||||
kfree(sprom);
|
||||
|
@ -812,11 +809,11 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
|
|||
if (err)
|
||||
goto out_kfree;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
bcm43xx_lock_irqsafe(bcm, flags);
|
||||
err = -ENODEV;
|
||||
if (bcm->initialized)
|
||||
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
|
||||
err = bcm43xx_sprom_write(bcm, sprom);
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
bcm43xx_unlock_irqsafe(bcm, flags);
|
||||
out_kfree:
|
||||
kfree(sprom);
|
||||
out:
|
||||
|
|
|
@ -533,7 +533,7 @@ static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask)
|
|||
ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask);
|
||||
}
|
||||
|
||||
static inline void ipw_enable_interrupts(struct ipw_priv *priv)
|
||||
static inline void __ipw_enable_interrupts(struct ipw_priv *priv)
|
||||
{
|
||||
if (priv->status & STATUS_INT_ENABLED)
|
||||
return;
|
||||
|
@ -541,7 +541,7 @@ static inline void ipw_enable_interrupts(struct ipw_priv *priv)
|
|||
ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL);
|
||||
}
|
||||
|
||||
static inline void ipw_disable_interrupts(struct ipw_priv *priv)
|
||||
static inline void __ipw_disable_interrupts(struct ipw_priv *priv)
|
||||
{
|
||||
if (!(priv->status & STATUS_INT_ENABLED))
|
||||
return;
|
||||
|
@ -549,6 +549,24 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv)
|
|||
ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL);
|
||||
}
|
||||
|
||||
static inline void ipw_enable_interrupts(struct ipw_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->irq_lock, flags);
|
||||
__ipw_enable_interrupts(priv);
|
||||
spin_unlock_irqrestore(&priv->irq_lock, flags);
|
||||
}
|
||||
|
||||
static inline void ipw_disable_interrupts(struct ipw_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->irq_lock, flags);
|
||||
__ipw_disable_interrupts(priv);
|
||||
spin_unlock_irqrestore(&priv->irq_lock, flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPW2200_DEBUG
|
||||
static char *ipw_error_desc(u32 val)
|
||||
{
|
||||
|
@ -1856,7 +1874,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
|
|||
unsigned long flags;
|
||||
int rc = 0;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
spin_lock_irqsave(&priv->irq_lock, flags);
|
||||
|
||||
inta = ipw_read32(priv, IPW_INTA_RW);
|
||||
inta_mask = ipw_read32(priv, IPW_INTA_MASK_R);
|
||||
|
@ -1865,6 +1883,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
|
|||
/* Add any cached INTA values that need to be handled */
|
||||
inta |= priv->isr_inta;
|
||||
|
||||
spin_unlock_irqrestore(&priv->irq_lock, flags);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* handle all the justifications for the interrupt */
|
||||
if (inta & IPW_INTA_BIT_RX_TRANSFER) {
|
||||
ipw_rx(priv);
|
||||
|
@ -1993,10 +2015,10 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
|
|||
IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/* enable all interrupts */
|
||||
ipw_enable_interrupts(priv);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
#define IPW_CMD(x) case IPW_CMD_ ## x : return #x
|
||||
|
@ -10460,7 +10482,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs)
|
|||
if (!priv)
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
spin_lock(&priv->irq_lock);
|
||||
|
||||
if (!(priv->status & STATUS_INT_ENABLED)) {
|
||||
/* Shared IRQ */
|
||||
|
@ -10482,7 +10504,7 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
/* tell the device to stop sending interrupts */
|
||||
ipw_disable_interrupts(priv);
|
||||
__ipw_disable_interrupts(priv);
|
||||
|
||||
/* ack current interrupts */
|
||||
inta &= (IPW_INTA_MASK_ALL & inta_mask);
|
||||
|
@ -10493,11 +10515,11 @@ static irqreturn_t ipw_isr(int irq, void *data, struct pt_regs *regs)
|
|||
|
||||
tasklet_schedule(&priv->irq_tasklet);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
spin_unlock(&priv->irq_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
none:
|
||||
spin_unlock(&priv->lock);
|
||||
spin_unlock(&priv->irq_lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
|
@ -11477,6 +11499,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
#ifdef CONFIG_IPW2200_DEBUG
|
||||
ipw_debug_level = debug;
|
||||
#endif
|
||||
spin_lock_init(&priv->irq_lock);
|
||||
spin_lock_init(&priv->lock);
|
||||
for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++)
|
||||
INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
|
||||
|
|
|
@ -1173,6 +1173,7 @@ struct ipw_priv {
|
|||
struct ieee80211_device *ieee;
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t irq_lock;
|
||||
struct mutex mutex;
|
||||
|
||||
/* basic pci-network driver stuff */
|
||||
|
|
|
@ -1695,8 +1695,8 @@ static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */
|
|||
/* Look in the table if the frequency is allowed */
|
||||
if (table[9 - (freq / 16)] & (1 << (freq % 16))) {
|
||||
/* Compute approximate channel number */
|
||||
while ((((channel_bands[c] >> 1) - 24) < freq) &&
|
||||
(c < NELS(channel_bands)))
|
||||
while ((c < NELS(channel_bands)) &&
|
||||
(((channel_bands[c] >> 1) - 24) < freq))
|
||||
c++;
|
||||
list[i].i = c; /* Set the list index */
|
||||
|
||||
|
@ -2903,6 +2903,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev)
|
|||
{
|
||||
net_local *lp = (net_local *) dev->priv;
|
||||
unsigned long flags;
|
||||
char data[ETH_ZLEN];
|
||||
|
||||
#ifdef DEBUG_TX_TRACE
|
||||
printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
|
||||
|
@ -2937,15 +2938,16 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev)
|
|||
* able to detect collisions, therefore in theory we don't really
|
||||
* need to pad. Jean II */
|
||||
if (skb->len < ETH_ZLEN) {
|
||||
skb = skb_padto(skb, ETH_ZLEN);
|
||||
if (skb == NULL)
|
||||
return 0;
|
||||
memset(data, 0, ETH_ZLEN);
|
||||
memcpy(data, skb->data, skb->len);
|
||||
/* Write packet on the card */
|
||||
if(wv_packet_write(dev, data, ETH_ZLEN))
|
||||
return 1; /* We failed */
|
||||
}
|
||||
|
||||
/* Write packet on the card */
|
||||
if(wv_packet_write(dev, skb->data, skb->len))
|
||||
else if(wv_packet_write(dev, skb->data, skb->len))
|
||||
return 1; /* We failed */
|
||||
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
#ifdef DEBUG_TX_TRACE
|
||||
|
|
27
include/asm-arm/arch-netx/eth.h
Normal file
27
include/asm-arm/arch-netx/eth.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* include/asm-arm/arch-netx/eth.h
|
||||
*
|
||||
* Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef ASMARM_ARCH_ETH_H
|
||||
#define ASMARM_ARCH_ETH_H
|
||||
|
||||
struct netxeth_platform_data {
|
||||
unsigned int xcno; /* number of xmac/xpec engine this eth uses */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -188,7 +188,7 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr);
|
|||
int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
|
||||
|
||||
/* Must be used by hardware driver on module startup/exit */
|
||||
int register_hdlc_device(struct net_device *dev);
|
||||
#define register_hdlc_device(dev) register_netdev(dev)
|
||||
void unregister_hdlc_device(struct net_device *dev);
|
||||
|
||||
struct net_device *alloc_hdlcdev(void *priv);
|
||||
|
|
|
@ -968,6 +968,7 @@ enum ieee80211_state {
|
|||
|
||||
enum {
|
||||
IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
|
||||
IEEE80211_CH_80211H_RULES = (1 << 1),
|
||||
IEEE80211_CH_B_ONLY = (1 << 2),
|
||||
IEEE80211_CH_NO_IBSS = (1 << 3),
|
||||
IEEE80211_CH_UNIFORM_SPREADING = (1 << 4),
|
||||
|
@ -976,10 +977,10 @@ enum {
|
|||
};
|
||||
|
||||
struct ieee80211_channel {
|
||||
u32 freq;
|
||||
u32 freq; /* in MHz */
|
||||
u8 channel;
|
||||
u8 flags;
|
||||
u8 max_power;
|
||||
u8 max_power; /* in dBm */
|
||||
};
|
||||
|
||||
struct ieee80211_geo {
|
||||
|
|
|
@ -388,7 +388,7 @@ ieee80211softmac_wx_set_genie(struct net_device *dev,
|
|||
memcpy(mac->wpa.IE, extra, wrqu->data.length);
|
||||
dprintk(KERN_INFO PFX "generic IE set to ");
|
||||
for (i=0;i<wrqu->data.length;i++)
|
||||
dprintk("%.2x", mac->wpa.IE[i]);
|
||||
dprintk("%.2x", (u8)mac->wpa.IE[i]);
|
||||
dprintk("\n");
|
||||
mac->wpa.IElen = wrqu->data.length;
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue