Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/netdev-2.6
* 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/netdev-2.6: [PATCH] bcm43xx: Fix access to non-existent PHY registers [PATCH] bcm43xx: Fix array overrun in bcm43xx_geo_init [PATCH] bcm43xx: check for valid MAC address in SPROM [PATCH] ieee80211: Fix A band channel count (resent) [PATCH] bcm43xx: fix iwmode crash when down [PATCH] softmac: make non-operational after being stopped [PATCH] softmac: don't reassociate if user asked for deauthentication spidernet: enable support for bcm5461 ethernet phy spidernet: introduce new setting Fix RTL8019AS init for Toshiba RBTX49xx boards au1000_eth.c: use ether_crc() from <linux/crc32.h> sky2: version 1.3 Add more support for the Yukon Ultra chip found in dual core centino laptops. sky2: synchronize irq on remove sky2: dont write status ring sky2: edge triggered workaround enhancement sky2: use mask instead of modulo operation sky2: tx ring index mask fix sky2: status irq hang fix sky2: backout NAPI reschedule
This commit is contained in:
commit
3cd73eedde
19 changed files with 283 additions and 178 deletions
|
@ -52,6 +52,7 @@
|
|||
#include <linux/mii.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -2070,23 +2071,6 @@ static void au1000_tx_timeout(struct net_device *dev)
|
|||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
|
||||
static unsigned const ethernet_polynomial = 0x04c11db7U;
|
||||
static inline u32 ether_crc(int length, unsigned char *data)
|
||||
{
|
||||
int crc = -1;
|
||||
|
||||
while(--length >= 0) {
|
||||
unsigned char current_octet = *data++;
|
||||
int bit;
|
||||
for (bit = 0; bit < 8; bit++, current_octet >>= 1)
|
||||
crc = (crc << 1) ^
|
||||
((crc < 0) ^ (current_octet & 1) ?
|
||||
ethernet_polynomial : 0);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
static void set_rx_mode(struct net_device *dev)
|
||||
{
|
||||
struct au1000_private *aup = (struct au1000_private *) dev->priv;
|
||||
|
|
|
@ -139,8 +139,9 @@ bad_clone_list[] __initdata = {
|
|||
|
||||
#if defined(CONFIG_PLAT_MAPPI)
|
||||
# define DCR_VAL 0x4b
|
||||
#elif defined(CONFIG_PLAT_OAKS32R)
|
||||
# define DCR_VAL 0x48
|
||||
#elif defined(CONFIG_PLAT_OAKS32R) || \
|
||||
defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
|
||||
# define DCR_VAL 0x48 /* 8-bit mode */
|
||||
#else
|
||||
# define DCR_VAL 0x49
|
||||
#endif
|
||||
|
@ -396,10 +397,22 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
|
|||
/* We must set the 8390 for word mode. */
|
||||
outb_p(DCR_VAL, ioaddr + EN0_DCFG);
|
||||
start_page = NESM_START_PG;
|
||||
stop_page = NESM_STOP_PG;
|
||||
|
||||
/*
|
||||
* Realtek RTL8019AS datasheet says that the PSTOP register
|
||||
* shouldn't exceed 0x60 in 8-bit mode.
|
||||
* This chip can be identified by reading the signature from
|
||||
* the remote byte count registers (otherwise write-only)...
|
||||
*/
|
||||
if ((DCR_VAL & 0x01) == 0 && /* 8-bit mode */
|
||||
inb(ioaddr + EN0_RCNTLO) == 0x50 &&
|
||||
inb(ioaddr + EN0_RCNTHI) == 0x70)
|
||||
stop_page = 0x60;
|
||||
else
|
||||
stop_page = NESM_STOP_PG;
|
||||
} else {
|
||||
start_page = NE1SM_START_PG;
|
||||
stop_page = NE1SM_STOP_PG;
|
||||
stop_page = NE1SM_STOP_PG;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
|
||||
|
@ -509,15 +522,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
|
|||
ei_status.name = name;
|
||||
ei_status.tx_start_page = start_page;
|
||||
ei_status.stop_page = stop_page;
|
||||
#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
|
||||
wordlength = 1;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PLAT_OAKS32R
|
||||
ei_status.word16 = 0;
|
||||
#else
|
||||
ei_status.word16 = (wordlength == 2);
|
||||
#endif
|
||||
/* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
|
||||
ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
|
||||
|
||||
ei_status.rx_start_page = start_page + TX_PAGES;
|
||||
#ifdef PACKETBUF_MEMSIZE
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#include "sky2.h"
|
||||
|
||||
#define DRV_NAME "sky2"
|
||||
#define DRV_VERSION "1.2"
|
||||
#define DRV_VERSION "1.3"
|
||||
#define PFX DRV_NAME " "
|
||||
|
||||
/*
|
||||
|
@ -79,6 +79,8 @@
|
|||
#define NAPI_WEIGHT 64
|
||||
#define PHY_RETRIES 1000
|
||||
|
||||
#define RING_NEXT(x,s) (((x)+1) & ((s)-1))
|
||||
|
||||
static const u32 default_msg =
|
||||
NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
|
||||
| NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
|
||||
|
@ -96,6 +98,10 @@ static int disable_msi = 0;
|
|||
module_param(disable_msi, int, 0);
|
||||
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
|
||||
|
||||
static int idle_timeout = 100;
|
||||
module_param(idle_timeout, int, 0);
|
||||
MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms)");
|
||||
|
||||
static const struct pci_device_id sky2_id_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
|
||||
|
@ -298,7 +304,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
|
|||
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
|
||||
u16 ctrl, ct1000, adv, pg, ledctrl, ledover;
|
||||
|
||||
if (sky2->autoneg == AUTONEG_ENABLE && hw->chip_id != CHIP_ID_YUKON_XL) {
|
||||
if (sky2->autoneg == AUTONEG_ENABLE &&
|
||||
(hw->chip_id != CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
|
||||
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
|
||||
|
||||
ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
|
||||
|
@ -326,7 +333,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
|
|||
ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
|
||||
|
||||
if (sky2->autoneg == AUTONEG_ENABLE &&
|
||||
hw->chip_id == CHIP_ID_YUKON_XL) {
|
||||
(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) {
|
||||
ctrl &= ~PHY_M_PC_DSC_MSK;
|
||||
ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
|
||||
}
|
||||
|
@ -442,10 +449,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
|
|||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
|
||||
|
||||
/* set LED Function Control register */
|
||||
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
|
||||
PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */
|
||||
PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
|
||||
PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */
|
||||
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
|
||||
(PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
|
||||
PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */
|
||||
PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
|
||||
PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */
|
||||
|
||||
/* set Polarity Control register */
|
||||
gm_phy_write(hw, port, PHY_MARV_PHY_STAT,
|
||||
|
@ -459,6 +467,25 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
|
|||
/* restore page register */
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
|
||||
break;
|
||||
case CHIP_ID_YUKON_EC_U:
|
||||
pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
|
||||
|
||||
/* select page 3 to access LED control register */
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
|
||||
|
||||
/* set LED Function Control register */
|
||||
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
|
||||
(PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
|
||||
PHY_M_LEDC_INIT_CTRL(8) | /* 10 Mbps */
|
||||
PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
|
||||
PHY_M_LEDC_STA0_CTRL(7)));/* 1000 Mbps */
|
||||
|
||||
/* set Blink Rate in LED Timer Control Register */
|
||||
gm_phy_write(hw, port, PHY_MARV_INT_MASK,
|
||||
ledctrl | PHY_M_LED_BLINK_RT(BLINK_84MS));
|
||||
/* restore page register */
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
|
||||
|
@ -467,19 +494,21 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
|
|||
ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
|
||||
}
|
||||
|
||||
if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) {
|
||||
if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) {
|
||||
/* apply fixes in PHY AFE */
|
||||
gm_phy_write(hw, port, 22, 255);
|
||||
pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255);
|
||||
|
||||
/* increase differential signal amplitude in 10BASE-T */
|
||||
gm_phy_write(hw, port, 24, 0xaa99);
|
||||
gm_phy_write(hw, port, 23, 0x2011);
|
||||
gm_phy_write(hw, port, 0x18, 0xaa99);
|
||||
gm_phy_write(hw, port, 0x17, 0x2011);
|
||||
|
||||
/* fix for IEEE A/B Symmetry failure in 1000BASE-T */
|
||||
gm_phy_write(hw, port, 24, 0xa204);
|
||||
gm_phy_write(hw, port, 23, 0x2002);
|
||||
gm_phy_write(hw, port, 0x18, 0xa204);
|
||||
gm_phy_write(hw, port, 0x17, 0x2002);
|
||||
|
||||
/* set page register to 0 */
|
||||
gm_phy_write(hw, port, 22, 0);
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
|
||||
} else {
|
||||
gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
|
||||
|
||||
|
@ -553,6 +582,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
|
|||
|
||||
if (sky2->duplex == DUPLEX_FULL)
|
||||
reg |= GM_GPCR_DUP_FULL;
|
||||
|
||||
/* turn off pause in 10/100mbps half duplex */
|
||||
else if (sky2->speed != SPEED_1000 &&
|
||||
hw->chip_id != CHIP_ID_YUKON_EC_U)
|
||||
sky2->tx_pause = sky2->rx_pause = 0;
|
||||
} else
|
||||
reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
|
||||
|
||||
|
@ -719,7 +753,7 @@ static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
|
|||
{
|
||||
struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod;
|
||||
|
||||
sky2->tx_prod = (sky2->tx_prod + 1) % TX_RING_SIZE;
|
||||
sky2->tx_prod = RING_NEXT(sky2->tx_prod, TX_RING_SIZE);
|
||||
return le;
|
||||
}
|
||||
|
||||
|
@ -735,7 +769,7 @@ static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx)
|
|||
static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
|
||||
{
|
||||
struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put;
|
||||
sky2->rx_put = (sky2->rx_put + 1) % RX_LE_SIZE;
|
||||
sky2->rx_put = RING_NEXT(sky2->rx_put, RX_LE_SIZE);
|
||||
return le;
|
||||
}
|
||||
|
||||
|
@ -1078,7 +1112,7 @@ err_out:
|
|||
/* Modular subtraction in ring */
|
||||
static inline int tx_dist(unsigned tail, unsigned head)
|
||||
{
|
||||
return (head - tail) % TX_RING_SIZE;
|
||||
return (head - tail) & (TX_RING_SIZE - 1);
|
||||
}
|
||||
|
||||
/* Number of list elements available for next tx */
|
||||
|
@ -1255,7 +1289,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
|
|||
le->opcode = OP_BUFFER | HW_OWNER;
|
||||
|
||||
fre = sky2->tx_ring
|
||||
+ ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE;
|
||||
+ RING_NEXT((re - sky2->tx_ring) + i, TX_RING_SIZE);
|
||||
pci_unmap_addr_set(fre, mapaddr, mapping);
|
||||
}
|
||||
|
||||
|
@ -1315,7 +1349,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
|
|||
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
struct tx_ring_info *fre;
|
||||
fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE;
|
||||
fre = sky2->tx_ring + RING_NEXT(put + i, TX_RING_SIZE);
|
||||
pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr),
|
||||
skb_shinfo(skb)->frags[i].size,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
@ -1498,17 +1532,26 @@ static void sky2_link_up(struct sky2_port *sky2)
|
|||
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
|
||||
LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
|
||||
|
||||
if (hw->chip_id == CHIP_ID_YUKON_XL) {
|
||||
if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) {
|
||||
u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
|
||||
u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */
|
||||
|
||||
switch(sky2->speed) {
|
||||
case SPEED_10:
|
||||
led |= PHY_M_LEDC_INIT_CTRL(7);
|
||||
break;
|
||||
|
||||
case SPEED_100:
|
||||
led |= PHY_M_LEDC_STA1_CTRL(7);
|
||||
break;
|
||||
|
||||
case SPEED_1000:
|
||||
led |= PHY_M_LEDC_STA0_CTRL(7);
|
||||
break;
|
||||
}
|
||||
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
|
||||
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
|
||||
PHY_M_LEDC_INIT_CTRL(sky2->speed ==
|
||||
SPEED_10 ? 7 : 0) |
|
||||
PHY_M_LEDC_STA1_CTRL(sky2->speed ==
|
||||
SPEED_100 ? 7 : 0) |
|
||||
PHY_M_LEDC_STA0_CTRL(sky2->speed ==
|
||||
SPEED_1000 ? 7 : 0));
|
||||
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led);
|
||||
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
|
||||
}
|
||||
|
||||
|
@ -1583,7 +1626,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
|
|||
sky2->speed = sky2_phy_speed(hw, aux);
|
||||
|
||||
/* Pause bits are offset (9..8) */
|
||||
if (hw->chip_id == CHIP_ID_YUKON_XL)
|
||||
if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)
|
||||
aux >>= 6;
|
||||
|
||||
sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0;
|
||||
|
@ -1859,35 +1902,28 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
|
|||
static int sky2_status_intr(struct sky2_hw *hw, int to_do)
|
||||
{
|
||||
int work_done = 0;
|
||||
u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
|
||||
|
||||
rmb();
|
||||
|
||||
for(;;) {
|
||||
while (hw->st_idx != hwidx) {
|
||||
struct sky2_status_le *le = hw->st_le + hw->st_idx;
|
||||
struct net_device *dev;
|
||||
struct sky2_port *sky2;
|
||||
struct sk_buff *skb;
|
||||
u32 status;
|
||||
u16 length;
|
||||
u8 link, opcode;
|
||||
|
||||
opcode = le->opcode;
|
||||
if (!opcode)
|
||||
break;
|
||||
opcode &= ~HW_OWNER;
|
||||
hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
|
||||
|
||||
hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
|
||||
le->opcode = 0;
|
||||
|
||||
link = le->link;
|
||||
BUG_ON(link >= 2);
|
||||
dev = hw->dev[link];
|
||||
BUG_ON(le->link >= 2);
|
||||
dev = hw->dev[le->link];
|
||||
|
||||
sky2 = netdev_priv(dev);
|
||||
length = le->length;
|
||||
status = le->status;
|
||||
|
||||
switch (opcode) {
|
||||
switch (le->opcode & ~HW_OWNER) {
|
||||
case OP_RXSTAT:
|
||||
skb = sky2_receive(sky2, length, status);
|
||||
if (!skb)
|
||||
|
@ -1927,7 +1963,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
|
|||
|
||||
case OP_TXINDEXLE:
|
||||
/* TX index reports status for both ports */
|
||||
sky2_tx_done(hw->dev[0], status & 0xffff);
|
||||
BUILD_BUG_ON(TX_RING_SIZE > 0x1000);
|
||||
sky2_tx_done(hw->dev[0], status & 0xfff);
|
||||
if (hw->dev[1])
|
||||
sky2_tx_done(hw->dev[1],
|
||||
((status >> 24) & 0xff)
|
||||
|
@ -1937,8 +1974,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
|
|||
default:
|
||||
if (net_ratelimit())
|
||||
printk(KERN_WARNING PFX
|
||||
"unknown status opcode 0x%x\n", opcode);
|
||||
break;
|
||||
"unknown status opcode 0x%x\n", le->opcode);
|
||||
goto exit_loop;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2089,12 +2126,13 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port,
|
|||
*/
|
||||
static void sky2_idle(unsigned long arg)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *) arg;
|
||||
struct sky2_hw *hw = (struct sky2_hw *) arg;
|
||||
struct net_device *dev = hw->dev[0];
|
||||
|
||||
local_irq_disable();
|
||||
if (__netif_rx_schedule_prep(dev))
|
||||
__netif_rx_schedule(dev);
|
||||
local_irq_enable();
|
||||
|
||||
mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2105,65 +2143,46 @@ static int sky2_poll(struct net_device *dev0, int *budget)
|
|||
int work_done = 0;
|
||||
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
|
||||
|
||||
restart_poll:
|
||||
if (unlikely(status & ~Y2_IS_STAT_BMU)) {
|
||||
if (status & Y2_IS_HW_ERR)
|
||||
sky2_hw_intr(hw);
|
||||
if (status & Y2_IS_HW_ERR)
|
||||
sky2_hw_intr(hw);
|
||||
|
||||
if (status & Y2_IS_IRQ_PHY1)
|
||||
sky2_phy_intr(hw, 0);
|
||||
if (status & Y2_IS_IRQ_PHY1)
|
||||
sky2_phy_intr(hw, 0);
|
||||
|
||||
if (status & Y2_IS_IRQ_PHY2)
|
||||
sky2_phy_intr(hw, 1);
|
||||
if (status & Y2_IS_IRQ_PHY2)
|
||||
sky2_phy_intr(hw, 1);
|
||||
|
||||
if (status & Y2_IS_IRQ_MAC1)
|
||||
sky2_mac_intr(hw, 0);
|
||||
if (status & Y2_IS_IRQ_MAC1)
|
||||
sky2_mac_intr(hw, 0);
|
||||
|
||||
if (status & Y2_IS_IRQ_MAC2)
|
||||
sky2_mac_intr(hw, 1);
|
||||
if (status & Y2_IS_IRQ_MAC2)
|
||||
sky2_mac_intr(hw, 1);
|
||||
|
||||
if (status & Y2_IS_CHK_RX1)
|
||||
sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);
|
||||
if (status & Y2_IS_CHK_RX1)
|
||||
sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);
|
||||
|
||||
if (status & Y2_IS_CHK_RX2)
|
||||
sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);
|
||||
if (status & Y2_IS_CHK_RX2)
|
||||
sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);
|
||||
|
||||
if (status & Y2_IS_CHK_TXA1)
|
||||
sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);
|
||||
if (status & Y2_IS_CHK_TXA1)
|
||||
sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);
|
||||
|
||||
if (status & Y2_IS_CHK_TXA2)
|
||||
sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
|
||||
}
|
||||
|
||||
if (status & Y2_IS_STAT_BMU) {
|
||||
work_done += sky2_status_intr(hw, work_limit - work_done);
|
||||
*budget -= work_done;
|
||||
dev0->quota -= work_done;
|
||||
|
||||
if (work_done >= work_limit)
|
||||
return 1;
|
||||
if (status & Y2_IS_CHK_TXA2)
|
||||
sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
|
||||
|
||||
if (status & Y2_IS_STAT_BMU)
|
||||
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
|
||||
}
|
||||
|
||||
mod_timer(&hw->idle_timer, jiffies + HZ);
|
||||
work_done = sky2_status_intr(hw, work_limit);
|
||||
*budget -= work_done;
|
||||
dev0->quota -= work_done;
|
||||
|
||||
local_irq_disable();
|
||||
__netif_rx_complete(dev0);
|
||||
if (work_done >= work_limit)
|
||||
return 1;
|
||||
|
||||
netif_rx_complete(dev0);
|
||||
|
||||
status = sky2_read32(hw, B0_Y2_SP_LISR);
|
||||
|
||||
if (unlikely(status)) {
|
||||
/* More work pending, try and keep going */
|
||||
if (__netif_rx_schedule_prep(dev0)) {
|
||||
__netif_rx_reschedule(dev0, work_done);
|
||||
status = sky2_read32(hw, B0_Y2_SP_EISR);
|
||||
local_irq_enable();
|
||||
goto restart_poll;
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2244,13 +2263,6 @@ static int __devinit sky2_reset(struct sky2_hw *hw)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* This chip is new and not tested yet */
|
||||
if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
|
||||
pr_info(PFX "%s: is a version of Yukon 2 chipset that has not been tested yet.\n",
|
||||
pci_name(hw->pdev));
|
||||
pr_info("Please report success/failure to maintainer <shemminger@osdl.org>\n");
|
||||
}
|
||||
|
||||
/* disable ASF */
|
||||
if (hw->chip_id <= CHIP_ID_YUKON_EC) {
|
||||
sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
|
||||
|
@ -3302,7 +3314,10 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
|
|||
|
||||
sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
|
||||
|
||||
setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev);
|
||||
setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
|
||||
if (idle_timeout > 0)
|
||||
mod_timer(&hw->idle_timer,
|
||||
jiffies + msecs_to_jiffies(idle_timeout));
|
||||
|
||||
pci_set_drvdata(pdev, hw);
|
||||
|
||||
|
@ -3342,6 +3357,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
|
|||
del_timer_sync(&hw->idle_timer);
|
||||
|
||||
sky2_write32(hw, B0_IMSK, 0);
|
||||
synchronize_irq(hw->pdev->irq);
|
||||
|
||||
dev0 = hw->dev[0];
|
||||
dev1 = hw->dev[1];
|
||||
if (dev1)
|
||||
|
|
|
@ -378,6 +378,9 @@ enum {
|
|||
CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */
|
||||
CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */
|
||||
CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */
|
||||
|
||||
CHIP_REV_YU_EC_U_A0 = 0,
|
||||
CHIP_REV_YU_EC_U_A1 = 1,
|
||||
};
|
||||
|
||||
/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
|
||||
|
|
|
@ -1652,6 +1652,8 @@ spider_net_enable_card(struct spider_net_card *card)
|
|||
{ SPIDER_NET_GFTRESTRT, SPIDER_NET_RESTART_VALUE },
|
||||
|
||||
{ SPIDER_NET_GMRWOLCTRL, 0 },
|
||||
{ SPIDER_NET_GTESTMD, 0x10000000 },
|
||||
{ SPIDER_NET_GTTQMSK, 0x00400040 },
|
||||
{ SPIDER_NET_GTESTMD, 0 },
|
||||
|
||||
{ SPIDER_NET_GMACINTEN, 0 },
|
||||
|
@ -1792,15 +1794,7 @@ spider_net_setup_phy(struct spider_net_card *card)
|
|||
if (phy->def->ops->setup_forced)
|
||||
phy->def->ops->setup_forced(phy, SPEED_1000, DUPLEX_FULL);
|
||||
|
||||
/* the following two writes could be moved to sungem_phy.c */
|
||||
/* enable fiber mode */
|
||||
spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x9020);
|
||||
/* LEDs active in both modes, autosense prio = fiber */
|
||||
spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
|
||||
|
||||
/* switch off fibre autoneg */
|
||||
spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
|
||||
spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
|
||||
phy->def->ops->enable_fiber(phy);
|
||||
|
||||
phy->def->ops->read_link(phy);
|
||||
pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
|
||||
|
|
|
@ -120,6 +120,8 @@ extern char spider_net_driver_name[];
|
|||
#define SPIDER_NET_GMRUAFILnR 0x00000500
|
||||
#define SPIDER_NET_GMRUA0FIL15R 0x00000578
|
||||
|
||||
#define SPIDER_NET_GTTQMSK 0x00000934
|
||||
|
||||
/* RX DMA controller registers, all 0x00000a.. are for DMA controller A,
|
||||
* 0x00000b.. for DMA controller B, etc. */
|
||||
#define SPIDER_NET_GDADCHA 0x00000a00
|
||||
|
|
|
@ -329,6 +329,30 @@ static int bcm5421_init(struct mii_phy* phy)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bcm5421_enable_fiber(struct mii_phy* phy)
|
||||
{
|
||||
/* enable fiber mode */
|
||||
phy_write(phy, MII_NCONFIG, 0x9020);
|
||||
/* LEDs active in both modes, autosense prio = fiber */
|
||||
phy_write(phy, MII_NCONFIG, 0x945f);
|
||||
|
||||
/* switch off fibre autoneg */
|
||||
phy_write(phy, MII_NCONFIG, 0xfc01);
|
||||
phy_write(phy, 0x0b, 0x0004);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm5461_enable_fiber(struct mii_phy* phy)
|
||||
{
|
||||
phy_write(phy, MII_NCONFIG, 0xfc0c);
|
||||
phy_write(phy, MII_BMCR, 0x4140);
|
||||
phy_write(phy, MII_NCONFIG, 0xfc0b);
|
||||
phy_write(phy, MII_BMCR, 0x0140);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
|
||||
{
|
||||
u16 ctl, adv;
|
||||
|
@ -762,6 +786,7 @@ static struct mii_phy_ops bcm5421_phy_ops = {
|
|||
.setup_forced = bcm54xx_setup_forced,
|
||||
.poll_link = genmii_poll_link,
|
||||
.read_link = bcm54xx_read_link,
|
||||
.enable_fiber = bcm5421_enable_fiber,
|
||||
};
|
||||
|
||||
static struct mii_phy_def bcm5421_phy_def = {
|
||||
|
@ -792,6 +817,25 @@ static struct mii_phy_def bcm5421k2_phy_def = {
|
|||
.ops = &bcm5421k2_phy_ops
|
||||
};
|
||||
|
||||
static struct mii_phy_ops bcm5461_phy_ops = {
|
||||
.init = bcm5421_init,
|
||||
.suspend = generic_suspend,
|
||||
.setup_aneg = bcm54xx_setup_aneg,
|
||||
.setup_forced = bcm54xx_setup_forced,
|
||||
.poll_link = genmii_poll_link,
|
||||
.read_link = bcm54xx_read_link,
|
||||
.enable_fiber = bcm5461_enable_fiber,
|
||||
};
|
||||
|
||||
static struct mii_phy_def bcm5461_phy_def = {
|
||||
.phy_id = 0x002060c0,
|
||||
.phy_id_mask = 0xfffffff0,
|
||||
.name = "BCM5461",
|
||||
.features = MII_GBIT_FEATURES,
|
||||
.magic_aneg = 1,
|
||||
.ops = &bcm5461_phy_ops
|
||||
};
|
||||
|
||||
/* Broadcom BCM 5462 built-in Vesta */
|
||||
static struct mii_phy_ops bcm5462V_phy_ops = {
|
||||
.init = bcm5421_init,
|
||||
|
@ -857,6 +901,7 @@ static struct mii_phy_def* mii_phy_table[] = {
|
|||
&bcm5411_phy_def,
|
||||
&bcm5421_phy_def,
|
||||
&bcm5421k2_phy_def,
|
||||
&bcm5461_phy_def,
|
||||
&bcm5462V_phy_def,
|
||||
&marvell_phy_def,
|
||||
&genmii_phy_def,
|
||||
|
|
|
@ -12,6 +12,7 @@ struct mii_phy_ops
|
|||
int (*setup_forced)(struct mii_phy *phy, int speed, int fd);
|
||||
int (*poll_link)(struct mii_phy *phy);
|
||||
int (*read_link)(struct mii_phy *phy);
|
||||
int (*enable_fiber)(struct mii_phy *phy);
|
||||
};
|
||||
|
||||
/* Structure used to statically define an mii/gii based PHY */
|
||||
|
|
|
@ -939,9 +939,9 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
|
||||
static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
|
||||
{
|
||||
struct ieee80211_geo geo;
|
||||
struct ieee80211_geo *geo;
|
||||
struct ieee80211_channel *chan;
|
||||
int have_a = 0, have_bg = 0;
|
||||
int i;
|
||||
|
@ -949,7 +949,10 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
|
|||
struct bcm43xx_phyinfo *phy;
|
||||
const char *iso_country;
|
||||
|
||||
memset(&geo, 0, sizeof(geo));
|
||||
geo = kzalloc(sizeof(*geo), GFP_KERNEL);
|
||||
if (!geo)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < bcm->nr_80211_available; i++) {
|
||||
phy = &(bcm->core_80211_ext[i].phy);
|
||||
switch (phy->type) {
|
||||
|
@ -967,31 +970,36 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm)
|
|||
iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
|
||||
|
||||
if (have_a) {
|
||||
for (i = 0, channel = 0; channel < 201; channel++) {
|
||||
chan = &geo.a[i++];
|
||||
for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
|
||||
channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
|
||||
chan = &geo->a[i++];
|
||||
chan->freq = bcm43xx_channel_to_freq_a(channel);
|
||||
chan->channel = channel;
|
||||
}
|
||||
geo.a_channels = i;
|
||||
geo->a_channels = i;
|
||||
}
|
||||
if (have_bg) {
|
||||
for (i = 0, channel = 1; channel < 15; channel++) {
|
||||
chan = &geo.bg[i++];
|
||||
for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
|
||||
channel <= IEEE80211_24GHZ_MAX_CHANNEL; channel++) {
|
||||
chan = &geo->bg[i++];
|
||||
chan->freq = bcm43xx_channel_to_freq_bg(channel);
|
||||
chan->channel = channel;
|
||||
}
|
||||
geo.bg_channels = i;
|
||||
geo->bg_channels = i;
|
||||
}
|
||||
memcpy(geo.name, iso_country, 2);
|
||||
memcpy(geo->name, iso_country, 2);
|
||||
if (0 /*TODO: Outdoor use only */)
|
||||
geo.name[2] = 'O';
|
||||
geo->name[2] = 'O';
|
||||
else if (0 /*TODO: Indoor use only */)
|
||||
geo.name[2] = 'I';
|
||||
geo->name[2] = 'I';
|
||||
else
|
||||
geo.name[2] = ' ';
|
||||
geo.name[3] = '\0';
|
||||
geo->name[2] = ' ';
|
||||
geo->name[3] = '\0';
|
||||
|
||||
ieee80211_set_geo(bcm->ieee, &geo);
|
||||
ieee80211_set_geo(bcm->ieee, geo);
|
||||
kfree(geo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DummyTransmission function, as documented on
|
||||
|
@ -3479,16 +3487,17 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
|
|||
goto err_80211_unwind;
|
||||
bcm43xx_wireless_core_disable(bcm);
|
||||
}
|
||||
err = bcm43xx_geo_init(bcm);
|
||||
if (err)
|
||||
goto err_80211_unwind;
|
||||
bcm43xx_pctl_set_crystal(bcm, 0);
|
||||
|
||||
/* Set the MAC address in the networking subsystem */
|
||||
if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
|
||||
if (is_valid_ether_addr(bcm->sprom.et1macaddr))
|
||||
memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
|
||||
else
|
||||
memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
|
||||
|
||||
bcm43xx_geo_init(bcm);
|
||||
|
||||
snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
|
||||
"Broadcom %04X", bcm->chip_id);
|
||||
|
||||
|
|
|
@ -118,12 +118,14 @@ int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
|
|||
static inline
|
||||
int bcm43xx_is_valid_channel_a(u8 channel)
|
||||
{
|
||||
return (channel <= 200);
|
||||
return (channel >= IEEE80211_52GHZ_MIN_CHANNEL
|
||||
&& channel <= IEEE80211_52GHZ_MAX_CHANNEL);
|
||||
}
|
||||
static inline
|
||||
int bcm43xx_is_valid_channel_bg(u8 channel)
|
||||
{
|
||||
return (channel >= 1 && channel <= 14);
|
||||
return (channel >= IEEE80211_24GHZ_MIN_CHANNEL
|
||||
&& channel <= IEEE80211_24GHZ_MAX_CHANNEL);
|
||||
}
|
||||
static inline
|
||||
int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
|
||||
|
|
|
@ -1287,7 +1287,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
|
|||
if (radio->revision == 8)
|
||||
bcm43xx_phy_write(bcm, 0x0805, 0x3230);
|
||||
bcm43xx_phy_init_pctl(bcm);
|
||||
if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) {
|
||||
if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
|
||||
bcm43xx_phy_write(bcm, 0x0429,
|
||||
bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
|
||||
bcm43xx_phy_write(bcm, 0x04C3,
|
||||
|
|
|
@ -182,8 +182,11 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev,
|
|||
mode = BCM43xx_INITIAL_IWMODE;
|
||||
|
||||
bcm43xx_lock_mmio(bcm, flags);
|
||||
if (bcm->ieee->iw_mode != mode)
|
||||
bcm43xx_set_iwmode(bcm, mode);
|
||||
if (bcm->initialized) {
|
||||
if (bcm->ieee->iw_mode != mode)
|
||||
bcm43xx_set_iwmode(bcm, mode);
|
||||
} else
|
||||
bcm->ieee->iw_mode = mode;
|
||||
bcm43xx_unlock_mmio(bcm, flags);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -831,21 +831,19 @@ static inline void netif_rx_schedule(struct net_device *dev)
|
|||
__netif_rx_schedule(dev);
|
||||
}
|
||||
|
||||
|
||||
static inline void __netif_rx_reschedule(struct net_device *dev, int undo)
|
||||
{
|
||||
dev->quota += undo;
|
||||
list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
|
||||
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
|
||||
}
|
||||
|
||||
/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete(). */
|
||||
/* Try to reschedule poll. Called by dev->poll() after netif_rx_complete().
|
||||
* Do not inline this?
|
||||
*/
|
||||
static inline int netif_rx_reschedule(struct net_device *dev, int undo)
|
||||
{
|
||||
if (netif_rx_schedule_prep(dev)) {
|
||||
unsigned long flags;
|
||||
|
||||
dev->quota += undo;
|
||||
|
||||
local_irq_save(flags);
|
||||
__netif_rx_reschedule(dev, undo);
|
||||
list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
|
||||
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
|
||||
local_irq_restore(flags);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -955,11 +955,13 @@ enum ieee80211_state {
|
|||
|
||||
#define IEEE80211_24GHZ_MIN_CHANNEL 1
|
||||
#define IEEE80211_24GHZ_MAX_CHANNEL 14
|
||||
#define IEEE80211_24GHZ_CHANNELS 14
|
||||
#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \
|
||||
IEEE80211_24GHZ_MIN_CHANNEL + 1)
|
||||
|
||||
#define IEEE80211_52GHZ_MIN_CHANNEL 34
|
||||
#define IEEE80211_52GHZ_MAX_CHANNEL 165
|
||||
#define IEEE80211_52GHZ_CHANNELS 131
|
||||
#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \
|
||||
IEEE80211_52GHZ_MIN_CHANNEL + 1)
|
||||
|
||||
enum {
|
||||
IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
|
||||
|
|
|
@ -204,7 +204,8 @@ struct ieee80211softmac_device {
|
|||
|
||||
/* couple of flags */
|
||||
u8 scanning:1, /* protects scanning from being done multiple times at once */
|
||||
associated:1;
|
||||
associated:1,
|
||||
running:1;
|
||||
|
||||
struct ieee80211softmac_scaninfo *scaninfo;
|
||||
struct ieee80211softmac_assoc_info associnfo;
|
||||
|
|
|
@ -51,11 +51,12 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
|
|||
spin_lock_irqsave(&mac->lock, flags);
|
||||
mac->associnfo.associating = 1;
|
||||
mac->associated = 0; /* just to make sure */
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
|
||||
/* Set a timer for timeout */
|
||||
/* FIXME: make timeout configurable */
|
||||
schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
|
||||
if (likely(mac->running))
|
||||
schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ);
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -319,6 +320,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev,
|
|||
u16 status = le16_to_cpup(&resp->status);
|
||||
struct ieee80211softmac_network *network = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(!mac->running))
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
|
||||
|
@ -377,10 +381,16 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
|
|||
{
|
||||
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(!mac->running))
|
||||
return -ENODEV;
|
||||
|
||||
if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
|
||||
return 0;
|
||||
|
||||
if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
|
||||
return 0;
|
||||
|
||||
dprintk(KERN_INFO PFX "got disassoc frame\n");
|
||||
netif_carrier_off(dev);
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
|
@ -400,6 +410,9 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev,
|
|||
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
|
||||
struct ieee80211softmac_network *network;
|
||||
|
||||
if (unlikely(!mac->running))
|
||||
return -ENODEV;
|
||||
|
||||
network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
|
||||
if (!network) {
|
||||
dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
|
||||
|
|
|
@ -86,6 +86,11 @@ ieee80211softmac_auth_queue(void *data)
|
|||
|
||||
/* Lock and set flags */
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
if (unlikely(!mac->running)) {
|
||||
/* Prevent reschedule on workqueue flush */
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
return;
|
||||
}
|
||||
net->authenticated = 0;
|
||||
net->authenticating = 1;
|
||||
/* add a timeout call so we eventually give up waiting for an auth reply */
|
||||
|
@ -124,6 +129,9 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
|
|||
unsigned long flags;
|
||||
u8 * data;
|
||||
|
||||
if (unlikely(!mac->running))
|
||||
return -ENODEV;
|
||||
|
||||
/* Find correct auth queue item */
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
list_for_each(list_ptr, &mac->auth_queue) {
|
||||
|
@ -298,8 +306,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
|
|||
|
||||
/* can't transmit data right now... */
|
||||
netif_carrier_off(mac->dev);
|
||||
/* let's try to re-associate */
|
||||
schedule_work(&mac->associnfo.work);
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -338,6 +344,9 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
|
|||
struct ieee80211softmac_network *net = NULL;
|
||||
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
|
||||
|
||||
if (unlikely(!mac->running))
|
||||
return -ENODEV;
|
||||
|
||||
if (!deauth) {
|
||||
dprintk("deauth without deauth packet. eek!\n");
|
||||
return 0;
|
||||
|
@ -360,5 +369,8 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de
|
|||
}
|
||||
|
||||
ieee80211softmac_deauth_from_net(mac, net);
|
||||
|
||||
/* let's try to re-associate */
|
||||
schedule_work(&mac->associnfo.work);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -89,6 +89,8 @@ ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
|
|||
ieee80211softmac_wait_for_scan(sm);
|
||||
|
||||
spin_lock_irqsave(&sm->lock, flags);
|
||||
sm->running = 0;
|
||||
|
||||
/* Free all pending assoc work items */
|
||||
cancel_delayed_work(&sm->associnfo.work);
|
||||
|
||||
|
@ -204,6 +206,8 @@ void ieee80211softmac_start(struct net_device *dev)
|
|||
assert(0);
|
||||
if (mac->txrates_change)
|
||||
mac->txrates_change(dev, change, &oldrates);
|
||||
|
||||
mac->running = 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ieee80211softmac_start);
|
||||
|
||||
|
|
|
@ -115,7 +115,15 @@ void ieee80211softmac_scan(void *d)
|
|||
// TODO: is this if correct, or should we do this only if scanning from assoc request?
|
||||
if (sm->associnfo.req_essid.len)
|
||||
ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
|
||||
|
||||
spin_lock_irqsave(&sm->lock, flags);
|
||||
if (unlikely(!sm->running)) {
|
||||
/* Prevent reschedule on workqueue flush */
|
||||
spin_unlock_irqrestore(&sm->lock, flags);
|
||||
break;
|
||||
}
|
||||
schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
|
||||
spin_unlock_irqrestore(&sm->lock, flags);
|
||||
return;
|
||||
} else {
|
||||
dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
|
||||
|
|
Loading…
Reference in a new issue