Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (75 commits)
  net: Handle NETREG_UNINITIALIZED devices correctly
  can: add the driver for Analog Devices Blackfin on-chip CAN controllers
  xfrm: Fix truncation length of authentication algorithms installed via PF_KEY
  net: use compat helper functions in compat_sys_recvmmsg
  net: fix compat_sys_recvmmsg parameter type
  cxgb3: Fixing EEH handlers
  cnic: Zero out status block and Event Queue indices.
  cnic: Send delete command when shutting down iSCSI ring.
  net: smc91x: Fix up type mismatch in smc_drv_resume().
  smc91x: fix unused flags warnings on UP systems
  MAINTAINERS: Transfering maintainership of cdc-ether
  net: Add missing TST_CFG_WRITE bits around sky2_pci_write
  net: Fix Yukon-2 Optima TCP offload setup
  net: niu uses crc32, so select CRC32
  wireless: update old static regulatory domain rules
  mac80211: Revert 'Use correct sign for mesh active path refresh'
  mac80211: Fixed bug in mesh portal paths
  net/mac80211: Correct size given to memset
  b43: Remove reset after fatal DMA error
  rtl8187: add radio led and fix warnings on suspend
  ...
This commit is contained in:
Linus Torvalds 2009-12-11 20:58:20 -08:00
commit 053fe57ac2
77 changed files with 1677 additions and 594 deletions

View file

@ -2505,7 +2505,7 @@ he_close(struct atm_vcc *vcc)
* TBRQ, the host issues the close command to the adapter.
*/
while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 0) &&
while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 1) &&
(retry < MAX_RETRY)) {
msleep(sleep);
if (sleep < 250)
@ -2514,7 +2514,7 @@ he_close(struct atm_vcc *vcc)
++retry;
}
if (tx_inuse)
if (tx_inuse > 1)
hprintk("close tx cid 0x%x tx_inuse = %d\n", cid, tx_inuse);
/* 2.3.1.1 generic close operations with flush */

View file

@ -29,7 +29,7 @@
#endif
/* Module parameters */
int gigaset_debuglevel = DEBUG_DEFAULT;
int gigaset_debuglevel;
EXPORT_SYMBOL_GPL(gigaset_debuglevel);
module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug, "debug level");

View file

@ -2696,6 +2696,7 @@ config NETXEN_NIC
config NIU
tristate "Sun Neptune 10Gbit Ethernet support"
depends on PCI
select CRC32
help
This enables support for cards based upon Sun's
Neptune chipset.

View file

@ -479,6 +479,9 @@ struct atl1c_buffer {
#define ATL1C_PCIMAP_PAGE 0x0008
#define ATL1C_PCIMAP_TYPE_MASK 0x000C
#define ATL1C_PCIMAP_TODEVICE 0x0010
#define ATL1C_PCIMAP_FROMDEVICE 0x0020
#define ATL1C_PCIMAP_DIRECTION_MASK 0x0030
dma_addr_t dma;
};
@ -487,9 +490,11 @@ struct atl1c_buffer {
((buff)->flags) |= (state); \
} while (0)
#define ATL1C_SET_PCIMAP_TYPE(buff, type) do { \
((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \
((buff)->flags) |= (type); \
#define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do { \
((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \
((buff)->flags) |= (type); \
((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK; \
((buff)->flags) |= (direction); \
} while (0)
/* transimit packet descriptor (tpd) ring */
@ -550,6 +555,9 @@ struct atl1c_adapter {
#define __AT_TESTING 0x0001
#define __AT_RESETTING 0x0002
#define __AT_DOWN 0x0003
u8 work_event;
#define ATL1C_WORK_EVENT_RESET 0x01
#define ATL1C_WORK_EVENT_LINK_CHANGE 0x02
u32 msg_enable;
bool have_msi;
@ -561,8 +569,7 @@ struct atl1c_adapter {
spinlock_t tx_lock;
atomic_t irq_sem;
struct work_struct reset_task;
struct work_struct link_chg_task;
struct work_struct common_task;
struct timer_list watchdog_timer;
struct timer_list phy_config_timer;

View file

@ -198,27 +198,12 @@ static void atl1c_phy_config(unsigned long data)
void atl1c_reinit_locked(struct atl1c_adapter *adapter)
{
WARN_ON(in_interrupt());
atl1c_down(adapter);
atl1c_up(adapter);
clear_bit(__AT_RESETTING, &adapter->flags);
}
static void atl1c_reset_task(struct work_struct *work)
{
struct atl1c_adapter *adapter;
struct net_device *netdev;
adapter = container_of(work, struct atl1c_adapter, reset_task);
netdev = adapter->netdev;
netif_device_detach(netdev);
atl1c_down(adapter);
atl1c_up(adapter);
netif_device_attach(netdev);
}
static void atl1c_check_link_status(struct atl1c_adapter *adapter)
{
struct atl1c_hw *hw = &adapter->hw;
@ -275,18 +260,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
}
}
/*
* atl1c_link_chg_task - deal with link change event Out of interrupt context
* @netdev: network interface device structure
*/
static void atl1c_link_chg_task(struct work_struct *work)
{
struct atl1c_adapter *adapter;
adapter = container_of(work, struct atl1c_adapter, link_chg_task);
atl1c_check_link_status(adapter);
}
static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@ -311,19 +284,39 @@ static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
adapter->link_speed = SPEED_0;
}
}
schedule_work(&adapter->link_chg_task);
adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE;
schedule_work(&adapter->common_task);
}
static void atl1c_common_task(struct work_struct *work)
{
struct atl1c_adapter *adapter;
struct net_device *netdev;
adapter = container_of(work, struct atl1c_adapter, common_task);
netdev = adapter->netdev;
if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
netif_device_detach(netdev);
atl1c_down(adapter);
atl1c_up(adapter);
netif_device_attach(netdev);
return;
}
if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE)
atl1c_check_link_status(adapter);
return;
}
static void atl1c_del_timer(struct atl1c_adapter *adapter)
{
del_timer_sync(&adapter->phy_config_timer);
}
static void atl1c_cancel_work(struct atl1c_adapter *adapter)
{
cancel_work_sync(&adapter->reset_task);
cancel_work_sync(&adapter->link_chg_task);
}
/*
* atl1c_tx_timeout - Respond to a Tx Hang
@ -334,7 +327,8 @@ static void atl1c_tx_timeout(struct net_device *netdev)
struct atl1c_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */
schedule_work(&adapter->reset_task);
adapter->work_event |= ATL1C_WORK_EVENT_RESET;
schedule_work(&adapter->common_task);
}
/*
@ -713,15 +707,21 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
static inline void atl1c_clean_buffer(struct pci_dev *pdev,
struct atl1c_buffer *buffer_info, int in_irq)
{
u16 pci_driection;
if (buffer_info->flags & ATL1C_BUFFER_FREE)
return;
if (buffer_info->dma) {
if (buffer_info->flags & ATL1C_PCIMAP_FROMDEVICE)
pci_driection = PCI_DMA_FROMDEVICE;
else
pci_driection = PCI_DMA_TODEVICE;
if (buffer_info->flags & ATL1C_PCIMAP_SINGLE)
pci_unmap_single(pdev, buffer_info->dma,
buffer_info->length, PCI_DMA_TODEVICE);
buffer_info->length, pci_driection);
else if (buffer_info->flags & ATL1C_PCIMAP_PAGE)
pci_unmap_page(pdev, buffer_info->dma,
buffer_info->length, PCI_DMA_TODEVICE);
buffer_info->length, pci_driection);
}
if (buffer_info->skb) {
if (in_irq)
@ -1533,7 +1533,8 @@ static irqreturn_t atl1c_intr(int irq, void *data)
/* reset MAC */
hw->intr_mask &= ~ISR_ERROR;
AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
schedule_work(&adapter->reset_task);
adapter->work_event |= ATL1C_WORK_EVENT_RESET;
schedule_work(&adapter->common_task);
break;
}
@ -1606,7 +1607,8 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid
buffer_info->dma = pci_map_single(pdev, vir_addr,
buffer_info->length,
PCI_DMA_FROMDEVICE);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
ATL1C_PCIMAP_FROMDEVICE);
rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
rfd_next_to_use = next_next;
if (++next_next == rfd_ring->count)
@ -1967,7 +1969,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
buffer_info->dma = pci_map_single(adapter->pdev,
skb->data, hdr_len, PCI_DMA_TODEVICE);
ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
ATL1C_PCIMAP_TODEVICE);
mapped_len += map_len;
use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
use_tpd->buffer_len = cpu_to_le16(buffer_info->length);
@ -1988,7 +1991,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
pci_map_single(adapter->pdev, skb->data + mapped_len,
buffer_info->length, PCI_DMA_TODEVICE);
ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE,
ATL1C_PCIMAP_TODEVICE);
use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
use_tpd->buffer_len = cpu_to_le16(buffer_info->length);
}
@ -2009,7 +2013,8 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter,
buffer_info->length,
PCI_DMA_TODEVICE);
ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE);
ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE,
ATL1C_PCIMAP_TODEVICE);
use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
use_tpd->buffer_len = cpu_to_le16(buffer_info->length);
}
@ -2198,8 +2203,7 @@ void atl1c_down(struct atl1c_adapter *adapter)
struct net_device *netdev = adapter->netdev;
atl1c_del_timer(adapter);
atl1c_cancel_work(adapter);
adapter->work_event = 0; /* clear all event */
/* signal that we're down so the interrupt handler does not
* reschedule our watchdog timer */
set_bit(__AT_DOWN, &adapter->flags);
@ -2599,8 +2603,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
atl1c_hw_set_mac_addr(&adapter->hw);
INIT_WORK(&adapter->reset_task, atl1c_reset_task);
INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task);
INIT_WORK(&adapter->common_task, atl1c_common_task);
adapter->work_event = 0;
err = register_netdev(netdev);
if (err) {
dev_err(&pdev->dev, "register netdevice failed\n");

View file

@ -1505,8 +1505,7 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
for (k = 0; k< ethaddr_bytes; k++) {
ppattern[offset + magicsync +
(j * ETH_ALEN) + k] = macaddr[k];
len++;
set_bit(len, (unsigned long *) pmask);
set_bit(len++, (unsigned long *) pmask);
}
}
return len - 1;

View file

@ -54,6 +54,15 @@ config CAN_MCP251X
---help---
Driver for the Microchip MCP251x SPI CAN controllers.
config CAN_BFIN
depends on CAN_DEV && (BF534 || BF536 || BF537 || BF538 || BF539 || BF54x)
tristate "Analog Devices Blackfin on-chip CAN"
---help---
Driver for the Analog Devices Blackfin on-chip CAN controllers
To compile this driver as a module, choose M here: the
module will be called bfin_can.
source "drivers/net/can/mscan/Kconfig"
source "drivers/net/can/sja1000/Kconfig"

View file

@ -14,5 +14,6 @@ obj-$(CONFIG_CAN_MSCAN) += mscan/
obj-$(CONFIG_CAN_AT91) += at91_can.o
obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
obj-$(CONFIG_CAN_BFIN) += bfin_can.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG

783
drivers/net/can/bfin_can.c Normal file
View file

@ -0,0 +1,783 @@
/*
* Blackfin On-Chip CAN Driver
*
* Copyright 2004-2009 Analog Devices Inc.
*
* Enter bugs at http://blackfin.uclinux.org/
*
* Licensed under the GPL-2 or later.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/platform_device.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <asm/portmux.h>
#define DRV_NAME "bfin_can"
#define BFIN_CAN_TIMEOUT 100
/*
* transmit and receive channels
*/
#define TRANSMIT_CHL 24
#define RECEIVE_STD_CHL 0
#define RECEIVE_EXT_CHL 4
#define RECEIVE_RTR_CHL 8
#define RECEIVE_EXT_RTR_CHL 12
#define MAX_CHL_NUMBER 32
/*
* bfin can registers layout
*/
struct bfin_can_mask_regs {
u16 aml;
u16 dummy1;
u16 amh;
u16 dummy2;
};
struct bfin_can_channel_regs {
u16 data[8];
u16 dlc;
u16 dummy1;
u16 tsv;
u16 dummy2;
u16 id0;
u16 dummy3;
u16 id1;
u16 dummy4;
};
struct bfin_can_regs {
/*
* global control and status registers
*/
u16 mc1; /* offset 0 */
u16 dummy1;
u16 md1; /* offset 4 */
u16 rsv1[13];
u16 mbtif1; /* offset 0x20 */
u16 dummy2;
u16 mbrif1; /* offset 0x24 */
u16 dummy3;
u16 mbim1; /* offset 0x28 */
u16 rsv2[11];
u16 mc2; /* offset 0x40 */
u16 dummy4;
u16 md2; /* offset 0x44 */
u16 dummy5;
u16 trs2; /* offset 0x48 */
u16 rsv3[11];
u16 mbtif2; /* offset 0x60 */
u16 dummy6;
u16 mbrif2; /* offset 0x64 */
u16 dummy7;
u16 mbim2; /* offset 0x68 */
u16 rsv4[11];
u16 clk; /* offset 0x80 */
u16 dummy8;
u16 timing; /* offset 0x84 */
u16 rsv5[3];
u16 status; /* offset 0x8c */
u16 dummy9;
u16 cec; /* offset 0x90 */
u16 dummy10;
u16 gis; /* offset 0x94 */
u16 dummy11;
u16 gim; /* offset 0x98 */
u16 rsv6[3];
u16 ctrl; /* offset 0xa0 */
u16 dummy12;
u16 intr; /* offset 0xa4 */
u16 rsv7[7];
u16 esr; /* offset 0xb4 */
u16 rsv8[37];
/*
* channel(mailbox) mask and message registers
*/
struct bfin_can_mask_regs msk[MAX_CHL_NUMBER]; /* offset 0x100 */
struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */
};
/*
* bfin can private data
*/
struct bfin_can_priv {
struct can_priv can; /* must be the first member */
struct net_device *dev;
void __iomem *membase;
int rx_irq;
int tx_irq;
int err_irq;
unsigned short *pin_list;
};
/*
* bfin can timing parameters
*/
static struct can_bittiming_const bfin_can_bittiming_const = {
.name = DRV_NAME,
.tseg1_min = 1,
.tseg1_max = 16,
.tseg2_min = 1,
.tseg2_max = 8,
.sjw_max = 4,
/*
* Although the BRP field can be set to any value, it is recommended
* that the value be greater than or equal to 4, as restrictions
* apply to the bit timing configuration when BRP is less than 4.
*/
.brp_min = 4,
.brp_max = 1024,
.brp_inc = 1,
};
static int bfin_can_set_bittiming(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
struct can_bittiming *bt = &priv->can.bittiming;
u16 clk, timing;
clk = bt->brp - 1;
timing = ((bt->sjw - 1) << 8) | (bt->prop_seg + bt->phase_seg1 - 1) |
((bt->phase_seg2 - 1) << 4);
/*
* If the SAM bit is set, the input signal is oversampled three times
* at the SCLK rate.
*/
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
timing |= SAM;
bfin_write16(&reg->clk, clk);
bfin_write16(&reg->timing, timing);
dev_info(dev->dev.parent, "setting CLOCK=0x%04x TIMING=0x%04x\n",
clk, timing);
return 0;
}
static void bfin_can_set_reset_mode(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
int timeout = BFIN_CAN_TIMEOUT;
int i;
/* disable interrupts */
bfin_write16(&reg->mbim1, 0);
bfin_write16(&reg->mbim2, 0);
bfin_write16(&reg->gim, 0);
/* reset can and enter configuration mode */
bfin_write16(&reg->ctrl, SRS | CCR);
SSYNC();
bfin_write16(&reg->ctrl, CCR);
SSYNC();
while (!(bfin_read16(&reg->ctrl) & CCA)) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
"fail to enter configuration mode\n");
BUG();
}
}
/*
* All mailbox configurations are marked as inactive
* by writing to CAN Mailbox Configuration Registers 1 and 2
* For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
*/
bfin_write16(&reg->mc1, 0);
bfin_write16(&reg->mc2, 0);
/* Set Mailbox Direction */
bfin_write16(&reg->md1, 0xFFFF); /* mailbox 1-16 are RX */
bfin_write16(&reg->md2, 0); /* mailbox 17-32 are TX */
/* RECEIVE_STD_CHL */
for (i = 0; i < 2; i++) {
bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
bfin_write16(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
bfin_write16(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
bfin_write16(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
}
/* RECEIVE_EXT_CHL */
for (i = 0; i < 2; i++) {
bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
bfin_write16(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
bfin_write16(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
bfin_write16(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
}
bfin_write16(&reg->mc2, BIT(TRANSMIT_CHL - 16));
bfin_write16(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
SSYNC();
priv->can.state = CAN_STATE_STOPPED;
}
static void bfin_can_set_normal_mode(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
int timeout = BFIN_CAN_TIMEOUT;
/*
* leave configuration mode
*/
bfin_write16(&reg->ctrl, bfin_read16(&reg->ctrl) & ~CCR);
while (bfin_read16(&reg->status) & CCA) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
"fail to leave configuration mode\n");
BUG();
}
}
/*
* clear _All_ tx and rx interrupts
*/
bfin_write16(&reg->mbtif1, 0xFFFF);
bfin_write16(&reg->mbtif2, 0xFFFF);
bfin_write16(&reg->mbrif1, 0xFFFF);
bfin_write16(&reg->mbrif2, 0xFFFF);
/*
* clear global interrupt status register
*/
bfin_write16(&reg->gis, 0x7FF); /* overwrites with '1' */
/*
* Initialize Interrupts
* - set bits in the mailbox interrupt mask register
* - global interrupt mask
*/
bfin_write16(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
bfin_write16(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
bfin_write16(&reg->gim, EPIM | BOIM | RMLIM);
SSYNC();
}
static void bfin_can_start(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
/* enter reset mode */
if (priv->can.state != CAN_STATE_STOPPED)
bfin_can_set_reset_mode(dev);
/* leave reset mode */
bfin_can_set_normal_mode(dev);
}
static int bfin_can_set_mode(struct net_device *dev, enum can_mode mode)
{
switch (mode) {
case CAN_MODE_START:
bfin_can_start(dev);
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
struct can_frame *cf = (struct can_frame *)skb->data;
u8 dlc = cf->can_dlc;
canid_t id = cf->can_id;
u8 *data = cf->data;
u16 val;
int i;
netif_stop_queue(dev);
/* fill id */
if (id & CAN_EFF_FLAG) {
bfin_write16(&reg->chl[TRANSMIT_CHL].id0, id);
if (id & CAN_RTR_FLAG)
writew(((id & 0x1FFF0000) >> 16) | IDE | AME | RTR,
&reg->chl[TRANSMIT_CHL].id1);
else
writew(((id & 0x1FFF0000) >> 16) | IDE | AME,
&reg->chl[TRANSMIT_CHL].id1);
} else {
if (id & CAN_RTR_FLAG)
writew((id << 2) | AME | RTR,
&reg->chl[TRANSMIT_CHL].id1);
else
bfin_write16(&reg->chl[TRANSMIT_CHL].id1,
(id << 2) | AME);
}
/* fill payload */
for (i = 0; i < 8; i += 2) {
val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
((6 - i) < dlc ? (data[6 - i] << 8) : 0);
bfin_write16(&reg->chl[TRANSMIT_CHL].data[i], val);
}
/* fill data length code */
bfin_write16(&reg->chl[TRANSMIT_CHL].dlc, dlc);
dev->trans_start = jiffies;
can_put_echo_skb(skb, dev, 0);
/* set transmit request */
bfin_write16(&reg->trs2, BIT(TRANSMIT_CHL - 16));
return 0;
}
static void bfin_can_rx(struct net_device *dev, u16 isrc)
{
struct bfin_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
struct bfin_can_regs __iomem *reg = priv->membase;
struct can_frame *cf;
struct sk_buff *skb;
int obj;
int i;
u16 val;
skb = alloc_can_skb(dev, &cf);
if (skb == NULL)
return;
/* get id */
if (isrc & BIT(RECEIVE_EXT_CHL)) {
/* extended frame format (EFF) */
cf->can_id = ((bfin_read16(&reg->chl[RECEIVE_EXT_CHL].id1)
& 0x1FFF) << 16)
+ bfin_read16(&reg->chl[RECEIVE_EXT_CHL].id0);
cf->can_id |= CAN_EFF_FLAG;
obj = RECEIVE_EXT_CHL;
} else {
/* standard frame format (SFF) */
cf->can_id = (bfin_read16(&reg->chl[RECEIVE_STD_CHL].id1)
& 0x1ffc) >> 2;
obj = RECEIVE_STD_CHL;
}
if (bfin_read16(&reg->chl[obj].id1) & RTR)
cf->can_id |= CAN_RTR_FLAG;
/* get data length code */
cf->can_dlc = bfin_read16(&reg->chl[obj].dlc);
/* get payload */
for (i = 0; i < 8; i += 2) {
val = bfin_read16(&reg->chl[obj].data[i]);
cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
}
netif_rx(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
}
static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
{
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
struct net_device_stats *stats = &dev->stats;
struct can_frame *cf;
struct sk_buff *skb;
enum can_state state = priv->can.state;
skb = alloc_can_err_skb(dev, &cf);
if (skb == NULL)
return -ENOMEM;
if (isrc & RMLIS) {
/* data overrun interrupt */
dev_dbg(dev->dev.parent, "data overrun interrupt\n");
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
stats->rx_over_errors++;
stats->rx_errors++;
}
if (isrc & BOIS) {
dev_dbg(dev->dev.parent, "bus-off mode interrupt\n");
state = CAN_STATE_BUS_OFF;
cf->can_id |= CAN_ERR_BUSOFF;
can_bus_off(dev);
}
if (isrc & EPIS) {
/* error passive interrupt */
dev_dbg(dev->dev.parent, "error passive interrupt\n");
state = CAN_STATE_ERROR_PASSIVE;
}
if ((isrc & EWTIS) || (isrc & EWRIS)) {
dev_dbg(dev->dev.parent,
"Error Warning Transmit/Receive Interrupt\n");
state = CAN_STATE_ERROR_WARNING;
}
if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
state == CAN_STATE_ERROR_PASSIVE)) {
u16 cec = bfin_read16(&reg->cec);
u8 rxerr = cec;
u8 txerr = cec >> 8;
cf->can_id |= CAN_ERR_CRTL;
if (state == CAN_STATE_ERROR_WARNING) {
priv->can.can_stats.error_warning++;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
} else {
priv->can.can_stats.error_passive++;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_PASSIVE :
CAN_ERR_CRTL_RX_PASSIVE;
}
}
if (status) {
priv->can.can_stats.bus_error++;
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
if (status & BEF)
cf->data[2] |= CAN_ERR_PROT_BIT;
else if (status & FER)
cf->data[2] |= CAN_ERR_PROT_FORM;
else if (status & SER)
cf->data[2] |= CAN_ERR_PROT_STUFF;
else
cf->data[2] |= CAN_ERR_PROT_UNSPEC;
}
priv->can.state = state;
netif_rx(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
return 0;
}
irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
struct net_device_stats *stats = &dev->stats;
u16 status, isrc;
if ((irq == priv->tx_irq) && bfin_read16(&reg->mbtif2)) {
/* transmission complete interrupt */
bfin_write16(&reg->mbtif2, 0xFFFF);
stats->tx_packets++;
stats->tx_bytes += bfin_read16(&reg->chl[TRANSMIT_CHL].dlc);
can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
} else if ((irq == priv->rx_irq) && bfin_read16(&reg->mbrif1)) {
/* receive interrupt */
isrc = bfin_read16(&reg->mbrif1);
bfin_write16(&reg->mbrif1, 0xFFFF);
bfin_can_rx(dev, isrc);
} else if ((irq == priv->err_irq) && bfin_read16(&reg->gis)) {
/* error interrupt */
isrc = bfin_read16(&reg->gis);
status = bfin_read16(&reg->esr);
bfin_write16(&reg->gis, 0x7FF);
bfin_can_err(dev, isrc, status);
} else {
return IRQ_NONE;
}
return IRQ_HANDLED;
}
static int bfin_can_open(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
int err;
/* set chip into reset mode */
bfin_can_set_reset_mode(dev);
/* common open */
err = open_candev(dev);
if (err)
goto exit_open;
/* register interrupt handler */
err = request_irq(priv->rx_irq, &bfin_can_interrupt, 0,
"bfin-can-rx", dev);
if (err)
goto exit_rx_irq;
err = request_irq(priv->tx_irq, &bfin_can_interrupt, 0,
"bfin-can-tx", dev);
if (err)
goto exit_tx_irq;
err = request_irq(priv->err_irq, &bfin_can_interrupt, 0,
"bfin-can-err", dev);
if (err)
goto exit_err_irq;
bfin_can_start(dev);
netif_start_queue(dev);
return 0;
exit_err_irq:
free_irq(priv->tx_irq, dev);
exit_tx_irq:
free_irq(priv->rx_irq, dev);
exit_rx_irq:
close_candev(dev);
exit_open:
return err;
}
static int bfin_can_close(struct net_device *dev)
{
struct bfin_can_priv *priv = netdev_priv(dev);
netif_stop_queue(dev);
bfin_can_set_reset_mode(dev);
close_candev(dev);
free_irq(priv->rx_irq, dev);
free_irq(priv->tx_irq, dev);
free_irq(priv->err_irq, dev);
return 0;
}
struct net_device *alloc_bfin_candev(void)
{
struct net_device *dev;
struct bfin_can_priv *priv;
dev = alloc_candev(sizeof(*priv));
if (!dev)
return NULL;
priv = netdev_priv(dev);
priv->dev = dev;
priv->can.bittiming_const = &bfin_can_bittiming_const;
priv->can.do_set_bittiming = bfin_can_set_bittiming;
priv->can.do_set_mode = bfin_can_set_mode;
return dev;
}
static const struct net_device_ops bfin_can_netdev_ops = {
.ndo_open = bfin_can_open,
.ndo_stop = bfin_can_close,
.ndo_start_xmit = bfin_can_start_xmit,
};
static int __devinit bfin_can_probe(struct platform_device *pdev)
{
int err;
struct net_device *dev;
struct bfin_can_priv *priv;
struct resource *res_mem, *rx_irq, *tx_irq, *err_irq;
unsigned short *pdata;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "No platform data provided!\n");
err = -EINVAL;
goto exit;
}
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
tx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
err_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
if (!res_mem || !rx_irq || !tx_irq || !err_irq) {
err = -EINVAL;
goto exit;
}
if (!request_mem_region(res_mem->start, resource_size(res_mem),
dev_name(&pdev->dev))) {
err = -EBUSY;
goto exit;
}
/* request peripheral pins */
err = peripheral_request_list(pdata, dev_name(&pdev->dev));
if (err)
goto exit_mem_release;
dev = alloc_bfin_candev();
if (!dev) {
err = -ENOMEM;
goto exit_peri_pin_free;
}
priv = netdev_priv(dev);
priv->membase = (void __iomem *)res_mem->start;
priv->rx_irq = rx_irq->start;
priv->tx_irq = tx_irq->start;
priv->err_irq = err_irq->start;
priv->pin_list = pdata;
priv->can.clock.freq = get_sclk();
dev_set_drvdata(&pdev->dev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
dev->flags |= IFF_ECHO; /* we support local echo */
dev->netdev_ops = &bfin_can_netdev_ops;
bfin_can_set_reset_mode(dev);
err = register_candev(dev);
if (err) {
dev_err(&pdev->dev, "registering failed (err=%d)\n", err);
goto exit_candev_free;
}
dev_info(&pdev->dev,
"%s device registered"
"(&reg_base=%p, rx_irq=%d, tx_irq=%d, err_irq=%d, sclk=%d)\n",
DRV_NAME, (void *)priv->membase, priv->rx_irq,
priv->tx_irq, priv->err_irq, priv->can.clock.freq);
return 0;
exit_candev_free:
free_candev(dev);
exit_peri_pin_free:
peripheral_free_list(pdata);
exit_mem_release:
release_mem_region(res_mem->start, resource_size(res_mem));
exit:
return err;
}
static int __devexit bfin_can_remove(struct platform_device *pdev)
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct bfin_can_priv *priv = netdev_priv(dev);
struct resource *res;
bfin_can_set_reset_mode(dev);
unregister_candev(dev);
dev_set_drvdata(&pdev->dev, NULL);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
peripheral_free_list(priv->pin_list);
free_candev(dev);
return 0;
}
#ifdef CONFIG_PM
static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
int timeout = BFIN_CAN_TIMEOUT;
if (netif_running(dev)) {
/* enter sleep mode */
bfin_write16(&reg->ctrl, bfin_read16(&reg->ctrl) | SMR);
SSYNC();
while (!(bfin_read16(&reg->intr) & SMACK)) {
udelay(10);
if (--timeout == 0) {
dev_err(dev->dev.parent,
"fail to enter sleep mode\n");
BUG();
}
}
}
return 0;
}
static int bfin_can_resume(struct platform_device *pdev)
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
if (netif_running(dev)) {
/* leave sleep mode */
bfin_write16(&reg->intr, 0);
SSYNC();
}
return 0;
}
#else
#define bfin_can_suspend NULL
#define bfin_can_resume NULL
#endif /* CONFIG_PM */
static struct platform_driver bfin_can_driver = {
.probe = bfin_can_probe,
.remove = __devexit_p(bfin_can_remove),
.suspend = bfin_can_suspend,
.resume = bfin_can_resume,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
};
static int __init bfin_can_init(void)
{
return platform_driver_register(&bfin_can_driver);
}
module_init(bfin_can_init);
static void __exit bfin_can_exit(void)
{
platform_driver_unregister(&bfin_can_driver);
}
module_exit(bfin_can_exit);
MODULE_AUTHOR("Barry Song <[email protected]>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Blackfin on-chip CAN netdevice driver");

View file

@ -1104,6 +1104,8 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
cp->bnx2x_status_blk = cp->status_blk;
cp->bnx2x_def_status_blk = cp->ethdev->irq_arr[1].status_blk;
memset(cp->bnx2x_status_blk, 0, sizeof(struct host_status_block));
cp->l2_rx_ring_size = 15;
ret = cnic_alloc_l2_rings(dev, 4);
@ -4183,6 +4185,12 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_HALT,
BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data);
msleep(10);
memset(&l5_data, 0, sizeof(l5_data));
cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL,
BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE |
(1 << SPE_HDR_COMMON_RAMROD_SHIFT), &l5_data);
msleep(10);
}
}
@ -4289,6 +4297,9 @@ static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
offsetof(struct cstorm_status_block_c,
index_values[HC_INDEX_C_ISCSI_EQ_CONS]),
0);
CNIC_WR(dev, BAR_CSTRORM_INTMEM +
CSTORM_ISCSI_EQ_CONS_OFFSET(cp->func, 0), 0);
CNIC_WR16(dev, cp->kcq_io_addr, 0);
cnic_free_resc(dev);
}

View file

@ -2860,6 +2860,7 @@ static int t3_reenable_adapter(struct adapter *adapter)
}
pci_set_master(adapter->pdev);
pci_restore_state(adapter->pdev);
pci_save_state(adapter->pdev);
/* Free sge resources */
t3_free_sge_resources(adapter);

View file

@ -74,7 +74,7 @@
#define E1000_WUS_BC E1000_WUFC_BC
/* Extended Device Control */
#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */

View file

@ -46,6 +46,9 @@
#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000
#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000
#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C
#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004
#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000
@ -462,28 +465,36 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
return ret_val;
}
/*
* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
* transaction. So we wait 200us after each MDI command...
*/
udelay(200);
if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) {
/*
* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
* transaction. So we wait 200us after each MDI command...
*/
udelay(200);
/* ...and verify the command was successful. */
ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
/* ...and verify the command was successful. */
ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
ret_val = -E1000_ERR_PHY;
e1000_release_phy_80003es2lan(hw);
return ret_val;
if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
ret_val = -E1000_ERR_PHY;
e1000_release_phy_80003es2lan(hw);
return ret_val;
}
udelay(200);
ret_val = e1000e_read_phy_reg_mdic(hw,
MAX_PHY_REG_ADDRESS & offset,
data);
udelay(200);
} else {
ret_val = e1000e_read_phy_reg_mdic(hw,
MAX_PHY_REG_ADDRESS & offset,
data);
}
udelay(200);
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
udelay(200);
e1000_release_phy_80003es2lan(hw);
return ret_val;
@ -526,28 +537,35 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
return ret_val;
}
if (hw->dev_spec.e80003es2lan.mdic_wa_enable == true) {
/*
* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
* transaction. So we wait 200us after each MDI command...
*/
udelay(200);
/*
* The "ready" bit in the MDIC register may be incorrectly set
* before the device has completed the "Page Select" MDI
* transaction. So we wait 200us after each MDI command...
*/
udelay(200);
/* ...and verify the command was successful. */
ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
/* ...and verify the command was successful. */
ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp);
if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
e1000_release_phy_80003es2lan(hw);
return -E1000_ERR_PHY;
}
if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
e1000_release_phy_80003es2lan(hw);
return -E1000_ERR_PHY;
udelay(200);
ret_val = e1000e_write_phy_reg_mdic(hw,
MAX_PHY_REG_ADDRESS & offset,
data);
udelay(200);
} else {
ret_val = e1000e_write_phy_reg_mdic(hw,
MAX_PHY_REG_ADDRESS & offset,
data);
}
udelay(200);
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
udelay(200);
e1000_release_phy_80003es2lan(hw);
return ret_val;
@ -866,6 +884,19 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
reg_data &= ~0x00100000;
E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
/* default to true to enable the MDIC W/A */
hw->dev_spec.e80003es2lan.mdic_wa_enable = true;
ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET >>
E1000_KMRNCTRLSTA_OFFSET_SHIFT,
&i);
if (!ret_val) {
if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
hw->dev_spec.e80003es2lan.mdic_wa_enable = false;
}
/*
* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link

View file

@ -302,6 +302,8 @@ enum e1e_registers {
#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16
#define E1000_KMRNCTRLSTA_REN 0x00200000
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E
@ -898,6 +900,10 @@ struct e1000_dev_spec_82571 {
u32 smb_counter;
};
struct e1000_dev_spec_80003es2lan {
bool mdic_wa_enable;
};
struct e1000_shadow_ram {
u16 value;
bool modified;
@ -926,6 +932,7 @@ struct e1000_hw {
union {
struct e1000_dev_spec_82571 e82571;
struct e1000_dev_spec_80003es2lan e80003es2lan;
struct e1000_dev_spec_ich8lan ich8lan;
} dev_spec;
};

View file

@ -2755,14 +2755,16 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
* and increase the max iterations when polling the phy;
* this fixes erroneous timeouts at 10Mbps.
*/
ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_TIMEOUTS, 0xFFFF);
if (ret_val)
return ret_val;
ret_val = e1000e_read_kmrn_reg(hw, GG82563_REG(0x34, 9), &reg_data);
ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
&reg_data);
if (ret_val)
return ret_val;
reg_data |= 0x3F;
ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
reg_data);
if (ret_val)
return ret_val;

View file

@ -4541,7 +4541,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
e1000_media_type_internal_serdes) {
/* keep the laser running in D3 */
ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
ew32(CTRL_EXT, ctrl_ext);
}

View file

@ -85,11 +85,15 @@ MODULE_PARM_DESC(debug, "debugging messages level");
static void mpc52xx_fec_tx_timeout(struct net_device *dev)
{
struct mpc52xx_fec_priv *priv = netdev_priv(dev);
unsigned long flags;
dev_warn(&dev->dev, "transmit timed out\n");
spin_lock_irqsave(&priv->lock, flags);
mpc52xx_fec_reset(dev);
dev->stats.tx_errors++;
spin_unlock_irqrestore(&priv->lock, flags);
netif_wake_queue(dev);
}
@ -135,28 +139,32 @@ static void mpc52xx_fec_free_rx_buffers(struct net_device *dev, struct bcom_task
}
}
static void
mpc52xx_fec_rx_submit(struct net_device *dev, struct sk_buff *rskb)
{
struct mpc52xx_fec_priv *priv = netdev_priv(dev);
struct bcom_fec_bd *bd;
bd = (struct bcom_fec_bd *) bcom_prepare_next_buffer(priv->rx_dmatsk);
bd->status = FEC_RX_BUFFER_SIZE;
bd->skb_pa = dma_map_single(dev->dev.parent, rskb->data,
FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
bcom_submit_next_buffer(priv->rx_dmatsk, rskb);
}
static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task *rxtsk)
{
while (!bcom_queue_full(rxtsk)) {
struct sk_buff *skb;
struct bcom_fec_bd *bd;
struct sk_buff *skb;
while (!bcom_queue_full(rxtsk)) {
skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
if (skb == NULL)
if (!skb)
return -EAGAIN;
/* zero out the initial receive buffers to aid debugging */
memset(skb->data, 0, FEC_RX_BUFFER_SIZE);
bd = (struct bcom_fec_bd *)bcom_prepare_next_buffer(rxtsk);
bd->status = FEC_RX_BUFFER_SIZE;
bd->skb_pa = dma_map_single(dev->dev.parent, skb->data,
FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
bcom_submit_next_buffer(rxtsk, skb);
mpc52xx_fec_rx_submit(dev, skb);
}
return 0;
}
@ -328,13 +336,12 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
DMA_TO_DEVICE);
bcom_submit_next_buffer(priv->tx_dmatsk, skb);
spin_unlock_irqrestore(&priv->lock, flags);
if (bcom_queue_full(priv->tx_dmatsk)) {
netif_stop_queue(dev);
}
spin_unlock_irqrestore(&priv->lock, flags);
return NETDEV_TX_OK;
}
@ -359,9 +366,9 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct mpc52xx_fec_priv *priv = netdev_priv(dev);
unsigned long flags;
spin_lock(&priv->lock);
spin_lock_irqsave(&priv->lock, flags);
while (bcom_buffer_done(priv->tx_dmatsk)) {
struct sk_buff *skb;
struct bcom_fec_bd *bd;
@ -372,11 +379,10 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
dev_kfree_skb_irq(skb);
}
spin_unlock_irqrestore(&priv->lock, flags);
netif_wake_queue(dev);
spin_unlock(&priv->lock);
return IRQ_HANDLED;
}
@ -384,67 +390,60 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct mpc52xx_fec_priv *priv = netdev_priv(dev);
struct sk_buff *rskb; /* received sk_buff */
struct sk_buff *skb; /* new sk_buff to enqueue in its place */
struct bcom_fec_bd *bd;
u32 status, physaddr;
int length;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
while (bcom_buffer_done(priv->rx_dmatsk)) {
struct sk_buff *skb;
struct sk_buff *rskb;
struct bcom_fec_bd *bd;
u32 status;
rskb = bcom_retrieve_buffer(priv->rx_dmatsk, &status,
(struct bcom_bd **)&bd);
dma_unmap_single(dev->dev.parent, bd->skb_pa, rskb->len,
DMA_FROM_DEVICE);
(struct bcom_bd **)&bd);
physaddr = bd->skb_pa;
/* Test for errors in received frame */
if (status & BCOM_FEC_RX_BD_ERRORS) {
/* Drop packet and reuse the buffer */
bd = (struct bcom_fec_bd *)
bcom_prepare_next_buffer(priv->rx_dmatsk);
bd->status = FEC_RX_BUFFER_SIZE;
bd->skb_pa = dma_map_single(dev->dev.parent,
rskb->data,
FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
bcom_submit_next_buffer(priv->rx_dmatsk, rskb);
mpc52xx_fec_rx_submit(dev, rskb);
dev->stats.rx_dropped++;
continue;
}
/* skbs are allocated on open, so now we allocate a new one,
* and remove the old (with the packet) */
skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
if (skb) {
/* Process the received skb */
int length = status & BCOM_FEC_RX_BD_LEN_MASK;
skb_put(rskb, length - 4); /* length without CRC32 */
rskb->dev = dev;
rskb->protocol = eth_type_trans(rskb, dev);
netif_rx(rskb);
} else {
if (!skb) {
/* Can't get a new one : reuse the same & drop pkt */
dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n");
dev_notice(&dev->dev, "Low memory - dropped packet.\n");
mpc52xx_fec_rx_submit(dev, rskb);
dev->stats.rx_dropped++;
skb = rskb;
continue;
}
bd = (struct bcom_fec_bd *)
bcom_prepare_next_buffer(priv->rx_dmatsk);
/* Enqueue the new sk_buff back on the hardware */
mpc52xx_fec_rx_submit(dev, skb);
bd->status = FEC_RX_BUFFER_SIZE;
bd->skb_pa = dma_map_single(dev->dev.parent, skb->data,
FEC_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
/* Process the received skb - Drop the spin lock while
* calling into the network stack */
spin_unlock_irqrestore(&priv->lock, flags);
bcom_submit_next_buffer(priv->rx_dmatsk, skb);
dma_unmap_single(dev->dev.parent, physaddr, rskb->len,
DMA_FROM_DEVICE);
length = status & BCOM_FEC_RX_BD_LEN_MASK;
skb_put(rskb, length - 4); /* length without CRC32 */
rskb->dev = dev;
rskb->protocol = eth_type_trans(rskb, dev);
netif_rx(rskb);
spin_lock_irqsave(&priv->lock, flags);
}
spin_unlock_irqrestore(&priv->lock, flags);
return IRQ_HANDLED;
}
@ -454,6 +453,7 @@ static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id)
struct mpc52xx_fec_priv *priv = netdev_priv(dev);
struct mpc52xx_fec __iomem *fec = priv->fec;
u32 ievent;
unsigned long flags;
ievent = in_be32(&fec->ievent);
@ -471,9 +471,10 @@ static irqreturn_t mpc52xx_fec_interrupt(int irq, void *dev_id)
if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
dev_warn(&dev->dev, "FEC_IEVENT_XFIFO_ERROR\n");
spin_lock_irqsave(&priv->lock, flags);
mpc52xx_fec_reset(dev);
spin_unlock_irqrestore(&priv->lock, flags);
netif_wake_queue(dev);
return IRQ_HANDLED;
}
@ -768,6 +769,8 @@ static void mpc52xx_fec_reset(struct net_device *dev)
bcom_enable(priv->tx_dmatsk);
mpc52xx_fec_start(dev);
netif_wake_queue(dev);
}

View file

@ -2644,6 +2644,7 @@ static void gfar_netpoll(struct net_device *dev)
gfar_interrupt(priv->gfargrp[i].interruptTransmit,
&priv->gfargrp[i]);
enable_irq(priv->gfargrp[i].interruptTransmit);
}
}
}
#endif

View file

@ -342,6 +342,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82599_KX4:
case IXGBE_DEV_ID_82599_KX4_MEZZ:
case IXGBE_DEV_ID_82599_COMBO_BACKPLANE:
case IXGBE_DEV_ID_82599_KR:
case IXGBE_DEV_ID_82599_XAUI_LOM:
/* Default device ID is mezzanine card KX/KX4 */
media_type = ixgbe_media_type_backplane;

View file

@ -990,6 +990,7 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
char *p = NULL;
ixgbe_update_stats(adapter);
dev_get_stats(netdev);
for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) {
switch (ixgbe_gstrings_stats[i].type) {
case NETDEV_STATS:

View file

@ -96,6 +96,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KR),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM),
@ -435,8 +437,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
tx_ring->total_packets += total_packets;
tx_ring->stats.packets += total_packets;
tx_ring->stats.bytes += total_bytes;
netdev->stats.tx_bytes += total_bytes;
netdev->stats.tx_packets += total_packets;
return (count < tx_ring->work_limit);
}
@ -5327,6 +5327,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_ring *tx_ring;
struct netdev_queue *txq;
unsigned int first;
unsigned int tx_flags = 0;
u8 hdr_len = 0;
@ -5424,6 +5425,9 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
tx_ring->atr_count = 0;
}
}
txq = netdev_get_tx_queue(netdev, tx_ring->queue_index);
txq->tx_bytes += skb->len;
txq->tx_packets++;
ixgbe_tx_queue(adapter, tx_ring, tx_flags, count, skb->len,
hdr_len);
ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED);
@ -5437,19 +5441,6 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
return NETDEV_TX_OK;
}
/**
* ixgbe_get_stats - Get System Network Statistics
* @netdev: network interface device structure
*
* Returns the address of the device statistics structure.
* The statistics are actually updated from the timer callback.
**/
static struct net_device_stats *ixgbe_get_stats(struct net_device *netdev)
{
/* only return the current stats */
return &netdev->stats;
}
/**
* ixgbe_set_mac - Change the Ethernet Address of the NIC
* @netdev: network interface device structure
@ -5580,7 +5571,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_stop = ixgbe_close,
.ndo_start_xmit = ixgbe_xmit_frame,
.ndo_select_queue = ixgbe_select_queue,
.ndo_get_stats = ixgbe_get_stats,
.ndo_set_rx_mode = ixgbe_set_rx_mode,
.ndo_set_multicast_list = ixgbe_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,

View file

@ -50,6 +50,7 @@
#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
#define IXGBE_DEV_ID_82599_KX4 0x10F7
#define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514
#define IXGBE_DEV_ID_82599_KR 0x1517
#define IXGBE_DEV_ID_82599_CX4 0x10F9
#define IXGBE_DEV_ID_82599_SFP 0x10FB
#define IXGBE_DEV_ID_82599_SFP_EM 0x1507

View file

@ -1827,6 +1827,9 @@ static int mv643xx_eth_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *sa = addr;
if (!is_valid_ether_addr(sa->sa_data))
return -EINVAL;
memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
netif_addr_lock_bh(dev);

View file

@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
#define MYRI10GE_VERSION_STR "1.5.1-1.451"
#define MYRI10GE_VERSION_STR "1.5.1-1.453"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: [email protected]");
@ -347,7 +347,7 @@ static int myri10ge_max_slices = 1;
module_param(myri10ge_max_slices, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_max_slices, "Max tx/rx queues");
static int myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_PORT;
static int myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT;
module_param(myri10ge_rss_hash, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_rss_hash, "Type of RSS hashing to do");

View file

@ -619,17 +619,20 @@ nx_set_product_offs(struct netxen_adapter *adapter)
uint32_t i;
__le32 entries;
int mn_present = (NX_IS_REVISION_P2(adapter->ahw.revision_id)) ?
1 : netxen_p3_has_mn(adapter);
ptab_descr = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_PRODUCT_TBL);
if (ptab_descr == NULL)
return -1;
entries = cpu_to_le32(ptab_descr->num_entries);
nomn:
for (i = 0; i < entries; i++) {
__le32 flags, file_chiprev, offs;
u8 chiprev = adapter->ahw.revision_id;
int mn_present = netxen_p3_has_mn(adapter);
uint32_t flagbit;
offs = cpu_to_le32(ptab_descr->findex) +
@ -647,6 +650,11 @@ nx_set_product_offs(struct netxen_adapter *adapter)
}
}
if (mn_present && NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
mn_present = 0;
goto nomn;
}
return -1;
}
@ -1021,6 +1029,10 @@ netxen_p3_has_mn(struct netxen_adapter *adapter)
u32 capability, flashed_ver;
capability = 0;
/* NX2031 always had MN */
if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
return 1;
netxen_rom_fast_read(adapter,
NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);

View file

@ -946,8 +946,9 @@ netxen_nic_init_coalesce_defaults(struct netxen_adapter *adapter)
NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS;
}
/* with rtnl_lock */
static int
netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
__netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
{
int err;
@ -988,14 +989,32 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
return 0;
}
/* Usage: During resume and firmware recovery module.*/
static inline int
netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
{
int err = 0;
rtnl_lock();
if (netif_running(netdev))
err = __netxen_nic_up(adapter, netdev);
rtnl_unlock();
return err;
}
/* with rtnl_lock */
static void
netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
__netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
{
if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
return;
clear_bit(__NX_DEV_UP, &adapter->state);
if (!test_and_clear_bit(__NX_DEV_UP, &adapter->state))
return;
smp_mb();
spin_lock(&adapter->tx_clean_lock);
netif_carrier_off(netdev);
netif_tx_disable(netdev);
@ -1014,6 +1033,17 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
spin_unlock(&adapter->tx_clean_lock);
}
/* Usage: During suspend and firmware recovery module */
static inline void
netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
{
rtnl_lock();
if (netif_running(netdev))
__netxen_nic_down(adapter, netdev);
rtnl_unlock();
}
static int
netxen_nic_attach(struct netxen_adapter *adapter)
@ -1122,14 +1152,14 @@ netxen_nic_reset_context(struct netxen_adapter *adapter)
netif_device_detach(netdev);
if (netif_running(netdev))
netxen_nic_down(adapter, netdev);
__netxen_nic_down(adapter, netdev);
netxen_nic_detach(adapter);
if (netif_running(netdev)) {
err = netxen_nic_attach(adapter);
if (!err)
err = netxen_nic_up(adapter, netdev);
err = __netxen_nic_up(adapter, netdev);
if (err)
goto done;
@ -1499,7 +1529,7 @@ static int netxen_nic_open(struct net_device *netdev)
if (err)
return err;
err = netxen_nic_up(adapter, netdev);
err = __netxen_nic_up(adapter, netdev);
if (err)
goto err_out;
@ -1519,7 +1549,7 @@ static int netxen_nic_close(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
netxen_nic_down(adapter, netdev);
__netxen_nic_down(adapter, netdev);
return 0;
}
@ -2025,7 +2055,7 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
if ((work_done < budget) && tx_complete) {
napi_complete(&sds_ring->napi);
if (netif_running(adapter->netdev))
if (test_bit(__NX_DEV_UP, &adapter->state))
netxen_nic_enable_int(sds_ring);
}
@ -2210,8 +2240,7 @@ netxen_detach_work(struct work_struct *work)
netif_device_detach(netdev);
if (netif_running(netdev))
netxen_nic_down(adapter, netdev);
netxen_nic_down(adapter, netdev);
netxen_nic_detach(adapter);

View file

@ -2152,7 +2152,9 @@ static void sky2_qlink_intr(struct sky2_hw *hw)
/* reset PHY Link Detect */
phy = sky2_pci_read16(hw, PSM_CONFIG_REG4);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1);
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
sky2_link_up(sky2);
}
@ -2968,8 +2970,13 @@ static int __devinit sky2_init(struct sky2_hw *hw)
break;
case CHIP_ID_YUKON_UL_2:
hw->flags = SKY2_HW_GIGABIT
| SKY2_HW_ADV_POWER_CTL;
break;
case CHIP_ID_YUKON_OPT:
hw->flags = SKY2_HW_GIGABIT
| SKY2_HW_NEW_LE
| SKY2_HW_ADV_POWER_CTL;
break;
@ -3077,6 +3084,7 @@ static void sky2_reset(struct sky2_hw *hw)
reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE;
/* reset PHY Link Detect */
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
sky2_pci_write16(hw, PSM_CONFIG_REG4,
reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT);
sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
@ -3094,6 +3102,7 @@ static void sky2_reset(struct sky2_hw *hw)
/* restore the PCIe Link Control register */
sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg);
}
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
/* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16));

View file

@ -534,9 +534,9 @@ static inline void smc_rcv(struct net_device *dev)
#define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags)
#define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags)
#else
#define smc_special_trylock(lock, flags) (1)
#define smc_special_lock(lock, flags) do { } while (0)
#define smc_special_unlock(lock, flags) do { } while (0)
#define smc_special_trylock(lock, flags) (flags == flags)
#define smc_special_lock(lock, flags) do { flags = 0; } while (0)
#define smc_special_unlock(lock, flags) do { flags = 0; } while (0)
#endif
/*
@ -2387,7 +2387,7 @@ static int smc_drv_resume(struct device *dev)
if (ndev) {
struct smc_local *lp = netdev_priv(ndev);
smc_enable_device(dev);
smc_enable_device(pdev);
if (netif_running(ndev)) {
smc_reset(ndev);
smc_enable(ndev);

View file

@ -97,6 +97,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
int ret;
u16 val;
u32 cksum, offset;
/*
* Read values from EEPROM and store them in the capability structure
@ -111,7 +112,6 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
return 0;
#ifdef notyet
/*
* Validate the checksum of the EEPROM date. There are some
* devices with invalid EEPROMs.
@ -124,7 +124,6 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
return -EIO;
}
#endif
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
ee_ant_gain);

View file

@ -79,6 +79,8 @@ static const struct pci_device_id ath5k_led_devices[] = {
{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) },
/* IBM-specific AR5212 (all others) */
{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) },
/* Dell Vostro A860 ([email protected]) */
{ ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0112), ATH_LED(3, 0) },
{ }
};

View file

@ -2078,7 +2078,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
&txq->axq_q, lastbf->list.prev);
txq->axq_depth--;
txok = (ds->ds_txstat.ts_status == 0);
txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT);
txq->axq_tx_inprogress = false;
spin_unlock_bh(&txq->axq_lock);

View file

@ -1784,7 +1784,10 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
dma_reason[0], dma_reason[1],
dma_reason[2], dma_reason[3],
dma_reason[4], dma_reason[5]);
b43_controller_restart(dev, "DMA error");
b43err(dev->wl, "This device does not support DMA "
"on your system. Please use PIO instead.\n");
b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in "
"your kernel configuration.\n");
return;
}
if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {

View file

@ -1353,7 +1353,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
if (priv->stations[sta_id].tid[tid].agg.state ==
IWL_EMPTYING_HW_QUEUE_ADDBA) {
IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid);
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
return 0;
}

View file

@ -84,7 +84,8 @@ struct rxd_ops {
int rxd_size;
void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status);
int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status,
__le16 *qos);
};
struct mwl8k_device_info {
@ -184,7 +185,7 @@ struct mwl8k_priv {
/* PHY parameters */
struct ieee80211_supported_band band;
struct ieee80211_channel channels[14];
struct ieee80211_rate rates[13];
struct ieee80211_rate rates[14];
bool radio_on;
bool radio_short_preamble;
@ -220,15 +221,6 @@ struct mwl8k_vif {
u8 bssid[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
/*
* Subset of supported legacy rates.
* Intersection of AP and STA supported rates.
*/
struct ieee80211_rate legacy_rates[13];
/* number of supported legacy rates */
u8 legacy_nrates;
/* Index into station database.Returned by update_sta_db call */
u8 peer_id;
@ -266,6 +258,11 @@ static const struct ieee80211_rate mwl8k_rates[] = {
{ .bitrate = 360, .hw_value = 72, },
{ .bitrate = 480, .hw_value = 96, },
{ .bitrate = 540, .hw_value = 108, },
{ .bitrate = 720, .hw_value = 144, },
};
static const u8 mwl8k_rateids[12] = {
2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108,
};
/* Set or get info from Firmware */
@ -574,7 +571,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
"helper image\n", pci_name(priv->pdev));
return rc;
}
msleep(1);
msleep(5);
rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
} else {
@ -591,9 +588,8 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR);
else
iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
msleep(1);
loops = 200000;
loops = 500000;
do {
u32 ready_code;
@ -633,9 +629,6 @@ struct ewc_ht_info {
/* Peer Entry flags - used to define the type of the peer node */
#define MWL8K_PEER_TYPE_ACCESSPOINT 2
#define MWL8K_IEEE_LEGACY_DATA_RATES 13
#define MWL8K_MCS_BITMAP_SIZE 16
struct peer_capability_info {
/* Peer type - AP vs. STA. */
__u8 peer_type;
@ -652,10 +645,10 @@ struct peer_capability_info {
struct ewc_ht_info ewc_info;
/* Legacy rate table. Intersection of our rates and peer rates. */
__u8 legacy_rates[MWL8K_IEEE_LEGACY_DATA_RATES];
__u8 legacy_rates[12];
/* HT rate table. Intersection of our rates and peer rates. */
__u8 ht_rates[MWL8K_MCS_BITMAP_SIZE];
__u8 ht_rates[16];
__u8 pad[16];
/* If set, interoperability mode, no proprietary extensions. */
@ -706,55 +699,64 @@ static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len)
struct mwl8k_dma_data {
__le16 fwlen;
struct ieee80211_hdr wh;
char data[0];
} __attribute__((packed));
/* Routines to add/remove DMA header from skb. */
static inline void mwl8k_remove_dma_header(struct sk_buff *skb)
static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos)
{
struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data;
void *dst, *src = &tr->wh;
int hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
u16 space = sizeof(struct mwl8k_dma_data) - hdrlen;
struct mwl8k_dma_data *tr;
int hdrlen;
dst = (void *)tr + space;
if (dst != src) {
memmove(dst, src, hdrlen);
skb_pull(skb, space);
tr = (struct mwl8k_dma_data *)skb->data;
hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
if (hdrlen != sizeof(tr->wh)) {
if (ieee80211_is_data_qos(tr->wh.frame_control)) {
memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2);
*((__le16 *)(tr->data - 2)) = qos;
} else {
memmove(tr->data - hdrlen, &tr->wh, hdrlen);
}
}
if (hdrlen != sizeof(*tr))
skb_pull(skb, sizeof(*tr) - hdrlen);
}
static inline void mwl8k_add_dma_header(struct sk_buff *skb)
{
struct ieee80211_hdr *wh;
u32 hdrlen, pktlen;
int hdrlen;
struct mwl8k_dma_data *tr;
wh = (struct ieee80211_hdr *)skb->data;
hdrlen = ieee80211_hdrlen(wh->frame_control);
pktlen = skb->len;
/*
* Copy up/down the 802.11 header; the firmware requires
* we present a 2-byte payload length followed by a
* 4-address header (w/o QoS), followed (optionally) by
* any WEP/ExtIV header (but only filled in for CCMP).
* Add a firmware DMA header; the firmware requires that we
* present a 2-byte payload length followed by a 4-address
* header (without QoS field), followed (optionally) by any
* WEP/ExtIV header (but only filled in for CCMP).
*/
if (hdrlen != sizeof(struct mwl8k_dma_data))
skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen);
wh = (struct ieee80211_hdr *)skb->data;
hdrlen = ieee80211_hdrlen(wh->frame_control);
if (hdrlen != sizeof(*tr))
skb_push(skb, sizeof(*tr) - hdrlen);
if (ieee80211_is_data_qos(wh->frame_control))
hdrlen -= 2;
tr = (struct mwl8k_dma_data *)skb->data;
if (wh != &tr->wh)
memmove(&tr->wh, wh, hdrlen);
/* Clear addr4 */
memset(tr->wh.addr4, 0, ETH_ALEN);
if (hdrlen != sizeof(tr->wh))
memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen);
/*
* Firmware length is the length of the fully formed "802.11
* payload". That is, everything except for the 802.11 header.
* This includes all crypto material including the MIC.
*/
tr->fwlen = cpu_to_le16(pktlen - hdrlen);
tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr));
}
@ -779,6 +781,10 @@ struct mwl8k_rxd_8366 {
__u8 rx_ctrl;
} __attribute__((packed));
#define MWL8K_8366_RATE_INFO_MCS_FORMAT 0x80
#define MWL8K_8366_RATE_INFO_40MHZ 0x40
#define MWL8K_8366_RATE_INFO_RATEID(x) ((x) & 0x3f)
#define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80
static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr)
@ -800,7 +806,8 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len)
}
static int
mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status,
__le16 *qos)
{
struct mwl8k_rxd_8366 *rxd = _rxd;
@ -813,9 +820,11 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
status->signal = -rxd->rssi;
status->noise = -rxd->noise_floor;
if (rxd->rate & 0x80) {
if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) {
status->flag |= RX_FLAG_HT;
status->rate_idx = rxd->rate & 0x7f;
if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ)
status->flag |= RX_FLAG_40MHZ;
status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate);
} else {
int i;
@ -830,6 +839,8 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
status->band = IEEE80211_BAND_2GHZ;
status->freq = ieee80211_channel_to_frequency(rxd->channel);
*qos = rxd->qos_control;
return le16_to_cpu(rxd->pkt_len);
}
@ -888,7 +899,8 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len)
}
static int
mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status,
__le16 *qos)
{
struct mwl8k_rxd_8687 *rxd = _rxd;
u16 rate_info;
@ -903,7 +915,6 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
status->signal = -rxd->rssi;
status->noise = -rxd->noise_level;
status->qual = rxd->link_quality;
status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info);
status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info);
@ -919,6 +930,8 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
status->band = IEEE80211_BAND_2GHZ;
status->freq = ieee80211_channel_to_frequency(rxd->channel);
*qos = rxd->qos_control;
return le16_to_cpu(rxd->pkt_len);
}
@ -1090,6 +1103,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
void *rxd;
int pkt_len;
struct ieee80211_rx_status status;
__le16 qos;
skb = rxq->buf[rxq->head].skb;
if (skb == NULL)
@ -1097,7 +1111,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);
pkt_len = priv->rxd_ops->rxd_process(rxd, &status);
pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos);
if (pkt_len < 0)
break;
@ -1115,7 +1129,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
rxq->rxd_count--;
skb_put(skb, pkt_len);
mwl8k_remove_dma_header(skb);
mwl8k_remove_dma_header(skb, qos);
/*
* Check for a pending join operation. Save a
@ -1221,99 +1235,106 @@ static inline void mwl8k_tx_start(struct mwl8k_priv *priv)
ioread32(priv->regs + MWL8K_HIU_INT_CODE);
}
struct mwl8k_txq_info {
u32 fw_owned;
u32 drv_owned;
u32 unused;
u32 len;
u32 head;
u32 tail;
};
static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
struct mwl8k_txq_info *txinfo)
static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw)
{
int count, desc, status;
struct mwl8k_tx_queue *txq;
struct mwl8k_tx_desc *tx_desc;
int ndescs = 0;
struct mwl8k_priv *priv = hw->priv;
int i;
memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info));
for (i = 0; i < MWL8K_TX_QUEUES; i++) {
struct mwl8k_tx_queue *txq = priv->txq + i;
int fw_owned = 0;
int drv_owned = 0;
int unused = 0;
int desc;
for (count = 0; count < MWL8K_TX_QUEUES; count++) {
txq = priv->txq + count;
txinfo[count].len = txq->stats.len;
txinfo[count].head = txq->head;
txinfo[count].tail = txq->tail;
for (desc = 0; desc < MWL8K_TX_DESCS; desc++) {
tx_desc = txq->txd + desc;
status = le32_to_cpu(tx_desc->status);
struct mwl8k_tx_desc *tx_desc = txq->txd + desc;
u32 status;
status = le32_to_cpu(tx_desc->status);
if (status & MWL8K_TXD_STATUS_FW_OWNED)
txinfo[count].fw_owned++;
fw_owned++;
else
txinfo[count].drv_owned++;
drv_owned++;
if (tx_desc->pkt_len == 0)
txinfo[count].unused++;
unused++;
}
}
return ndescs;
printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d "
"fw_owned=%d drv_owned=%d unused=%d\n",
wiphy_name(hw->wiphy), i,
txq->stats.len, txq->head, txq->tail,
fw_owned, drv_owned, unused);
}
}
/*
* Must be called with priv->fw_mutex held and tx queues stopped.
*/
#define MWL8K_TX_WAIT_TIMEOUT_MS 1000
static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
DECLARE_COMPLETION_ONSTACK(tx_wait);
u32 count;
unsigned long timeout;
int retry;
int rc;
might_sleep();
/*
* The TX queues are stopped at this point, so this test
* doesn't need to take ->tx_lock.
*/
if (!priv->pending_tx_pkts)
return 0;
retry = 0;
rc = 0;
spin_lock_bh(&priv->tx_lock);
count = priv->pending_tx_pkts;
if (count)
priv->tx_wait = &tx_wait;
priv->tx_wait = &tx_wait;
while (!rc) {
int oldcount;
unsigned long timeout;
oldcount = priv->pending_tx_pkts;
spin_unlock_bh(&priv->tx_lock);
timeout = wait_for_completion_timeout(&tx_wait,
msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS));
spin_lock_bh(&priv->tx_lock);
if (timeout) {
WARN_ON(priv->pending_tx_pkts);
if (retry) {
printk(KERN_NOTICE "%s: tx rings drained\n",
wiphy_name(hw->wiphy));
}
break;
}
if (priv->pending_tx_pkts < oldcount) {
printk(KERN_NOTICE "%s: timeout waiting for tx "
"rings to drain (%d -> %d pkts), retrying\n",
wiphy_name(hw->wiphy), oldcount,
priv->pending_tx_pkts);
retry = 1;
continue;
}
priv->tx_wait = NULL;
printk(KERN_ERR "%s: tx rings stuck for %d ms\n",
wiphy_name(hw->wiphy), MWL8K_TX_WAIT_TIMEOUT_MS);
mwl8k_dump_tx_rings(hw);
rc = -ETIMEDOUT;
}
spin_unlock_bh(&priv->tx_lock);
if (count) {
struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES];
int index;
int newcount;
timeout = wait_for_completion_timeout(&tx_wait,
msecs_to_jiffies(5000));
if (timeout)
return 0;
spin_lock_bh(&priv->tx_lock);
priv->tx_wait = NULL;
newcount = priv->pending_tx_pkts;
mwl8k_scan_tx_ring(priv, txinfo);
spin_unlock_bh(&priv->tx_lock);
printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n",
__func__, __LINE__, count, newcount);
for (index = 0; index < MWL8K_TX_QUEUES; index++)
printk(KERN_ERR "TXQ:%u L:%u H:%u T:%u FW:%u "
"DRV:%u U:%u\n",
index,
txinfo[index].len,
txinfo[index].head,
txinfo[index].tail,
txinfo[index].fw_owned,
txinfo[index].drv_owned,
txinfo[index].unused);
return -ETIMEDOUT;
}
return 0;
return rc;
}
#define MWL8K_TXD_SUCCESS(status) \
@ -1361,7 +1382,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
BUG_ON(skb == NULL);
pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
mwl8k_remove_dma_header(skb);
mwl8k_remove_dma_header(skb, tx_desc->qos_control);
/* Mark descriptor as unused */
tx_desc->pkt_phys_addr = 0;
@ -1563,8 +1584,8 @@ static void mwl8k_fw_unlock(struct ieee80211_hw *hw)
* Command processing.
*/
/* Timeout firmware commands after 2000ms */
#define MWL8K_CMD_TIMEOUT_MS 2000
/* Timeout firmware commands after 10s */
#define MWL8K_CMD_TIMEOUT_MS 10000
static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
{
@ -1615,12 +1636,21 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
MWL8K_CMD_TIMEOUT_MS);
rc = -ETIMEDOUT;
} else {
int ms;
ms = MWL8K_CMD_TIMEOUT_MS - jiffies_to_msecs(timeout);
rc = cmd->result ? -EINVAL : 0;
if (rc)
printk(KERN_ERR "%s: Command %s error 0x%x\n",
wiphy_name(hw->wiphy),
mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
le16_to_cpu(cmd->result));
else if (ms > 2000)
printk(KERN_NOTICE "%s: Command %s took %d ms\n",
wiphy_name(hw->wiphy),
mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
ms);
}
return rc;
@ -2439,8 +2469,6 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
/*
* CMD_FINALIZE_JOIN.
*/
/* FJ beacon buffer size is compiled into the firmware. */
#define MWL8K_FJ_BEACON_MAXLEN 128
struct mwl8k_cmd_finalize_join {
@ -2450,17 +2478,13 @@ struct mwl8k_cmd_finalize_join {
} __attribute__((packed));
static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
__u16 framelen, __u16 dtim)
int framelen, int dtim)
{
struct mwl8k_cmd_finalize_join *cmd;
struct ieee80211_mgmt *payload = frame;
u16 hdrlen;
u32 payload_len;
int payload_len;
int rc;
if (frame == NULL)
return -EINVAL;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
@ -2469,24 +2493,17 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);
hdrlen = ieee80211_hdrlen(payload->frame_control);
payload_len = framelen > hdrlen ? framelen - hdrlen : 0;
/* XXX TBD Might just have to abort and return an error */
if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
printk(KERN_ERR "%s(): WARNING: Incomplete beacon "
"sent to firmware. Sz=%u MAX=%u\n", __func__,
payload_len, MWL8K_FJ_BEACON_MAXLEN);
if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
payload_len = framelen - ieee80211_hdrlen(payload->frame_control);
if (payload_len < 0)
payload_len = 0;
else if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
payload_len = MWL8K_FJ_BEACON_MAXLEN;
if (payload && payload_len)
memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
return rc;
}
@ -2515,9 +2532,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *info = &mv_vif->bss_info;
struct mwl8k_cmd_update_sta_db *cmd;
struct peer_capability_info *peer_info;
struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
int rc;
__u8 count, *rates;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
@ -2536,13 +2551,11 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
/* Build peer_info block */
peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
peer_info->basic_caps = cpu_to_le16(info->assoc_capability);
memcpy(peer_info->legacy_rates, mwl8k_rateids,
sizeof(mwl8k_rateids));
peer_info->interop = 1;
peer_info->amsdu_enabled = 0;
rates = peer_info->legacy_rates;
for (count = 0; count < mv_vif->legacy_nrates; count++)
rates[count] = bitrates[count].hw_value;
rc = mwl8k_post_cmd(hw, &cmd->header);
if (rc == 0)
mv_vif->peer_id = peer_info->station_id;
@ -2565,8 +2578,6 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
/*
* CMD_SET_AID.
*/
#define MWL8K_RATE_INDEX_MAX_ARRAY 14
#define MWL8K_FRAME_PROT_DISABLED 0x00
#define MWL8K_FRAME_PROT_11G 0x07
#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02
@ -2579,7 +2590,7 @@ struct mwl8k_cmd_update_set_aid {
/* AP's MAC address (BSSID) */
__u8 bssid[ETH_ALEN];
__le16 protection_mode;
__u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY];
__u8 supp_rates[14];
} __attribute__((packed));
static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
@ -2588,8 +2599,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
struct ieee80211_bss_conf *info = &mv_vif->bss_info;
struct mwl8k_cmd_update_set_aid *cmd;
struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
int count;
u16 prot_mode;
int rc;
@ -2621,8 +2630,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
}
cmd->protection_mode = cpu_to_le16(prot_mode);
for (count = 0; count < mv_vif->legacy_nrates; count++)
cmd->supp_rates[count] = bitrates[count].hw_value;
memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids));
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@ -2635,20 +2643,17 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
*/
struct mwl8k_cmd_update_rateset {
struct mwl8k_cmd_pkt header;
__u8 legacy_rates[MWL8K_RATE_INDEX_MAX_ARRAY];
__u8 legacy_rates[14];
/* Bitmap for supported MCS codes. */
__u8 mcs_set[MWL8K_IEEE_LEGACY_DATA_RATES];
__u8 reserved[MWL8K_IEEE_LEGACY_DATA_RATES];
__u8 mcs_set[16];
__u8 reserved[16];
} __attribute__((packed));
static int mwl8k_update_rateset(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
struct mwl8k_cmd_update_rateset *cmd;
struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
int count;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@ -2657,9 +2662,7 @@ static int mwl8k_update_rateset(struct ieee80211_hw *hw,
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
for (count = 0; count < mv_vif->legacy_nrates; count++)
cmd->legacy_rates[count] = bitrates[count].hw_value;
memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids));
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@ -2932,11 +2935,6 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
/* Back pointer to parent config block */
mwl8k_vif->priv = priv;
/* Setup initial PHY parameters */
memcpy(mwl8k_vif->legacy_rates,
priv->rates, sizeof(mwl8k_vif->legacy_rates));
mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates);
/* Set Initial sequence number to zero */
mwl8k_vif->seqno = 0;
@ -3014,9 +3012,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
int rc;
if (changed & BSS_CHANGED_BSSID)
memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN);
if ((changed & BSS_CHANGED_ASSOC) == 0)
return;
@ -3030,6 +3025,8 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
memcpy(&mwl8k_vif->bss_info, info,
sizeof(struct ieee80211_bss_conf));
memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN);
/* Install rates */
rc = mwl8k_update_rateset(hw, vif);
if (rc)
@ -3366,7 +3363,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
if (rc) {
printk(KERN_ERR "%s: Cannot obtain PCI resources\n",
MWL8K_NAME);
return rc;
goto err_disable_device;
}
pci_set_master(pdev);
@ -3597,6 +3594,8 @@ err_iounmap:
err_free_reg:
pci_release_regions(pdev);
err_disable_device:
pci_disable_device(pdev);
return rc;

View file

@ -427,7 +427,7 @@ int hermesi_program_init(hermes_t *hw, u32 offset)
if (err)
return err;
pr_debug(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset);
pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset);
err = hermes_doicmd_wait(hw,
HERMES_PROGRAM_ENABLE_VOLATILE,
offset & 0xFFFFu,

View file

@ -23,6 +23,7 @@
#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */
#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */
#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */
#define RTL8187_EEPROM_SELECT_GPIO 0x3B
#define RTL8187_REQT_READ 0xC0
#define RTL8187_REQT_WRITE 0x40
@ -31,6 +32,9 @@
#define RTL8187_MAX_RX 0x9C4
#define RFKILL_MASK_8187_89_97 0x2
#define RFKILL_MASK_8198 0x4
struct rtl8187_rx_info {
struct urb *urb;
struct ieee80211_hw *dev;
@ -104,6 +108,7 @@ struct rtl8187_priv {
struct delayed_work work;
struct ieee80211_hw *dev;
#ifdef CONFIG_RTL8187_LEDS
struct rtl8187_led led_radio;
struct rtl8187_led led_tx;
struct rtl8187_led led_rx;
struct delayed_work led_on;
@ -122,6 +127,7 @@ struct rtl8187_priv {
u8 noise;
u8 slot_time;
u8 aifsn[4];
u8 rfkill_mask;
struct {
__le64 buf;
struct sk_buff_head queue;

View file

@ -1322,6 +1322,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
struct ieee80211_channel *channel;
const char *chip_name;
u16 txpwr, reg;
u16 product_id = le16_to_cpu(udev->descriptor.idProduct);
int err, i;
dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
@ -1481,6 +1482,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
(*channel++).hw_value = txpwr & 0xFF;
(*channel++).hw_value = txpwr >> 8;
}
/* Handle the differing rfkill GPIO bit in different models */
priv->rfkill_mask = RFKILL_MASK_8187_89_97;
if (product_id == 0x8197 || product_id == 0x8198) {
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, &reg);
if (reg & 0xFF00)
priv->rfkill_mask = RFKILL_MASK_8198;
}
/*
* XXX: Once this driver supports anything that requires
@ -1509,9 +1517,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
mutex_init(&priv->conf_mutex);
skb_queue_head_init(&priv->b_tx_status.queue);
printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n",
printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n",
wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
chip_name, priv->asic_rev, priv->rf->name);
chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask);
#ifdef CONFIG_RTL8187_LEDS
eeprom_93cx6_read(&eeprom, 0x3F, &reg);

View file

@ -105,19 +105,36 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led,
led_dev);
struct ieee80211_hw *hw = led->dev;
struct rtl8187_priv *priv = hw->priv;
struct rtl8187_priv *priv;
static bool radio_on;
if (brightness == LED_OFF) {
ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
/* The LED is off for 1/20 sec so that it just blinks. */
ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20);
} else
ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
if (!hw)
return;
priv = hw->priv;
if (led->is_radio) {
if (brightness == LED_FULL) {
ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
radio_on = true;
} else if (radio_on) {
radio_on = false;
cancel_delayed_work_sync(&priv->led_on);
ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
}
} else if (radio_on) {
if (brightness == LED_OFF) {
ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
/* The LED is off for 1/20 sec - it just blinks. */
ieee80211_queue_delayed_work(hw, &priv->led_on,
HZ / 20);
} else
ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
}
}
static int rtl8187_register_led(struct ieee80211_hw *dev,
struct rtl8187_led *led, const char *name,
const char *default_trigger, u8 ledpin)
const char *default_trigger, u8 ledpin,
bool is_radio)
{
int err;
struct rtl8187_priv *priv = dev->priv;
@ -128,6 +145,7 @@ static int rtl8187_register_led(struct ieee80211_hw *dev,
return -EINVAL;
led->dev = dev;
led->ledpin = ledpin;
led->is_radio = is_radio;
strncpy(led->name, name, sizeof(led->name));
led->led_dev.name = led->name;
@ -145,7 +163,11 @@ static int rtl8187_register_led(struct ieee80211_hw *dev,
static void rtl8187_unregister_led(struct rtl8187_led *led)
{
struct ieee80211_hw *hw = led->dev;
struct rtl8187_priv *priv = hw->priv;
led_classdev_unregister(&led->led_dev);
flush_delayed_work(&priv->led_off);
led->dev = NULL;
}
@ -182,34 +204,38 @@ void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
INIT_DELAYED_WORK(&priv->led_on, led_turn_on);
INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
snprintf(name, sizeof(name),
"rtl8187-%s::radio", wiphy_name(dev->wiphy));
err = rtl8187_register_led(dev, &priv->led_radio, name,
ieee80211_get_radio_led_name(dev), ledpin, true);
if (err)
return;
snprintf(name, sizeof(name),
"rtl8187-%s::tx", wiphy_name(dev->wiphy));
err = rtl8187_register_led(dev, &priv->led_tx, name,
ieee80211_get_tx_led_name(dev), ledpin);
ieee80211_get_tx_led_name(dev), ledpin, false);
if (err)
goto error;
goto err_tx;
snprintf(name, sizeof(name),
"rtl8187-%s::rx", wiphy_name(dev->wiphy));
err = rtl8187_register_led(dev, &priv->led_rx, name,
ieee80211_get_rx_led_name(dev), ledpin);
if (!err) {
ieee80211_queue_delayed_work(dev, &priv->led_on, 0);
ieee80211_get_rx_led_name(dev), ledpin, false);
if (!err)
return;
}
/* registration of RX LED failed - unregister TX */
/* registration of RX LED failed - unregister */
rtl8187_unregister_led(&priv->led_tx);
error:
/* If registration of either failed, cancel delayed work */
cancel_delayed_work_sync(&priv->led_off);
cancel_delayed_work_sync(&priv->led_on);
err_tx:
rtl8187_unregister_led(&priv->led_radio);
}
void rtl8187_leds_exit(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
/* turn the LED off before exiting */
ieee80211_queue_delayed_work(dev, &priv->led_off, 0);
rtl8187_unregister_led(&priv->led_radio);
rtl8187_unregister_led(&priv->led_rx);
rtl8187_unregister_led(&priv->led_tx);
cancel_delayed_work_sync(&priv->led_off);

View file

@ -47,6 +47,8 @@ struct rtl8187_led {
u8 ledpin;
/* The unique name string for this LED device. */
char name[RTL8187_LED_MAX_NAME_LEN + 1];
/* If the LED is radio or tx/rx */
bool is_radio;
};
void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code);

View file

@ -25,10 +25,10 @@ static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv)
u8 gpio;
gpio = rtl818x_ioread8(priv, &priv->map->GPIO0);
rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~0x02);
rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask);
gpio = rtl818x_ioread8(priv, &priv->map->GPIO1);
return gpio & 0x02;
return gpio & priv->rfkill_mask;
}
void rtl8187_rfkill_init(struct ieee80211_hw *hw)

View file

@ -629,10 +629,6 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
goto out_sleep;
}
ret = wl1251_build_null_data(wl);
if (ret < 0)
goto out_sleep;
if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
wl1251_debug(DEBUG_PSM, "psm enabled");
@ -1110,6 +1106,21 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
if (changed & BSS_CHANGED_BSSID) {
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
ret = wl1251_build_null_data(wl);
if (ret < 0)
goto out;
if (wl->bss_type != BSS_TYPE_IBSS) {
ret = wl1251_join(wl, wl->bss_type, wl->channel,
wl->beacon_int, wl->dtim_period);
if (ret < 0)
goto out_sleep;
}
}
if (changed & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
wl->beacon_int = bss_conf->beacon_int;
@ -1169,23 +1180,6 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
}
}
if (changed & BSS_CHANGED_BSSID) {
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
ret = wl1251_build_null_data(wl);
if (ret < 0)
goto out;
if (wl->bss_type != BSS_TYPE_IBSS) {
ret = wl1251_join(wl, wl->bss_type, wl->channel,
wl->beacon_int, wl->dtim_period);
if (ret < 0)
goto out_sleep;
wl1251_warning("Set ctsprotect failed %d", ret);
goto out_sleep;
}
}
if (changed & BSS_CHANGED_BEACON) {
beacon = ieee80211_beacon_get(hw, vif);
ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data,