diff options
Diffstat (limited to 'drivers/net')
127 files changed, 2590 insertions, 1178 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ab651d6..d271a78 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2543,7 +2543,7 @@ config S6GMAC source "drivers/net/stmmac/Kconfig" config PCH_GBE - tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE" + tristate "Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE" depends on PCI select MII ---help--- @@ -2556,10 +2556,11 @@ config PCH_GBE This driver enables Gigabit Ethernet function. This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ - Output Hub), ML7223. - ML7223 IOH is for MP(Media Phone) use. - ML7223 is companion chip for Intel Atom E6xx series. - ML7223 is completely compatible for Intel EG20T PCH. + Output Hub), ML7223/ML7831. + ML7223 IOH is for MP(Media Phone) use. ML7831 IOH is for general + purpose use. + ML7223/ML7831 is companion chip for Intel Atom E6xx series. + ML7223/ML7831 is completely compatible for Intel EG20T PCH. endif # NETDEV_1000 diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a485f7f..2ce5db5 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -763,6 +763,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb); if (copied) { + int gso_segs = skb_shinfo(skb)->gso_segs; + /* record the sent skb in the sent_skb table */ BUG_ON(tx_obj->sent_skb_list[start]); tx_obj->sent_skb_list[start] = skb; @@ -780,8 +782,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, be_txq_notify(adapter, txq->id, wrb_cnt); - be_tx_stats_update(adapter, wrb_cnt, copied, - skb_shinfo(skb)->gso_segs, stopped); + be_tx_stats_update(adapter, wrb_cnt, copied, gso_segs, stopped); } else { txq->head = start; dev_kfree_skb_any(skb); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 74580bb..c9b123c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -5310,7 +5310,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) int k, last; if (skb == NULL) { - j++; + j = NEXT_TX_BD(j); continue; } @@ -5322,8 +5322,8 @@ bnx2_free_tx_skbs(struct bnx2 *bp) tx_buf->skb = NULL; last = tx_buf->nr_frags; - j++; - for (k = 0; k < last; k++, j++) { + j = NEXT_TX_BD(j); + for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) { tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)]; dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e6da842..6f8b268 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -77,6 +77,7 @@ #include <net/route.h> #include <net/net_namespace.h> #include <net/netns/generic.h> +#include <net/pkt_sched.h> #include "bonding.h" #include "bond_3ad.h" #include "bond_alb.h" @@ -388,8 +389,6 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) return next; } -#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb)) - /** * bond_dev_queue_xmit - Prepare skb for xmit. * @@ -403,7 +402,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, skb->dev = slave_dev; skb->priority = 1; - skb->queue_mapping = bond_queue_mapping(skb); + BUILD_BUG_ON(sizeof(skb->queue_mapping) != + sizeof(qdisc_skb_cb(skb)->bond_queue_mapping)); + skb->queue_mapping = qdisc_skb_cb(skb)->bond_queue_mapping; if (unlikely(netpoll_tx_running(slave_dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); @@ -1438,6 +1439,8 @@ static void bond_compute_features(struct bonding *bond) struct net_device *bond_dev = bond->dev; u32 vlan_features = BOND_VLAN_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; + unsigned int gso_max_size = GSO_MAX_SIZE; + u16 gso_max_segs = GSO_MAX_SEGS; int i; read_lock(&bond->lock); @@ -1451,11 +1454,16 @@ static void bond_compute_features(struct bonding *bond) if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; + + gso_max_size = min(gso_max_size, slave->dev->gso_max_size); + gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs); } done: bond_dev->vlan_features = vlan_features; bond_dev->hard_header_len = max_hard_header_len; + bond_dev->gso_max_segs = gso_max_segs; + netif_set_gso_max_size(bond_dev, gso_max_size); read_unlock(&bond->lock); @@ -4240,7 +4248,7 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) /* * Save the original txq to restore before passing to the driver */ - bond_queue_mapping(skb) = skb->queue_mapping; + qdisc_skb_cb(skb)->bond_queue_mapping = skb->queue_mapping; if (unlikely(txq >= dev->real_num_tx_queues)) { do { diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 0624610..8a96735 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1524,6 +1524,7 @@ static ssize_t bonding_store_slaves_active(struct device *d, goto out; } + read_lock(&bond->lock); bond_for_each_slave(bond, slave, i) { if (!bond_is_active_slave(slave)) { if (new_value) @@ -1532,6 +1533,7 @@ static ssize_t bonding_store_slaves_active(struct device *d, slave->inactive = 1; } } + read_unlock(&bond->lock); out: return ret; } diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 3df0c0f..82b1802 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -325,6 +325,9 @@ static int ldisc_open(struct tty_struct *tty) sprintf(name, "cf%s", tty->name); dev = alloc_netdev(sizeof(*ser), name, caifdev_setup); + if (!dev) + return -ENOMEM; + ser = netdev_priv(dev); ser->tty = tty_kref_get(tty); ser->dev = dev; diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 7e5cc0b..6195868 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -592,8 +592,8 @@ static void c_can_chip_config(struct net_device *dev) priv->write_reg(priv, &priv->regs->control, CONTROL_ENABLE_AR); - if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY & - CAN_CTRLMODE_LOOPBACK)) { + if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) && + (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) { /* loopback + silent mode : useful for hot self-test */ priv->write_reg(priv, &priv->regs->control, CONTROL_EIE | CONTROL_SIE | CONTROL_IE | CONTROL_TEST); @@ -688,7 +688,7 @@ static int c_can_get_berr_counter(const struct net_device *dev, * * We iterate from priv->tx_echo to priv->tx_next and check if the * packet has been transmitted, echo it back to the CAN framework. - * If we discover a not yet transmitted package, stop looking for more. + * If we discover a not yet transmitted packet, stop looking for more. */ static void c_can_do_tx(struct net_device *dev) { @@ -700,7 +700,7 @@ static void c_can_do_tx(struct net_device *dev) for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { msg_obj_no = get_tx_echo_msg_obj(priv); val = c_can_read_reg32(priv, &priv->regs->txrqst1); - if (!(val & (1 << msg_obj_no))) { + if (!(val & (1 << (msg_obj_no - 1)))) { can_get_echo_skb(dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); stats->tx_bytes += priv->read_reg(priv, @@ -708,6 +708,8 @@ static void c_can_do_tx(struct net_device *dev) & IF_MCONT_DLC_MASK; stats->tx_packets++; c_can_inval_msg_object(dev, 0, msg_obj_no); + } else { + break; } } @@ -914,7 +916,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_ACK_ERROR: netdev_dbg(dev, "ack error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL); break; case LEC_BIT1_ERROR: @@ -927,7 +929,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_CRC_ERROR: netdev_dbg(dev, "CRC error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL); break; default: @@ -952,7 +954,7 @@ static int c_can_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + irqstatus = priv->irqstatus; if (!irqstatus) goto end; @@ -1030,12 +1032,11 @@ end: static irqreturn_t c_can_isr(int irq, void *dev_id) { - u16 irqstatus; struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); - if (!irqstatus) + priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + if (!priv->irqstatus) return IRQ_NONE; /* disable all interrupts and schedule the NAPI */ @@ -1065,10 +1066,11 @@ static int c_can_open(struct net_device *dev) goto exit_irq_fail; } + napi_enable(&priv->napi); + /* start the c_can controller */ c_can_start(dev); - napi_enable(&priv->napi); netif_start_queue(dev); return 0; diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 9b7fbef..5f32d34 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -76,6 +76,7 @@ struct c_can_priv { unsigned int tx_next; unsigned int tx_echo; void *priv; /* for board-specific data */ + u16 irqstatus; }; struct net_device *alloc_c_can_dev(void); diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index d0f8c7e..cc3ea0d 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -557,8 +557,7 @@ void close_candev(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); - if (del_timer_sync(&priv->restart_timer)) - dev_put(dev); + del_timer_sync(&priv->restart_timer); can_flush_echo_skb(dev); } EXPORT_SYMBOL_GPL(close_candev); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index f1942ca..b4159a6 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1249,7 +1249,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id) */ static int ican3_reset_module(struct ican3_dev *mod) { - u8 val = 1 << mod->num; unsigned long start; u8 runold, runnew; @@ -1263,8 +1262,7 @@ static int ican3_reset_module(struct ican3_dev *mod) runold = ioread8(mod->dpm + TARGET_RUNNING); /* reset the module */ - iowrite8(val, &mod->ctrl->reset_assert); - iowrite8(val, &mod->ctrl->reset_deassert); + iowrite8(0x00, &mod->dpmctrl->hwreset); /* wait until the module has finished resetting and is running */ start = jiffies; diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 330140e..9bcc39a 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -83,6 +83,11 @@ #define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) #define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) #define INSTRUCTION_RESET 0xC0 +#define RTS_TXB0 0x01 +#define RTS_TXB1 0x02 +#define RTS_TXB2 0x04 +#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07)) + /* MPC251x registers */ #define CANSTAT 0x0e @@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, int tx_buf_idx) { + struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); u32 sid, eid, exide, rtr; u8 buf[SPI_TRANSFER_BUF_LEN]; @@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); + + /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ + priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); + mcp251x_spi_trans(priv->spi, 1); } static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 5fedc33..d8f2b5b 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -181,7 +181,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (!clock_name || !strcmp(clock_name, "sys")) { sys_clk = clk_get(&ofdev->dev, "sys_clk"); - if (!sys_clk) { + if (IS_ERR(sys_clk)) { dev_err(&ofdev->dev, "couldn't get sys_clk\n"); goto exit_unmap; } @@ -204,7 +204,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (clocksrc < 0) { ref_clk = clk_get(&ofdev->dev, "ref_clk"); - if (!ref_clk) { + if (IS_ERR(ref_clk)) { dev_err(&ofdev->dev, "couldn't get ref_clk\n"); goto exit_unmap; } diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index d11fbb2..b508a63 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -559,7 +559,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) stats->rx_errors++; break; case PCH_CRC_ERR: - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; priv->can.can_stats.bus_error++; stats->rx_errors++; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index f7bbde9..10b2394 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -734,12 +734,12 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, } if (err_status & HECC_CANES_CRCE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; } if (err_status & HECC_CANES_ACKE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); - cf->data[2] |= CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL; } } @@ -969,12 +969,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); + unregister_candev(ndev); clk_disable(priv->clk); clk_put(priv->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->base); release_mem_region(res->start, resource_size(res)); - unregister_candev(ndev); free_candev(ndev); platform_set_drvdata(pdev, NULL); diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c index ae47f23..6b67c52 100644 --- a/drivers/net/davinci_cpdma.c +++ b/drivers/net/davinci_cpdma.c @@ -849,6 +849,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan) next_dma = desc_read(desc, hw_next); chan->head = desc_from_phys(pool, next_dma); + chan->count--; chan->stats.teardown_dequeue++; /* issue callback without locks held */ diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 3fa19c1..098ff31 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -37,6 +37,7 @@ #include <linux/rtnetlink.h> #include <net/rtnetlink.h> #include <linux/u64_stats_sync.h> +#include <linux/sched.h> static int numdummies = 1; @@ -186,8 +187,10 @@ static int __init dummy_init_module(void) rtnl_lock(); err = __rtnl_link_register(&dummy_link_ops); - for (i = 0; i < numdummies && !err; i++) + for (i = 0; i < numdummies && !err; i++) { err = dummy_init_one(); + cond_resched(); + } if (err < 0) __rtnl_link_unregister(&dummy_link_ops); rtnl_unlock(); diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 8676899..2c71884 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -150,6 +150,8 @@ struct e1000_buffer { unsigned long time_stamp; u16 length; u16 next_to_watch; + unsigned int segs; + unsigned int bytecount; u16 mapped_as_page; }; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 76e8af0..99525f9 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2798,7 +2798,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info; unsigned int len = skb_headlen(skb); unsigned int offset = 0, size, count = 0, i; - unsigned int f; + unsigned int f, bytecount, segs; i = tx_ring->next_to_use; @@ -2899,7 +2899,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, } } + segs = skb_shinfo(skb)->gso_segs ?: 1; + /* multiply data chunks by size of headers */ + bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len; + tx_ring->buffer_info[i].skb = skb; + tx_ring->buffer_info[i].segs = segs; + tx_ring->buffer_info[i].bytecount = bytecount; tx_ring->buffer_info[first].next_to_watch = i; return count; @@ -3573,14 +3579,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, cleaned = (i == eop); if (cleaned) { - struct sk_buff *skb = buffer_info->skb; - unsigned int segs, bytecount; - segs = skb_shinfo(skb)->gso_segs ?: 1; - /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * skb_headlen(skb)) + - skb->len; - total_tx_packets += segs; - total_tx_bytes += bytecount; + total_tx_packets += buffer_info->segs; + total_tx_bytes += buffer_info->bytecount; } e1000_unmap_and_free_tx_resource(adapter, buffer_info); tx_desc->upper.data = 0; diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 8295f21..8402d19 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1573,6 +1573,9 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) ctrl = er32(CTRL); status = er32(STATUS); rxcw = er32(RXCW); + /* SYNCH bit and IV bit are sticky */ + udelay(10); + rxcw = er32(RXCW); if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { @@ -1599,10 +1602,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. - * If the partner code word is null, stop forcing - * and restart auto negotiation. */ - if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) { + if (rxcw & E1000_RXCW_C) { /* Enable autoneg, and unforce link up */ ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); @@ -2087,7 +2088,8 @@ struct e1000_info e1000_82574_info = { | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, .flags2 = FLAG2_CHECK_PHY_HANG - | FLAG2_DISABLE_ASPM_L0S, + | FLAG2_DISABLE_ASPM_L0S + | FLAG2_DISABLE_ASPM_L1, .pba = 32, .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_82571, diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index efe05bb..ddec154 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -221,7 +221,7 @@ static void sirdev_config_fsm(struct work_struct *work) break; case SIRDEV_STATE_DONGLE_SPEED: - if (dev->dongle_drv->reset) { + if (dev->dongle_drv->set_speed) { ret = dev->dongle_drv->set_speed(dev, fsm->param); if (ret < 0) { fsm->result = ret; diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 8ee6612..4adce71 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -360,6 +360,8 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82599_SFP_FCOE: case IXGBE_DEV_ID_82599_SFP_EM: case IXGBE_DEV_ID_82599_SFP_SF2: + case IXGBE_DEV_ID_82599EN_SFP: + case IXGBE_DEV_ID_82599_SFP_SF_QP: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82599_CX4: diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index b894b42..864403d 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -3181,6 +3181,7 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: return 0; case IXGBE_DEV_ID_82599_T3_LOM: return 0; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 83f197d..f0b0ff3 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -129,6 +129,12 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), + board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), + board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), + board_X540 }, /* required last entry */ {0, } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index fa43f25..1ea1577 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -59,11 +59,14 @@ #define IXGBE_SUBDEV_ID_82599_SFP 0x11A9 #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 #define IXGBE_DEV_ID_82599_SFP_SF2 0x154D +#define IXGBE_DEV_ID_82599EN_SFP 0x1557 #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC #define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 #define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C #define IXGBE_DEV_ID_82599_LS 0x154F +#define IXGBE_DEV_ID_82599_SFP_SF_QP 0x154A #define IXGBE_DEV_ID_X540T 0x1528 +#define IXGBE_DEV_ID_X540T1 0x1560 /* General Registers */ #define IXGBE_CTRL 0x00000 diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 4ce9e5f..d0893e4 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -78,6 +78,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, skb_orphan(skb); + /* Before queueing this packet to netif_rx(), + * make sure dst is refcounted. + */ + skb_dst_force(skb); + skb->protocol = eth_type_trans(skb, dev); /* it's OK to use per_cpu_ptr() because BHs are off */ diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index ab4723d..735f726 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -247,7 +247,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) xmit_world: skb->ip_summed = ip_summed; - skb_set_dev(skb, vlan->lowerdev); + skb->dev = vlan->lowerdev; return dev_queue_xmit(skb); } diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 1063093..e8ee2bc 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -814,6 +814,7 @@ static int __init ne_drv_probe(struct platform_device *pdev) dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; } + SET_NETDEV_DEV(dev, &pdev->dev); err = do_ne_probe(dev); if (err) { free_netdev(dev); diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 4840ab7..4309296 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -652,7 +652,6 @@ static int netconsole_netdev_event(struct notifier_block *this, flags); dev_put(nt->np.dev); nt->np.dev = NULL; - netconsole_target_put(nt); } nt->enabled = 0; stopped = true; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index c0788a3..78d5b67 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1288,6 +1288,10 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter) struct pci_dev *root = pdev->bus->self; u32 aer_pos; + /* root bus? */ + if (!root) + return; + if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM && adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP) return; diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index eac3c5c..236d00e 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -39,6 +39,9 @@ const char pch_driver_version[] = DRV_VERSION; #define PCI_VENDOR_ID_ROHM 0x10db #define PCI_DEVICE_ID_ROHM_ML7223_GBE 0x8013 +/* Macros for ML7831 */ +#define PCI_DEVICE_ID_ROHM_ML7831_GBE 0x8802 + #define PCH_GBE_TX_WEIGHT 64 #define PCH_GBE_RX_WEIGHT 64 #define PCH_GBE_RX_BUFFER_WRITE 16 @@ -717,13 +720,6 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) iowrite32(rdba, &hw->reg->RX_DSC_BASE); iowrite32(rdlen, &hw->reg->RX_DSC_SIZE); iowrite32((rdba + rdlen), &hw->reg->RX_DSC_SW_P); - - /* Enables Receive DMA */ - rxdma = ioread32(&hw->reg->DMA_CTRL); - rxdma |= PCH_GBE_RX_DMA_EN; - iowrite32(rxdma, &hw->reg->DMA_CTRL); - /* Enables Receive */ - iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN); } /** @@ -1097,6 +1093,19 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, flags); } +static void pch_gbe_start_receive(struct pch_gbe_hw *hw) +{ + u32 rxdma; + + /* Enables Receive DMA */ + rxdma = ioread32(&hw->reg->DMA_CTRL); + rxdma |= PCH_GBE_RX_DMA_EN; + iowrite32(rxdma, &hw->reg->DMA_CTRL); + /* Enables Receive */ + iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN); + return; +} + /** * pch_gbe_intr - Interrupt Handler * @irq: Interrupt number @@ -1701,6 +1710,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; int err; + /* Ensure we have a valid MAC */ + if (!is_valid_ether_addr(adapter->hw.mac.addr)) { + pr_err("Error: Invalid MAC address\n"); + return -EINVAL; + } + /* hardware has been reset, we need to reload some things */ pch_gbe_set_multi(netdev); @@ -1717,6 +1732,7 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) pch_gbe_alloc_tx_buffers(adapter, tx_ring); pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count); adapter->tx_queue_len = netdev->tx_queue_len; + pch_gbe_start_receive(&adapter->hw); mod_timer(&adapter->watchdog_timer, jiffies); @@ -2118,7 +2134,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) /* If no Tx and not enough Rx work done, * exit the polling mode */ - if ((work_done < budget) || !netif_running(netdev)) + if (work_done < budget) poll_end_flag = true; } @@ -2392,9 +2408,14 @@ static int pch_gbe_probe(struct pci_dev *pdev, memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->dev_addr)) { - dev_err(&pdev->dev, "Invalid MAC Address\n"); - ret = -EIO; - goto err_free_adapter; + /* + * If the MAC is invalid (or just missing), display a warning + * but do not abort setting up the device. pch_gbe_up will + * prevent the interface from being brought up until a valid MAC + * is set. + */ + dev_err(&pdev->dev, "Invalid MAC address, " + "interface disabled.\n"); } setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog, (unsigned long)adapter); @@ -2452,6 +2473,13 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = { .class = (PCI_CLASS_NETWORK_ETHERNET << 8), .class_mask = (0xFFFF00) }, + {.vendor = PCI_VENDOR_ID_ROHM, + .device = PCI_DEVICE_ID_ROHM_ML7831_GBE, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .class = (PCI_CLASS_NETWORK_ETHERNET << 8), + .class_mask = (0xFFFF00) + }, /* required last entry */ {0} }; diff --git a/drivers/net/pch_gbe/pch_gbe_param.c b/drivers/net/pch_gbe/pch_gbe_param.c index 5b5d90a..fb74ef9 100644 --- a/drivers/net/pch_gbe/pch_gbe_param.c +++ b/drivers/net/pch_gbe/pch_gbe_param.c @@ -320,10 +320,10 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter) pr_debug("AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n"); hw->phy.autoneg_advertised = opt.def; } else { - hw->phy.autoneg_advertised = AutoNeg; - pch_gbe_validate_option( - (int *)(&hw->phy.autoneg_advertised), - &opt, adapter); + int tmp = AutoNeg; + + pch_gbe_validate_option(&tmp, &opt, adapter); + hw->phy.autoneg_advertised = tmp; } } @@ -494,9 +494,10 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter) .arg = { .l = { .nr = (int)ARRAY_SIZE(fc_list), .p = fc_list } } }; - hw->mac.fc = FlowControl; - pch_gbe_validate_option((int *)(&hw->mac.fc), - &opt, adapter); + int tmp = FlowControl; + + pch_gbe_validate_option(&tmp, &opt, adapter); + hw->mac.fc = tmp; } pch_gbe_check_copper_options(adapter); diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index bc9a4bb..1161584 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -576,7 +576,7 @@ static int pppoe_release(struct socket *sock) po = pppox_sk(sk); - if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { + if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { dev_put(po->pppoe_dev); po->pppoe_dev = NULL; } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 5f838ef..80b230e 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -58,8 +58,12 @@ #define R8169_MSG_DEFAULT \ (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) -#define TX_BUFFS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1) +#define TX_SLOTS_AVAIL(tp) \ + (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx) + +/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ +#define TX_FRAGS_READY_FOR(tp,nr_frags) \ + (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1)) /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). The RTL chips use a 64 element hash table based on the Ethernet CRC. */ @@ -71,7 +75,7 @@ static const int multicast_filter_limit = 32; #define MAX_READ_REQUEST_SHIFT 12 #define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */ #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ +#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ @@ -140,82 +144,101 @@ enum rtl_tx_desc_version { RTL_TD_1 = 1, }; -#define _R(NAME,TD,FW) \ - { .name = NAME, .txd_version = TD, .fw_name = FW } +#define JUMBO_1K ETH_DATA_LEN +#define JUMBO_4K (4*1024 - ETH_HLEN - 2) +#define JUMBO_6K (6*1024 - ETH_HLEN - 2) +#define JUMBO_7K (7*1024 - ETH_HLEN - 2) +#define JUMBO_9K (9*1024 - ETH_HLEN - 2) + +#define _R(NAME,TD,FW,SZ,B) { \ + .name = NAME, \ + .txd_version = TD, \ + .fw_name = FW, \ + .jumbo_max = SZ, \ + .jumbo_tx_csum = B \ +} static const struct { const char *name; enum rtl_tx_desc_version txd_version; const char *fw_name; + u16 jumbo_max; + bool jumbo_tx_csum; } rtl_chip_infos[] = { /* PCI devices. */ [RTL_GIGA_MAC_VER_01] = - _R("RTL8169", RTL_TD_0, NULL), + _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_02] = - _R("RTL8169s", RTL_TD_0, NULL), + _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_03] = - _R("RTL8110s", RTL_TD_0, NULL), + _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_04] = - _R("RTL8169sb/8110sb", RTL_TD_0, NULL), + _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_05] = - _R("RTL8169sc/8110sc", RTL_TD_0, NULL), + _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_06] = - _R("RTL8169sc/8110sc", RTL_TD_0, NULL), + _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), /* PCI-E devices. */ [RTL_GIGA_MAC_VER_07] = - _R("RTL8102e", RTL_TD_1, NULL), + _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_08] = - _R("RTL8102e", RTL_TD_1, NULL), + _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_09] = - _R("RTL8102e", RTL_TD_1, NULL), + _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_10] = - _R("RTL8101e", RTL_TD_0, NULL), + _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_11] = - _R("RTL8168b/8111b", RTL_TD_0, NULL), + _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_12] = - _R("RTL8168b/8111b", RTL_TD_0, NULL), + _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_13] = - _R("RTL8101e", RTL_TD_0, NULL), + _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_14] = - _R("RTL8100e", RTL_TD_0, NULL), + _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_15] = - _R("RTL8100e", RTL_TD_0, NULL), + _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_16] = - _R("RTL8101e", RTL_TD_0, NULL), + _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_17] = - _R("RTL8168b/8111b", RTL_TD_0, NULL), + _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_18] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL), + _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_19] = - _R("RTL8168c/8111c", RTL_TD_1, NULL), + _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_20] = - _R("RTL8168c/8111c", RTL_TD_1, NULL), + _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_21] = - _R("RTL8168c/8111c", RTL_TD_1, NULL), + _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_22] = - _R("RTL8168c/8111c", RTL_TD_1, NULL), + _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_23] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL), + _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_24] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL), + _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_25] = - _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1), + _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1, + JUMBO_9K, false), [RTL_GIGA_MAC_VER_26] = - _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2), + _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2, + JUMBO_9K, false), [RTL_GIGA_MAC_VER_27] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL), + _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_28] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL), + _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_29] = - _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1), + _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, + JUMBO_1K, true), [RTL_GIGA_MAC_VER_30] = - _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1), + _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, + JUMBO_1K, true), [RTL_GIGA_MAC_VER_31] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL), + _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_32] = - _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1), + _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1, + JUMBO_9K, false), [RTL_GIGA_MAC_VER_33] = - _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2) + _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2, + JUMBO_9K, false) }; #undef _R @@ -280,6 +303,8 @@ enum rtl_registers { Config0 = 0x51, Config1 = 0x52, Config2 = 0x53, +#define PME_SIGNAL (1 << 5) /* 8168c and later */ + Config3 = 0x54, Config4 = 0x55, Config5 = 0x56, @@ -388,6 +413,7 @@ enum rtl_register_content { RxOK = 0x0001, /* RxStatusDesc */ + RxBOVF = (1 << 24), RxFOVF = (1 << 23), RxRWT = (1 << 22), RxRES = (1 << 21), @@ -428,7 +454,6 @@ enum rtl_register_content { /* Config1 register p.24 */ LEDS1 = (1 << 7), LEDS0 = (1 << 6), - MSIEnable = (1 << 5), /* Enable Message Signaled Interrupt */ Speed_down = (1 << 4), MEMMAP = (1 << 3), IOMAP = (1 << 2), @@ -436,14 +461,19 @@ enum rtl_register_content { PMEnable = (1 << 0), /* Power Management Enable */ /* Config2 register p. 25 */ + MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */ PCI_Clock_66MHz = 0x01, PCI_Clock_33MHz = 0x00, /* Config3 register p.25 */ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ + Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */ Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ + /* Config4 register */ + Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */ + /* Config5 register p.27 */ BWF = (1 << 6), /* Accept Broadcast wakeup frame */ MWF = (1 << 5), /* Accept Multicast wakeup frame */ @@ -652,6 +682,11 @@ struct rtl8169_private { void (*up)(struct rtl8169_private *); } pll_power_ops; + struct jumbo_ops { + void (*enable)(struct rtl8169_private *); + void (*disable)(struct rtl8169_private *); + } jumbo_ops; + int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); int (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(struct rtl8169_private *tp); @@ -666,6 +701,7 @@ struct rtl8169_private { struct mii_if_info mii; struct rtl8169_counters counters; u32 saved_wolopts; + u32 opts1_mask; const struct firmware *fw; #define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN); @@ -705,6 +741,21 @@ static int rtl8169_poll(struct napi_struct *napi, int budget); static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); +static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rtl8169_private *tp = netdev_priv(dev); + int cap = tp->pcie_cap; + + if (cap) { + u16 ctl; + + pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); + ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; + pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); + } +} + static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) { void __iomem *ioaddr = tp->mmio_addr; @@ -1043,17 +1094,21 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) return value; } -static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) +static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) { - RTL_W16(IntrMask, 0x0000); + void __iomem *ioaddr = tp->mmio_addr; - RTL_W16(IntrStatus, 0xffff); + RTL_W16(IntrMask, 0x0000); + RTL_W16(IntrStatus, tp->intr_event); + RTL_R8(ChipCmd); } -static void rtl8169_asic_down(void __iomem *ioaddr) +static void rtl8169_asic_down(struct rtl8169_private *tp) { + void __iomem *ioaddr = tp->mmio_addr; + RTL_W8(ChipCmd, 0x00); - rtl8169_irq_mask_and_ack(ioaddr); + rtl8169_irq_mask_and_ack(tp); RTL_R16(CPlusCmd); } @@ -1112,7 +1167,7 @@ static void __rtl8169_check_link_status(struct net_device *dev, netif_carrier_off(dev); netif_info(tp, ifdown, dev, "link down\n"); if (pm) - pm_schedule_suspend(&tp->pci_dev->dev, 100); + pm_schedule_suspend(&tp->pci_dev->dev, 5000); } spin_unlock_irqrestore(&tp->lock, flags); } @@ -1174,7 +1229,6 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) u16 reg; u8 mask; } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, { WAKE_PHY, Config3, LinkUp }, { WAKE_MAGIC, Config3, MagicPacket }, { WAKE_UCAST, Config5, UWF }, @@ -1182,16 +1236,32 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) { WAKE_MCAST, Config5, MWF }, { WAKE_ANY, Config5, LanWake } }; + u8 options; RTL_W8(Cfg9346, Cfg9346_Unlock); for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; + options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; if (wolopts & cfg[i].opt) options |= cfg[i].mask; RTL_W8(cfg[i].reg, options); } + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17: + options = RTL_R8(Config1) & ~PMEnable; + if (wolopts) + options |= PMEnable; + RTL_W8(Config1, options); + break; + default: + options = RTL_R8(Config2) & ~PME_SIGNAL; + if (wolopts) + options |= PME_SIGNAL; + RTL_W8(Config2, options); + break; + } + RTL_W8(Cfg9346, Cfg9346_Lock); } @@ -1373,9 +1443,15 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static u32 rtl8169_fix_features(struct net_device *dev, u32 features) { + struct rtl8169_private *tp = netdev_priv(dev); + if (dev->mtu > TD_MSS_MAX) features &= ~NETIF_F_ALL_TSO; + if (dev->mtu > JUMBO_1K && + !rtl_chip_infos[tp->mac_version].jumbo_tx_csum) + features &= ~NETIF_F_IP_CSUM; + return features; } @@ -2948,22 +3024,24 @@ static const struct rtl_cfg_info { }; /* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, +static unsigned rtl_try_msi(struct rtl8169_private *tp, const struct rtl_cfg_info *cfg) { + void __iomem *ioaddr = tp->mmio_addr; unsigned msi = 0; u8 cfg2; cfg2 = RTL_R8(Config2) & ~MSIEnable; if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(pdev)) { - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); + if (pci_enable_msi(tp->pci_dev)) { + netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n"); } else { cfg2 |= MSIEnable; msi = RTL_FEATURE_MSI; } } - RTL_W8(Config2, cfg2); + if (tp->mac_version <= RTL_GIGA_MAC_VER_06) + RTL_W8(Config2, cfg2); return msi; } @@ -3126,8 +3204,10 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); rtl_writephy(tp, MII_BMCR, 0x0000); - RTL_W32(RxConfig, RTL_R32(RxConfig) | - AcceptBroadcast | AcceptMulticast | AcceptMyPhys); + if (tp->mac_version == RTL_GIGA_MAC_VER_32 || + tp->mac_version == RTL_GIGA_MAC_VER_33) + RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast | + AcceptMulticast | AcceptMyPhys); return; } @@ -3172,8 +3252,8 @@ static void r8168_pll_power_up(struct rtl8169_private *tp) r8168_phy_power_up(tp); } -static void rtl_pll_power_op(struct rtl8169_private *tp, - void (*op)(struct rtl8169_private *)) +static void rtl_generic_op(struct rtl8169_private *tp, + void (*op)(struct rtl8169_private *)) { if (op) op(tp); @@ -3181,12 +3261,12 @@ static void rtl_pll_power_op(struct rtl8169_private *tp, static void rtl_pll_power_down(struct rtl8169_private *tp) { - rtl_pll_power_op(tp, tp->pll_power_ops.down); + rtl_generic_op(tp, tp->pll_power_ops.down); } static void rtl_pll_power_up(struct rtl8169_private *tp) { - rtl_pll_power_op(tp, tp->pll_power_ops.up); + rtl_generic_op(tp, tp->pll_power_ops.up); } static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) @@ -3233,6 +3313,149 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) } } +static void rtl_hw_jumbo_enable(struct rtl8169_private *tp) +{ + rtl_generic_op(tp, tp->jumbo_ops.enable); +} + +static void rtl_hw_jumbo_disable(struct rtl8169_private *tp) +{ + rtl_generic_op(tp, tp->jumbo_ops.disable); +} + +static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); + RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1); + rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT); +} + +static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); + RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1); + rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); +} + +static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); +} + +static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); +} + +static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + struct pci_dev *pdev = tp->pci_dev; + + RTL_W8(MaxTxPacketSize, 0x3f); + RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); + RTL_W8(Config4, RTL_R8(Config4) | 0x01); + pci_write_config_byte(pdev, 0x79, 0x20); +} + +static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + struct pci_dev *pdev = tp->pci_dev; + + RTL_W8(MaxTxPacketSize, 0x0c); + RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); + RTL_W8(Config4, RTL_R8(Config4) & ~0x01); + pci_write_config_byte(pdev, 0x79, 0x50); +} + +static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp) +{ + rtl_tx_performance_tweak(tp->pci_dev, + (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); +} + +static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp) +{ + rtl_tx_performance_tweak(tp->pci_dev, + (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); +} + +static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + r8168b_0_hw_jumbo_enable(tp); + + RTL_W8(Config4, RTL_R8(Config4) | (1 << 0)); +} + +static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + + r8168b_0_hw_jumbo_disable(tp); + + RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); +} + +static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp) +{ + struct jumbo_ops *ops = &tp->jumbo_ops; + + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_11: + ops->disable = r8168b_0_hw_jumbo_disable; + ops->enable = r8168b_0_hw_jumbo_enable; + break; + case RTL_GIGA_MAC_VER_12: + case RTL_GIGA_MAC_VER_17: + ops->disable = r8168b_1_hw_jumbo_disable; + ops->enable = r8168b_1_hw_jumbo_enable; + break; + case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */ + case RTL_GIGA_MAC_VER_19: + case RTL_GIGA_MAC_VER_20: + case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */ + case RTL_GIGA_MAC_VER_22: + case RTL_GIGA_MAC_VER_23: + case RTL_GIGA_MAC_VER_24: + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: + ops->disable = r8168c_hw_jumbo_disable; + ops->enable = r8168c_hw_jumbo_enable; + break; + case RTL_GIGA_MAC_VER_27: + case RTL_GIGA_MAC_VER_28: + ops->disable = r8168dp_hw_jumbo_disable; + ops->enable = r8168dp_hw_jumbo_enable; + break; + case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */ + case RTL_GIGA_MAC_VER_32: + case RTL_GIGA_MAC_VER_33: + ops->disable = r8168e_hw_jumbo_disable; + ops->enable = r8168e_hw_jumbo_enable; + break; + + /* + * No action needed for jumbo frames with 8169. + * No jumbo for 810x at all. + */ + default: + ops->disable = NULL; + ops->enable = NULL; + break; + } +} + static void rtl_hw_reset(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; @@ -3374,6 +3597,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_init_mdio_ops(tp); rtl_init_pll_power_ops(tp); + rtl_init_jumbo_ops(tp); rtl8169_print_mac_version(tp); @@ -3387,7 +3611,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->features |= RTL_FEATURE_WOL; if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(pdev, ioaddr, cfg); + tp->features |= rtl_try_msi(tp, cfg); RTL_W8(Cfg9346, Cfg9346_Lock); if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && @@ -3440,6 +3664,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->intr_event = cfg->intr_event; tp->napi_event = cfg->napi_event; + tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ? + ~(RxBOVF | RxFOVF) : ~0; + init_timer(&tp->timer); tp->timer.data = (unsigned long) dev; tp->timer.function = rtl8169_phy_timer; @@ -3455,6 +3682,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", rtl_chip_infos[chipset].name, dev->base_addr, dev->dev_addr, (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); + if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) { + netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, " + "tx checksumming: %s]\n", + rtl_chip_infos[chipset].jumbo_max, + rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko"); + } if (tp->mac_version == RTL_GIGA_MAC_VER_27 || tp->mac_version == RTL_GIGA_MAC_VER_28 || @@ -3473,6 +3706,7 @@ out: return rc; err_out_msi_4: + netif_napi_del(&tp->napi); rtl_disable_msi(pdev, tp); iounmap(ioaddr); err_out_free_res_3: @@ -3498,6 +3732,8 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) cancel_delayed_work_sync(&tp->task); + netif_napi_del(&tp->napi); + unregister_netdev(dev); rtl_release_firmware(tp); @@ -3611,7 +3847,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; /* Disable interrupts */ - rtl8169_irq_mask_and_ack(ioaddr); + rtl8169_irq_mask_and_ack(tp); if (tp->mac_version == RTL_GIGA_MAC_VER_27 || tp->mac_version == RTL_GIGA_MAC_VER_28 || @@ -3779,21 +4015,6 @@ static void rtl_hw_start_8169(struct net_device *dev) RTL_W16(IntrMask, tp->intr_event); } -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - int cap = tp->pcie_cap; - - if (cap) { - u16 ctl; - - pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); - ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; - pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); - } -} - static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits) { u32 csi; @@ -4093,8 +4314,7 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W16(IntrMitigate, 0x5151); /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11 || - tp->mac_version == RTL_GIGA_MAC_VER_22) { + if (tp->mac_version == RTL_GIGA_MAC_VER_11) { tp->intr_event |= RxFIFOOver | PCSTimeout; tp->intr_event &= ~RxOverflow; } @@ -4276,6 +4496,11 @@ static void rtl_hw_start_8101(struct net_device *dev) void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; + if (tp->mac_version >= RTL_GIGA_MAC_VER_30) { + tp->intr_event &= ~RxFIFOOver; + tp->napi_event &= ~RxFIFOOver; + } + if (tp->mac_version == RTL_GIGA_MAC_VER_13 || tp->mac_version == RTL_GIGA_MAC_VER_16) { int cap = tp->pcie_cap; @@ -4336,9 +4561,17 @@ static void rtl_hw_start_8101(struct net_device *dev) static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) { - if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) + struct rtl8169_private *tp = netdev_priv(dev); + + if (new_mtu < ETH_ZLEN || + new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max) return -EINVAL; + if (new_mtu > ETH_DATA_LEN) + rtl_hw_jumbo_enable(tp); + else + rtl_hw_jumbo_disable(tp); + dev->mtu = new_mtu; netdev_update_features(dev); @@ -4539,7 +4772,7 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) /* Wait for any pending NAPI task to complete */ napi_disable(&tp->napi); - rtl8169_irq_mask_and_ack(ioaddr); + rtl8169_irq_mask_and_ack(tp); tp->intr_mask = 0xffff; RTL_W16(IntrMask, tp->intr_event); @@ -4698,7 +4931,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, u32 opts[2]; int frags; - if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { + if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) { netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); goto err_stop_0; } @@ -4746,10 +4979,10 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, RTL_W8(TxPoll, NPQ); - if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) { + if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) { netif_stop_queue(dev); - smp_rmb(); - if (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS) + smp_mb(); + if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) netif_wake_queue(dev); } @@ -4849,9 +5082,9 @@ static void rtl8169_tx_interrupt(struct net_device *dev, if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; - smp_wmb(); + smp_mb(); if (netif_queue_stopped(dev) && - (TX_BUFFS_AVAIL(tp) >= MAX_SKB_FRAGS)) { + TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) { netif_wake_queue(dev); } /* @@ -4860,7 +5093,6 @@ static void rtl8169_tx_interrupt(struct net_device *dev, * of start_xmit activity is detected (if it is not detected, * it is slow enough). -- FR */ - smp_rmb(); if (tp->cur_tx != dirty_tx) RTL_W8(TxPoll, NPQ); } @@ -4918,7 +5150,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, u32 status; rmb(); - status = le32_to_cpu(desc->opts1); + status = le32_to_cpu(desc->opts1) & tp->opts1_mask; if (status & DescOwn) break; @@ -4938,7 +5170,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, } else { struct sk_buff *skb; dma_addr_t addr = le64_to_cpu(desc->addr); - int pkt_size = (status & 0x00001FFF) - 4; + int pkt_size = (status & 0x00003fff) - 4; /* * The driver does not support incoming fragmented @@ -4971,13 +5203,6 @@ static int rtl8169_rx_interrupt(struct net_device *dev, dev->stats.rx_bytes += pkt_size; dev->stats.rx_packets++; } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } } count = cur_rx - tp->cur_rx; @@ -5001,13 +5226,17 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) */ status = RTL_R16(IntrStatus); while (status && status != 0xffff) { + status &= tp->intr_event; + if (!status) + break; + handled = 1; /* Handle all of the error cases first. These will reset * the chip, so just exit the loop. */ if (unlikely(!netif_running(dev))) { - rtl8169_asic_down(ioaddr); + rtl8169_asic_down(tp); break; } @@ -5015,27 +5244,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) switch (tp->mac_version) { /* Work around for rx fifo overflow */ case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_26: netif_stop_queue(dev); rtl8169_tx_timeout(dev); goto done; - /* Testers needed. */ - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - /* Experimental science. Pktgen proof. */ - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_25: - if (status == RxFIFOOver) - goto done; - break; default: break; } @@ -5130,7 +5341,7 @@ static void rtl8169_down(struct net_device *dev) spin_lock_irq(&tp->lock); - rtl8169_asic_down(ioaddr); + rtl8169_asic_down(tp); /* * At this point device interrupts can not be enabled in any function, * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task, @@ -5376,6 +5587,9 @@ static void rtl_shutdown(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; + struct device *d = &pdev->dev; + + pm_runtime_get_sync(d); rtl8169_net_suspend(dev); @@ -5384,13 +5598,16 @@ static void rtl_shutdown(struct pci_dev *pdev) spin_lock_irq(&tp->lock); - rtl8169_asic_down(ioaddr); + rtl8169_asic_down(tp); spin_unlock_irq(&tp->lock); if (system_state == SYSTEM_POWER_OFF) { - /* WoL fails with some 8168 when the receiver is disabled. */ - if (tp->features & RTL_FEATURE_WOL) { + /* WoL fails with 8168b when the receiver is disabled. */ + if ((tp->mac_version == RTL_GIGA_MAC_VER_11 || + tp->mac_version == RTL_GIGA_MAC_VER_12 || + tp->mac_version == RTL_GIGA_MAC_VER_17) && + (tp->features & RTL_FEATURE_WOL)) { pci_clear_master(pdev); RTL_W8(ChipCmd, CmdRxEnb); @@ -5401,6 +5618,8 @@ static void rtl_shutdown(struct pci_dev *pdev) pci_wake_from_d3(pdev, true); pci_set_power_state(pdev, PCI_D3hot); } + + pm_runtime_put_noidle(d); } static struct pci_driver rtl8169_pci_driver = { diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 7d1651b..be3cade 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1383,6 +1383,11 @@ static int efx_probe_all(struct efx_nic *efx) goto fail2; } + BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT); + if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) { + rc = -EINVAL; + goto fail3; + } efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; rc = efx_probe_channels(efx); if (rc) @@ -1942,6 +1947,7 @@ static int efx_register_netdev(struct efx_nic *efx) net_dev->irq = efx->pci_dev->irq; net_dev->netdev_ops = &efx_netdev_ops; SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); + net_dev->gso_max_segs = EFX_TSO_MAX_SEGS; /* Clear MAC statistics */ efx->mac_op->update_stats(efx); diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index b0d1209..a5d1c60 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h @@ -38,6 +38,7 @@ extern netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc); +extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx); /* RX */ extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); @@ -60,10 +61,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); #define EFX_MAX_EVQ_SIZE 16384UL #define EFX_MIN_EVQ_SIZE 512UL -/* The smallest [rt]xq_entries that the driver supports. Callers of - * efx_wake_queue() assume that they can subsequently send at least one - * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ -#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) +/* Maximum number of TCP segments we support for soft-TSO */ +#define EFX_TSO_MAX_SEGS 100 + +/* The smallest [rt]xq_entries that the driver supports. RX minimum + * is a bit arbitrary. For TX, we must have space for at least 2 + * TSO skbs. + */ +#define EFX_RXQ_MIN_ENT 128U +#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx)) /* Filters */ extern int efx_probe_filters(struct efx_nic *efx); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index d229027..cfaf801 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -677,21 +677,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev, struct ethtool_ringparam *ring) { struct efx_nic *efx = netdev_priv(net_dev); + u32 txq_entries; if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->rx_pending > EFX_MAX_DMAQ_SIZE || ring->tx_pending > EFX_MAX_DMAQ_SIZE) return -EINVAL; - if (ring->rx_pending < EFX_MIN_RING_SIZE || - ring->tx_pending < EFX_MIN_RING_SIZE) { + if (ring->rx_pending < EFX_RXQ_MIN_ENT) { netif_err(efx, drv, efx->net_dev, - "TX and RX queues cannot be smaller than %ld\n", - EFX_MIN_RING_SIZE); + "RX queues cannot be smaller than %u\n", + EFX_RXQ_MIN_ENT); return -EINVAL; } - return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); + txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx)); + if (txq_entries != ring->tx_pending) + netif_warn(efx, drv, efx->net_dev, + "increasing TX queue size to minimum of %u\n", + txq_entries); + + return efx_realloc_channels(efx, ring->rx_pending, txq_entries); } static int efx_ethtool_set_pauseparam(struct net_device *net_dev, diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h index 7443f99..d2405ce 100644 --- a/drivers/net/sfc/nic.h +++ b/drivers/net/sfc/nic.h @@ -65,6 +65,11 @@ enum { #define FALCON_GMAC_LOOPBACKS \ (1 << LOOPBACK_GMAC) +/* Alignment of PCIe DMA boundaries (4KB) */ +#define EFX_PAGE_SIZE 4096 +/* Size and alignment of buffer table entries (same) */ +#define EFX_BUF_SIZE EFX_PAGE_SIZE + /** * struct falcon_board_type - board operations and type information * @id: Board type id, as found in NVRAM diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index 84eb99e..6d3b68a 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -115,6 +115,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr) return len; } +unsigned int efx_tx_max_skb_descs(struct efx_nic *efx) +{ + /* Header and payload descriptor for each output segment, plus + * one for every input fragment boundary within a segment + */ + unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; + + /* Possibly one more per segment for the alignment workaround */ + if (EFX_WORKAROUND_5391(efx)) + max_descs += EFX_TSO_MAX_SEGS; + + /* Possibly more for PCIe page boundaries within input fragments */ + if (PAGE_SIZE > EFX_PAGE_SIZE) + max_descs += max_t(unsigned int, MAX_SKB_FRAGS, + DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); + + return max_descs; +} + /* * Add a socket buffer to a TX queue * diff --git a/drivers/net/skge.c b/drivers/net/skge.c index f4be5c7..b446e7e 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -4097,6 +4097,13 @@ static struct dmi_system_id skge_32bit_dma_boards[] = { DMI_MATCH(DMI_BOARD_NAME, "nForce"), }, }, + { + .ident = "ASUS P5NSLI", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "P5NSLI") + }, + }, {} }; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 80df3a8..5f93956 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2344,8 +2344,13 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2, skb_copy_from_linear_data(re->skb, skb->data, length); skb->ip_summed = re->skb->ip_summed; skb->csum = re->skb->csum; + skb->rxhash = re->skb->rxhash; + skb->vlan_tci = re->skb->vlan_tci; + pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr, length, PCI_DMA_FROMDEVICE); + re->skb->vlan_tci = 0; + re->skb->rxhash = 0; re->skb->ip_summed = CHECKSUM_NONE; skb_put(skb, length); } @@ -2430,9 +2435,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev, struct sk_buff *skb = NULL; u16 count = (status & GMR_FS_LEN) >> 16; - if (status & GMR_FS_VLAN) - count -= VLAN_HLEN; /* Account for vlan tag */ - netif_printk(sky2, rx_status, KERN_DEBUG, dev, "rx slot %u status 0x%x len %d\n", sky2->rx_next, status, length); @@ -2440,6 +2442,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; prefetch(sky2->rx_ring + sky2->rx_next); + if (vlan_tx_tag_present(re->skb)) + count -= VLAN_HLEN; /* Account for vlan tag */ + /* This chip has hardware problems that generates bogus status. * So do only marginal checking and expect higher level protocols * to handle crap frames. @@ -2497,11 +2502,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) } static inline void sky2_skb_rx(const struct sky2_port *sky2, - u32 status, struct sk_buff *skb) + struct sk_buff *skb) { - if (status & GMR_FS_VLAN) - __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag)); - if (skb->ip_summed == CHECKSUM_NONE) netif_receive_skb(skb); else @@ -2555,6 +2557,14 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status) } } +static void sky2_rx_tag(struct sky2_port *sky2, u16 length) +{ + struct sk_buff *skb; + + skb = sky2->rx_ring[sky2->rx_next].skb; + __vlan_hwaccel_put_tag(skb, be16_to_cpu(length)); +} + static void sky2_rx_hash(struct sky2_port *sky2, u32 status) { struct sk_buff *skb; @@ -2613,8 +2623,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) } skb->protocol = eth_type_trans(skb, dev); - - sky2_skb_rx(sky2, status, skb); + sky2_skb_rx(sky2, skb); /* Stop after net poll weight */ if (++work_done >= to_do) @@ -2622,11 +2631,11 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) break; case OP_RXVLAN: - sky2->rx_tag = length; + sky2_rx_tag(sky2, length); break; case OP_RXCHKSVLAN: - sky2->rx_tag = length; + sky2_rx_tag(sky2, length); /* fall through */ case OP_RXCHKS: if (likely(dev->features & NETIF_F_RXCSUM)) @@ -2920,8 +2929,10 @@ static irqreturn_t sky2_intr(int irq, void *dev_id) /* Reading this mask interrupts as side effect */ status = sky2_read32(hw, B0_Y2_SP_ISRC2); - if (status == 0 || status == ~0) + if (status == 0 || status == ~0) { + sky2_write32(hw, B0_Y2_SP_ICR, 2); return IRQ_NONE; + } prefetch(&hw->st_le[hw->st_idx]); @@ -4197,10 +4208,12 @@ static int sky2_set_features(struct net_device *dev, u32 features) struct sky2_port *sky2 = netdev_priv(dev); u32 changed = dev->features ^ features; - if (changed & NETIF_F_RXCSUM) { - u32 on = features & NETIF_F_RXCSUM; - sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), - on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + if ((changed & NETIF_F_RXCSUM) && + !(sky2->hw->flags & SKY2_HW_NEW_LE)) { + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[sky2->port], Q_CSR), + (features & NETIF_F_RXCSUM) + ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } if (changed & NETIF_F_RXHASH) diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 318c9ae..a79a166 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -2236,7 +2236,6 @@ struct sky2_port { u16 rx_pending; u16 rx_data_size; u16 rx_nfrags; - u16 rx_tag; struct { unsigned long last; diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index ab59300..361beb7 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2363,7 +2363,7 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_detach(dev); /* Switch off MAC, remember WOL setting */ - gp->asleep_wol = gp->wake_on_lan; + gp->asleep_wol = !!gp->wake_on_lan; gem_do_stop(dev, gp->asleep_wol); } else gp->asleep_wol = 0; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index bc8c183..eaa24fa8 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -740,8 +740,13 @@ static inline unsigned int tg3_has_work(struct tg3_napi *tnapi) if (sblk->status & SD_STATUS_LINK_CHG) work_exists = 1; } - /* check for RX/TX work to do */ - if (sblk->idx[0].tx_consumer != tnapi->tx_cons || + + /* check for TX work to do */ + if (sblk->idx[0].tx_consumer != tnapi->tx_cons) + work_exists = 1; + + /* check for RX work to do */ + if (tnapi->rx_rcb_prod_idx && *(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr) work_exists = 1; @@ -991,14 +996,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); } -#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ - MII_TG3_AUXCTL_ACTL_TX_6DB) +static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) +{ + u32 val; + int err; -#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_TX_6DB); + err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); + + if (err) + return err; + if (enable) + + val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + else + val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + + err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, + val | MII_TG3_AUXCTL_ACTL_TX_6DB); + + return err; +} static int tg3_bmcr_reset(struct tg3 *tp) { @@ -1770,7 +1787,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) otp = tp->phy_otp; - if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) + if (tg3_phy_toggle_auxctl_smdsp(tp, true)) return; phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); @@ -1795,7 +1812,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) @@ -1843,9 +1860,9 @@ static void tg3_phy_eee_enable(struct tg3 *tp) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0003); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -1990,7 +2007,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) (MII_TG3_CTRL_AS_MASTER | MII_TG3_CTRL_ENABLE_AS_MASTER)); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (err) return err; @@ -2011,7 +2028,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); @@ -2100,10 +2117,10 @@ static int tg3_phy_reset(struct tg3 *tp) out: if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x201f, 0x2aaa); tg3_phydsp_write(tp, 0x000a, 0x0323); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { @@ -2112,14 +2129,14 @@ out: } if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x000a, 0x310b); tg3_phydsp_write(tp, 0x201f, 0x9506); tg3_phydsp_write(tp, 0x401f, 0x14e2); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); @@ -2128,7 +2145,7 @@ out: } else tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } @@ -2976,7 +2993,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) tw32(TG3_CPMU_EEE_MODE, tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (!err) { u32 err2; @@ -3003,7 +3020,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) val |= MDIO_AN_EEE_ADV_1000T; err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); - err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + err2 = tg3_phy_toggle_auxctl_smdsp(tp, false); if (!err) err = err2; } @@ -5216,6 +5233,9 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) return work_done; } + if (!tnapi->rx_rcb_prod_idx) + return work_done; + /* run RX thread, within the bounds set by NAPI. * All RX "locking" is done by ensuring outside * code synchronizes with tg3->napi.poll() @@ -5654,6 +5674,9 @@ static void tg3_poll_controller(struct net_device *dev) int i; struct tg3 *tp = netdev_priv(dev); + if (tg3_irq_sync(tp)) + return; + for (i = 0; i < tp->irq_cnt; i++) tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); } @@ -6626,6 +6649,12 @@ static int tg3_alloc_consistent(struct tg3 *tp) */ switch (i) { default: + if (tg3_flag(tp, ENABLE_RSS)) { + tnapi->rx_rcb_prod_idx = NULL; + break; + } + /* Fall through */ + case 1: tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer; break; case 2: @@ -13633,9 +13662,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tg3_flag(tp, HW_TSO_1) || tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3) || - (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF))) + tp->fw_needed) { + /* For firmware TSO, assume ASF is disabled. + * We'll disable TSO later if we discover ASF + * is enabled in tg3_get_eeprom_hw_cfg(). + */ tg3_flag_set(tp, TSO_CAPABLE); - else { + } else { tg3_flag_clear(tp, TSO_CAPABLE); tg3_flag_clear(tp, TSO_BUG); tp->fw_needed = NULL; @@ -13671,8 +13704,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ tg3_flag_set(tp, 4G_DMA_BNDRY_BUG); - if (tg3_flag(tp, 5755_PLUS)) - tg3_flag_set(tp, SHORT_DMA_BUG); + if (tg3_flag(tp, 5755_PLUS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + tg3_flag_set(tp, SHORT_DMA_BUG); else tg3_flag_set(tp, 40BIT_DMA_LIMIT_BUG); @@ -13873,6 +13907,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) */ tg3_get_eeprom_hw_cfg(tp); + if (tp->fw_needed && tg3_flag(tp, ENABLE_ASF)) { + tg3_flag_clear(tp, TSO_CAPABLE); + tg3_flag_clear(tp, TSO_BUG); + tp->fw_needed = NULL; + } + if (tg3_flag(tp, ENABLE_APE)) { /* Allow reads and writes to the * APE register and memory space. @@ -14956,6 +14996,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pm_cap = pm_cap; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; + tp->irq_sync = 1; if (tg3_debug > 0) tp->msg_enable = tg3_debug; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 76b8650..3cc22b9 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1245,10 +1245,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, } #endif - if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) + if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) { if (copy_from_user(&ifr, argp, ifreq_len)) return -EFAULT; - + } else { + memset(&ifr, 0, sizeof(ifr)); + } if (cmd == TUNGETFEATURES) { /* Currently this just means: "what IFF flags are valid?". * This is needed because we never checked for invalid flags on diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 3e33573..e2a988c 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -398,7 +398,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, u32 packet_len; u32 padbytes = 0xffff0000; - padlen = ((skb->len + 4) % 512) ? 0 : 4; + padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4; if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) { @@ -420,7 +420,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, cpu_to_le32s(&packet_len); skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); - if ((skb->len % 512) == 0) { + if (padlen) { cpu_to_le32s(&padbytes); memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); skb_put(skb, sizeof(padbytes)); @@ -1537,6 +1537,10 @@ static const struct usb_device_id products [] = { USB_DEVICE (0x2001, 0x3c05), .driver_info = (unsigned long) &ax88772_info, }, { + // DLink DUB-E100 H/W Ver C1 + USB_DEVICE (0x2001, 0x1a02), + .driver_info = (unsigned long) &ax88772_info, +}, { // Linksys USB1000 USB_DEVICE (0x1737, 0x0039), .driver_info = (unsigned long) &ax88178_info, diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 13919dd..544c309 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -83,6 +83,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) struct cdc_state *info = (void *) &dev->data; int status; int rndis; + bool android_rndis_quirk = false; struct usb_driver *driver = driver_of(intf); struct usb_cdc_mdlm_desc *desc = NULL; struct usb_cdc_mdlm_detail_desc *detail = NULL; @@ -195,6 +196,11 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) info->control, info->u->bSlaveInterface0, info->data); + /* fall back to hard-wiring for RNDIS */ + if (rndis) { + android_rndis_quirk = true; + goto next_desc; + } goto bad_desc; } if (info->control != intf) { @@ -271,11 +277,15 @@ next_desc: /* Microsoft ActiveSync based and some regular RNDIS devices lack the * CDC descriptors, so we'll hard-wire the interfaces and not check * for descriptors. + * + * Some Android RNDIS devices have a CDC Union descriptor pointing + * to non-existing interfaces. Ignore that and attempt the same + * hard-wired 0 and 1 interfaces. */ - if (rndis && !info->u) { + if (rndis && (!info->u || android_rndis_quirk)) { info->control = usb_ifnum_to_if(dev->udev, 0); info->data = usb_ifnum_to_if(dev->udev, 1); - if (!info->control || !info->data) { + if (!info->control || !info->data || info->control != intf) { dev_dbg(&intf->dev, "rndis: master #0/%p slave #1/%p\n", info->control, @@ -472,6 +482,7 @@ static const struct driver_info wwan_info = { /*-------------------------------------------------------------------------*/ #define HUAWEI_VENDOR_ID 0x12D1 +#define NOVATEL_VENDOR_ID 0x1410 static const struct usb_device_id products [] = { /* @@ -589,6 +600,21 @@ static const struct usb_device_id products [] = { * because of bugs/quirks in a given product (like Zaurus, above). */ { + /* Novatel USB551L */ + /* This match must come *before* the generic CDC-ETHER match so that + * we get FLAG_WWAN set on the device, since it's descriptors are + * generic CDC-ETHER. + */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = NOVATEL_VENDOR_ID, + .idProduct = 0xB001, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = (unsigned long)&wwan_info, +}, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 9cf4e47..ab43674 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -59,8 +59,10 @@ #define USB_PRODUCT_IPHONE_3G 0x1292 #define USB_PRODUCT_IPHONE_3GS 0x1294 #define USB_PRODUCT_IPHONE_4 0x1297 +#define USB_PRODUCT_IPAD 0x129a #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 +#define USB_PRODUCT_IPHONE_5 0x12a8 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -101,6 +103,10 @@ static struct usb_device_id ipheth_table[] = { IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPAD, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, @@ -108,6 +114,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index ad0298f..3362449 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1308,7 +1308,7 @@ static int kaweth_internal_control_msg(struct usb_device *usb_dev, int retv; int length = 0; /* shut up GCC */ - urb = usb_alloc_urb(0, GFP_NOIO); + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index ed1b432..e773250 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -678,7 +678,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) return -EIO; } - *datap = *attrdata; + *datap = le16_to_cpu(*attrdata); kfree(attrdata); return result; @@ -943,7 +943,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, } static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; -static const struct sierra_net_info_data sierra_net_info_data_68A3 = { +static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { .rx_urb_size = 8 * 1024, .whitelist = { .infolen = ARRAY_SIZE(sierra_net_ifnum_list), @@ -951,7 +951,7 @@ static const struct sierra_net_info_data sierra_net_info_data_68A3 = { } }; -static const struct driver_info sierra_net_info_68A3 = { +static const struct driver_info sierra_net_info_direct_ip = { .description = "Sierra Wireless USB-to-WWAN Modem", .flags = FLAG_WWAN | FLAG_SEND_ZLP, .bind = sierra_net_bind, @@ -959,12 +959,18 @@ static const struct driver_info sierra_net_info_68A3 = { .status = sierra_net_status, .rx_fixup = sierra_net_rx_fixup, .tx_fixup = sierra_net_tx_fixup, - .data = (unsigned long)&sierra_net_info_data_68A3, + .data = (unsigned long)&sierra_net_info_data_direct_ip, }; static const struct usb_device_id products[] = { {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ - .driver_info = (unsigned long) &sierra_net_info_68A3}, + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, {}, /* last item */ }; diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index f74f3ce..e5c15bb 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1190,7 +1190,7 @@ static const struct driver_info smsc95xx_info = { .rx_fixup = smsc95xx_rx_fixup, .tx_fixup = smsc95xx_tx_fixup, .status = smsc95xx_status, - .flags = FLAG_ETHER | FLAG_SEND_ZLP, + .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR, }; static const struct usb_device_id products[] = { diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index ed9c78b..bc2e489 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -316,7 +316,7 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list, enum skb_state state) { unsigned long flags; - enum skb_state old_state; + enum skb_state old_state; struct skb_data *entry = (struct skb_data *) skb->cb; spin_lock_irqsave(&list->lock, flags); @@ -526,7 +526,7 @@ block: if (urb) { if (netif_running (dev->net) && - !test_bit(EVENT_RX_HALT, &dev->flags) && + !test_bit (EVENT_RX_HALT, &dev->flags) && state != unlink_start) { rx_submit (dev, urb, GFP_ATOMIC); usb_mark_last_busy(dev->udev); @@ -1188,6 +1188,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, usb_anchor_urb(urb, &dev->deferred); /* no use to process more packets */ netif_stop_queue(net); + usb_put_urb(urb); spin_unlock_irqrestore(&dev->txq.lock, flags); netdev_dbg(dev->net, "Delaying transmission for resumption\n"); goto deferred; @@ -1329,6 +1330,8 @@ void usbnet_disconnect (struct usb_interface *intf) cancel_work_sync(&dev->kevent); + usb_scuttle_anchored_urbs(&dev->deferred); + if (dev->driver_info->unbind) dev->driver_info->unbind (dev, intf); diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index f1e1643..78c51ab 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -8,6 +8,7 @@ * as published by the Free Software Foundation. */ +#include <linux/module.h> #include <linux/bitops.h> #include <linux/cdev.h> #include <linux/dma-mapping.h> diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index 6650fde..9f1e947 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h @@ -152,6 +152,9 @@ enum { /* Device IDs */ USB_DEVICE_ID_I6050 = 0x0186, USB_DEVICE_ID_I6050_2 = 0x0188, + USB_DEVICE_ID_I6150 = 0x07d6, + USB_DEVICE_ID_I6150_2 = 0x07d7, + USB_DEVICE_ID_I6150_3 = 0x07d9, USB_DEVICE_ID_I6250 = 0x0187, }; diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 298f2b0..0ddc8db 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -491,6 +491,9 @@ int i2400mu_probe(struct usb_interface *iface, switch (id->idProduct) { case USB_DEVICE_ID_I6050: case USB_DEVICE_ID_I6050_2: + case USB_DEVICE_ID_I6150: + case USB_DEVICE_ID_I6150_2: + case USB_DEVICE_ID_I6150_3: case USB_DEVICE_ID_I6250: i2400mu->i6050 = 1; break; @@ -740,6 +743,9 @@ static struct usb_device_id i2400mu_id_table[] = { { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) }, { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, { USB_DEVICE(0x8086, 0x0181) }, { USB_DEVICE(0x8086, 0x1403) }, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 029773c..c84c493 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -34,98 +34,98 @@ static const u32 ar9300_2p2_radio_postamble[][5] = { static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, - {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, - {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, - {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, + {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, + {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, + {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, + {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index ab21a49..7f7bc94 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -69,13 +69,13 @@ #define AR9300_BASE_ADDR 0x3ff #define AR9300_BASE_ADDR_512 0x1ff -#define AR9300_OTP_BASE 0x14000 -#define AR9300_OTP_STATUS 0x15f18 +#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000) +#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18) #define AR9300_OTP_STATUS_TYPE 0x7 #define AR9300_OTP_STATUS_VALID 0x4 #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 #define AR9300_OTP_STATUS_SM_BUSY 0x1 -#define AR9300_OTP_READ_DATA 0x15f1c +#define AR9300_OTP_READ_DATA (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c) enum targetPowerHTRates { HT_TARGET_RATE_0_8_16, diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index d4d8cec..b109c47 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -159,6 +159,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_buf_addr = 0; + bf->bf_mpdu = NULL; } /* Get a new beacon from mac80211 */ diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 1b90ed8..4f7843a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -342,6 +342,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, skb, htc_hdr->endpoint_id, txok); + } else { + kfree_skb(skb); } } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7c2f06e..9130a5a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -530,7 +530,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || - ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) && + ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) && !ah->is_pciexpress)) { ah->config.serialize_regmode = SER_REG_MODE_ON; @@ -682,13 +682,25 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); + int i = 0; + REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); udelay(100); REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); - while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) + while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) { + udelay(100); + if (WARN_ON_ONCE(i >= 100)) { + ath_err(common, "PLL4 meaurement not done\n"); + break; + } + + i++; + } + return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; } EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a126a3e..633f962 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -648,6 +648,15 @@ void ath_hw_pll_work(struct work_struct *work) hw_pll_work.work); u32 pll_sqsum; + /* + * ensure that the PLL WAR is executed only + * after the STA is associated (or) if the + * beaconing had started in interfaces that + * uses beacons. + */ + if (!(sc->sc_flags & SC_OP_BEACONS)) + return; + if (AR_SREV_9485(sc->sc_ah)) { ath9k_ps_wakeup(sc); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 3b5f9d6..932b3ab 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1697,7 +1697,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) struct ieee80211_hw *hw = sc->hw; struct ieee80211_hdr *hdr; int retval; - bool decrypt_error = false; struct ath_rx_status rs; enum ath9k_rx_qtype qtype; bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); @@ -1719,6 +1718,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) tsf_lower = tsf & 0xffffffff; do { + bool decrypt_error = false; /* If handling rx interrupt and flush is in progress => exit */ if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) break; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 33443bc..6f6f100 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -272,6 +272,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) } bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + bf->bf_next = NULL; list_del(&bf->list); spin_unlock_bh(&sc->tx.txbuflock); @@ -1488,6 +1489,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, if (tid) INCR(tid->seq_start, IEEE80211_SEQ_MAX); + bf->bf_next = NULL; bf->bf_lastbf = bf; fi = get_frame_info(bf->bf_mpdu); ath_buf_set_rate(sc, bf, fi->framelen); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1ab8861..4e8b481 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3843,6 +3843,8 @@ static void b43legacy_remove(struct ssb_device *dev) cancel_work_sync(&wldev->restart_work); B43legacy_WARN_ON(!wl); + if (!wldev->fw.ucode) + return; /* NULL if fw never loaded */ if (wl->current_dev == wldev) ieee80211_unregister_hw(wl->hw); diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index 2f801f2..3d06eeb 100644 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -1,33 +1,47 @@ +config BCMDHD + tristate "Broadcom 43xx wireless cards support" + depends on MMC + default m + ---help--- + This module adds support for wireless adapters based on + Broadcom 4329/30 chipset. + + This driver uses the kernel's wireless extensions subsystem. + + If you choose to build a module, it'll be called dhd. Say M if + unsure. + config BCM4330 - tristate "Broadcom 4330 wireless cards support" - depends on WLAN + bool "Broadcom 4330 wireless cards support" + depends on BCMDHD ---help--- This module adds support for wireless adapters based on Broadcom 4330 chipset. config BCM4334 - tristate "Broadcom 4334 wireless cards support" - depends on WLAN + bool "Broadcom 4334 wireless cards support" + depends on BCMDHD + default y ---help--- This module adds support for wireless adapters based on Broadcom 4334 chipset. config BCM43241 - tristate "Broadcom 43241 wireless cards support" - depends on WLAN + bool "Broadcom 43241 wireless cards support" + depends on BCMDHD ---help--- This module adds support for wireless adapters based on Broadcom 43241 chipset. config BCMDHD_FW_PATH - depends on WLAN + depends on BCMDHD string "Firmware path" default "/system/etc/firmware/fw_bcmdhd.bin" ---help--- Path to the firmware file. config BCMDHD_NVRAM_PATH - depends on WLAN + depends on BCMDHD string "NVRAM path" default "/system/etc/wifi/bcmdhd.cal" ---help--- diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index c92c209..e115d07 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -39,6 +39,8 @@ DHDCFLAGS += -DDUAL_ESCAN_RESULT_BUFFER DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API DHDCFLAGS += -DDISABLE_FW_ROAM_SUSPEND +DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65 +DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15 # For Static Buffer ifeq ($(CONFIG_BROADCOM_WIFI_RESERVED_MEM),y) @@ -84,17 +86,16 @@ ifneq ($(CONFIG_BCM4334),) DHDCFLAGS += -DUSE_CID_CHECK -DCONFIG_CONTROL_PM DHDCFLAGS += -DPROP_TXSTATUS DHDCFLAGS += -DVSDB -DHT40_GO - DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST + DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST -DSDIO_CRC_ERROR_FIX + DHDCFLAGS += -DCUSTOM_SDIO_F2_BLKSIZE=128 DHDCFLAGS += -DDHD_USE_IDLECOUNT DHDCFLAGS += -DSUPPORT_AMPDU_MPDU_CMD DHDCFLAGS += -DVSDB_DYNAMIC_F2_BLKSIZE -DSDIO_F2_BLKSIZE=512 -DVSDB_F2_BLKSIZE=64 DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 -DENABLE_BCN_LI_BCN_WAKEUP -ifeq ($(CONFIG_MACH_M3_JPN_DCM),y) - DHDCFLAGS += -DUSE_WEP_AUTH_SHARED_OPEN -endif +# DHDCFLAGS += -DUSE_WEP_AUTH_SHARED_OPEN DHDCFLAGS += -DROAM_AP_ENV_DETECTION DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DWL11U + DHDCFLAGS += -DPASS_ARP_PACKET endif ifneq ($(CONFIG_BCM4330),) @@ -121,7 +122,6 @@ ifneq ($(CONFIG_BCM43241),) endif endif - ############################# # Platform dependent feature ############################# @@ -192,7 +192,7 @@ DHDCFLAGS += -DWLAN_REGION_CODE=$(REGION_CODE) # Others ######### -#EXTRA_LDFLAGS += --strip-debug +EXTRA_LDFLAGS += --strip-debug EXTRA_CFLAGS += $(DHDCFLAGS) -DDHD_DEBUG EXTRA_CFLAGS += -DSRCBASE=\"$(src)\" @@ -212,17 +212,6 @@ DHDOFILES :=$(filter-out bcmsdh_sdmmc.o,$(DHDOFILES)) DHDOFILES :=$(filter-out bcmsdh_sdmmc_linux.o,$(DHDOFILES)) endif -dhd-y := $(DHDOFILES) -obj-m += dhd.o - -all: - @echo "$(MAKE) --no-print-directory -C $(KDIR) SUBDIRS=$(CURDIR) modules" - @$(MAKE) --no-print-directory -C $(KDIR) SUBDIRS=$(CURDIR) modules - -clean: - rm -rf *.o *.ko *.mod.c *~ .*.cmd *.o.cmd .*.o.cmd \ - Module.symvers modules.order .tmp_versions modules.builtin +obj-$(CONFIG_BCMDHD) += dhd.o +dhd-objs += $(DHDOFILES) -install: - @$(MAKE) --no-print-directory -C $(KDIR) \ - SUBDIRS=$(CURDIR) modules_install diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c index c743d09..8137701 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c @@ -62,12 +62,13 @@ extern int sdio_reset_comm(struct mmc_card *card); extern PBCMSDH_SDMMC_INSTANCE gInstance; -uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */ -#if defined(SDIO_F2_BLKSIZE) -uint sd_f2_blocksize = SDIO_F2_BLKSIZE; -#else -uint sd_f2_blocksize = 512; /* Default blocksize */ +#define DEFAULT_SDIO_F2_BLKSIZE 512 +#ifndef CUSTOM_SDIO_F2_BLKSIZE +#define CUSTOM_SDIO_F2_BLKSIZE DEFAULT_SDIO_F2_BLKSIZE #endif + +uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */ +uint sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE; uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */ uint sd_power = 1; /* Default to SD Slot powered ON */ @@ -81,6 +82,7 @@ DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait); DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait); #define DMA_ALIGN_MASK 0x03 +#define MMC_SDIO_ABORT_RETRY_LIMIT 5 int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data); @@ -792,7 +794,9 @@ extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) { int err_ret; - +#if defined(MMC_SDIO_ABORT) + int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; +#endif sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); DHD_PM_RESUME_WAIT(sdioh_request_byte_wait); @@ -826,16 +830,20 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by #if defined(MMC_SDIO_ABORT) /* to allow abort command through F1 */ else if (regaddr == SDIOD_CCCR_IOABORT) { - if (gInstance->func[func]) { - sdio_claim_host(gInstance->func[func]); - /* - * this sdio_f0_writeb() can be replaced with another api - * depending upon MMC driver change. - * As of this time, this is temporaray one - */ - sdio_writeb(gInstance->func[func], - *byte, regaddr, &err_ret); - sdio_release_host(gInstance->func[func]); + while (sdio_abort_retry--) { + if (gInstance->func[func]) { + sdio_claim_host(gInstance->func[func]); + /* + * this sdio_f0_writeb() can be replaced with + * another api depending upon MMC driver change. + * As of this time, this is temporaray one + */ + sdio_writeb(gInstance->func[func], + *byte, regaddr, &err_ret); + sdio_release_host(gInstance->func[func]); + } + if (!err_ret) + break; } } #endif /* MMC_SDIO_ABORT */ @@ -884,6 +892,9 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add uint32 *word, uint nbytes) { int err_ret = SDIOH_API_RC_FAIL; +#if defined(MMC_SDIO_ABORT) + int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; +#endif if (func == 0) { sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__)); @@ -920,8 +931,29 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add sdio_release_host(gInstance->func[func]); if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x", +#if defined(MMC_SDIO_ABORT) + /* Any error on CMD53 transaction should abort that function using function 0. */ + while (sdio_abort_retry--) { + if (gInstance->func[0]) { + sdio_claim_host(gInstance->func[0]); + /* + * this sdio_f0_writeb() can be replaced with another api + * depending upon MMC driver change. + * As of this time, this is temporaray one + */ + sdio_writeb(gInstance->func[0], + func, SDIOD_CCCR_IOABORT, &err_ret); + sdio_release_host(gInstance->func[0]); + } + if (!err_ret) + break; + } + if (err_ret) +#endif /* MMC_SDIO_ABORT */ + { + sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x\n", rw ? "Write" : "Read", err_ret)); + } } return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 36f2a6c..ed37e8c 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc_linux.c 353908 2012-08-29 08:09:02Z $ + * $Id: bcmsdh_sdmmc_linux.c 355594 2012-09-07 10:22:02Z $ */ #include <typedefs.h> @@ -192,7 +192,7 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) if (func->num != 2) return 0; - sd_trace(("%s Enter\n", __FUNCTION__)); + sd_trace_hw4(("%s Enter\n", __FUNCTION__)); if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) return -EBUSY; @@ -232,7 +232,7 @@ static int bcmsdh_sdmmc_resume(struct device *pdev) struct sdio_func *func = dev_to_sdio_func(pdev); #endif /* defined(OOB_INTR_ONLY) */ #endif /* defined(CUSTOMER_HW4) */ - sd_trace(("%s Enter\n", __FUNCTION__)); + sd_trace_hw4(("%s Enter\n", __FUNCTION__)); dhd_mmc_suspend = FALSE; #if !defined(CUSTOMER_HW4) diff --git a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c index e834366..2dbb168 100644..100755 --- a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c @@ -2,13 +2,13 @@ * Broadcom SPI Host Controller Driver - Linux Per-port * * Copyright (C) 1999-2012, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,7 +16,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. diff --git a/drivers/net/wireless/bcmdhd/bcmspibrcm.c b/drivers/net/wireless/bcmdhd/bcmspibrcm.c index d5f5754..d5f5754 100644..100755 --- a/drivers/net/wireless/bcmdhd/bcmspibrcm.c +++ b/drivers/net/wireless/bcmdhd/bcmspibrcm.c diff --git a/drivers/net/wireless/bcmdhd/bcmutils.c b/drivers/net/wireless/bcmdhd/bcmutils.c index 272201b..0646195 100644 --- a/drivers/net/wireless/bcmdhd/bcmutils.c +++ b/drivers/net/wireless/bcmdhd/bcmutils.c @@ -336,13 +336,6 @@ pktq_pdeq_tail(struct pktq *pq, int prec) if ((p = q->head) == NULL) return NULL; -#if defined(CONFIG_MACH_M3_JPN_DCM) - if (!q || !(q->tail)) { - printk(" %s : tail is NULL \n", __func__); - return NULL; - } -#endif - for (prev = NULL; p != q->tail; p = PKTLINK(p)) prev = p; diff --git a/drivers/net/wireless/bcmdhd/bcmwifi.c b/drivers/net/wireless/bcmdhd/bcmwifi.c new file mode 100644 index 0000000..7072217 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/bcmwifi.c @@ -0,0 +1,274 @@ +/* + * Misc utility routines used by kernel or app-level. + * Contents are wifi-specific, used by any kernel or app-level + * software that might want wifi things as it grows. + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * $Id: bcmwifi.c,v 1.31.8.1 2010-08-03 17:47:05 Exp $ + */ + + +#include <typedefs.h> + +#ifdef BCMDRIVER +#include <osl.h> +#include <bcmutils.h> +#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) +#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) +#else +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#ifndef ASSERT +#define ASSERT(exp) +#endif +#endif +#include <bcmwifi.h> + +#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL)) +#include <bcmstdlib.h> +#endif + + + + + +char * +wf_chspec_ntoa(chanspec_t chspec, char *buf) +{ + const char *band, *bw, *sb; + uint channel; + + band = ""; + bw = ""; + sb = ""; + channel = CHSPEC_CHANNEL(chspec); + + if ((CHSPEC_IS2G(chspec) && channel > CH_MAX_2G_CHANNEL) || + (CHSPEC_IS5G(chspec) && channel <= CH_MAX_2G_CHANNEL)) + band = (CHSPEC_IS2G(chspec)) ? "b" : "a"; + if (CHSPEC_IS40(chspec)) { + if (CHSPEC_SB_UPPER(chspec)) { + sb = "u"; + channel += CH_10MHZ_APART; + } else { + sb = "l"; + channel -= CH_10MHZ_APART; + } + } else if (CHSPEC_IS10(chspec)) { + bw = "n"; + } + + + snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb); + return (buf); +} + + +chanspec_t +wf_chspec_aton(char *a) +{ + char *endp = NULL; + uint channel, band, bw, ctl_sb; + char c; + + channel = strtoul(a, &endp, 10); + + + if (endp == a) + return 0; + + if (channel > MAXCHANNEL) + return 0; + + band = ((channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); + bw = WL_CHANSPEC_BW_20; + ctl_sb = WL_CHANSPEC_CTL_SB_NONE; + + a = endp; + + c = tolower(a[0]); + if (c == '\0') + goto done; + + + if (c == 'a' || c == 'b') { + band = (c == 'a') ? WL_CHANSPEC_BAND_5G : WL_CHANSPEC_BAND_2G; + a++; + c = tolower(a[0]); + if (c == '\0') + goto done; + } + + + if (c == 'n') { + bw = WL_CHANSPEC_BW_10; + } else if (c == 'l') { + bw = WL_CHANSPEC_BW_40; + ctl_sb = WL_CHANSPEC_CTL_SB_LOWER; + + if (channel <= (MAXCHANNEL - CH_20MHZ_APART)) + channel += CH_10MHZ_APART; + else + return 0; + } else if (c == 'u') { + bw = WL_CHANSPEC_BW_40; + ctl_sb = WL_CHANSPEC_CTL_SB_UPPER; + + if (channel > CH_20MHZ_APART) + channel -= CH_10MHZ_APART; + else + return 0; + } else { + return 0; + } + +done: + return (channel | band | bw | ctl_sb); +} + + +bool +wf_chspec_malformed(chanspec_t chanspec) +{ + + if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec)) + return TRUE; + + if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec)) + return TRUE; + + + if (CHSPEC_IS20_UNCOND(chanspec)) { + if (!CHSPEC_SB_NONE(chanspec)) + return TRUE; + } else { + if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) + return TRUE; + } + + return FALSE; +} + + +uint8 +wf_chspec_ctlchan(chanspec_t chspec) +{ + uint8 ctl_chan; + + + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { + return CHSPEC_CHANNEL(chspec); + } else { + + ASSERT(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_40); + + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { + + ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); + } else { + ASSERT(CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_LOWER); + + ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); + } + } + + return ctl_chan; +} + +chanspec_t +wf_chspec_ctlchspec(chanspec_t chspec) +{ + chanspec_t ctl_chspec = 0; + uint8 channel; + + ASSERT(!wf_chspec_malformed(chspec)); + + + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { + return chspec; + } else { + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { + channel = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); + } else { + channel = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); + } + ctl_chspec = channel | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; + ctl_chspec |= CHSPEC_BAND(chspec); + } + return ctl_chspec; +} + + +int +wf_mhz2channel(uint freq, uint start_factor) +{ + int ch = -1; + uint base; + int offset; + + + if (start_factor == 0) { + if (freq >= 2400 && freq <= 2500) + start_factor = WF_CHAN_FACTOR_2_4_G; + else if (freq >= 5000 && freq <= 6000) + start_factor = WF_CHAN_FACTOR_5_G; + } + + if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G) + return 14; + + base = start_factor / 2; + + + if ((freq < base) || (freq > base + 1000)) + return -1; + + offset = freq - base; + ch = offset / 5; + + + if (offset != (ch * 5)) + return -1; + + + if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13)) + return -1; + + return ch; +} + + +int +wf_channel2mhz(uint ch, uint start_factor) +{ + int freq; + + if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) || + (ch > 200)) + freq = -1; + else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14)) + freq = 2484; + else + freq = ch * 5 + start_factor / 2; + + return freq; +} diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index d9deae8..94cbe91 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 357924 2012-09-20 10:44:32Z $ + * $Id: dhd.h 356711 2012-09-13 15:58:32Z $ */ /**************** @@ -77,17 +77,20 @@ enum dhd_bus_state { DHD_BUS_DATA /* Ready for frame transfers */ }; - +enum dhd_op_flags { /* Firmware requested operation mode */ -#define STA_MASK 0x0001 -#define HOSTAPD_MASK 0x0002 -#define WFD_MASK 0x0004 -#define SOFTAP_FW_MASK 0x0008 -#define CONCURRENT_FW_MASK (STA_MASK | WFD_MASK) -#define P2P_GO_ENABLED 0x0010 -#define P2P_GC_ENABLED 0x0020 -#define CONCURENT_MASK 0x00F0 -#define CONCURRENT_MULTI_CHAN 0x0100 + DHD_FLAG_STA_MODE = BIT(0), /* STA only */ + DHD_FLAG_HOSTAP_MODE = BIT(1), /* SOFTAP only */ + DHD_FLAG_P2P_MODE = BIT(2), /* P2P Only */ + /* STA + P2P */ + DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE), + DHD_FLAG_CONCURR_MULTI_CHAN_MODE = BIT(4), /* STA + P2P */ + /* Current P2P mode for P2P connection */ + DHD_FLAG_P2P_GC_MODE = BIT(5), + DHD_FLAG_P2P_GO_MODE = BIT(6), + DHD_FLAG_MBSS_MODE = BIT(7) /* MBSS in future */ +}; + #define MANUFACTRING_FW "WLTEST" /* max sequential rxcntl timeouts to set HANG event */ @@ -95,6 +98,10 @@ enum dhd_bus_state { #define MAX_CNTL_TIMEOUT 2 #endif +#define DHD_SCAN_ASSOC_ACTIVE_TIME 40 /* ms: Embedded default Active setting from DHD */ +#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */ +#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */ + #ifndef POWERUP_MAX_RETRY #define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */ #endif @@ -278,7 +285,7 @@ typedef struct dhd_pub { #endif struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS]; #if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK) - struct wake_lock pno_wakelock; + struct wake_lock pno_wakelock; #endif } dhd_pub_t; @@ -533,7 +540,7 @@ extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); #endif /* PKT_FILTER_SUPPORT */ extern int dhd_get_dtim_skip(dhd_pub_t *dhd); -extern bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd); +extern bool dhd_support_sta_mode(dhd_pub_t *dhd); #ifdef DHD_DEBUG extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); @@ -605,7 +612,7 @@ extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); extern void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode); extern void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable); #endif /* ARP_OFFLOAD_SUPPORT */ - +extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd); typedef enum cust_gpio_modes { WLAN_RESET_ON, @@ -672,15 +679,7 @@ extern uint dhd_sdiod_drive_strength; /* Override to force tx queueing all the time */ extern uint dhd_force_tx_queueing; /* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ -#if defined(CUSTOMER_HW4) -#ifdef KEEP_ALIVE_PACKET_PERIOD_30_SEC -#define KEEP_ALIVE_PERIOD 30000 -#else /* KEEP_ALIVE_PACKET_PERIOD_30_SEC */ -#define KEEP_ALIVE_PERIOD 55000 -#endif /* KEEP_ALIVE_PACKET_PERIOD_30_SEC */ -#else -#define KEEP_ALIVE_PERIOD 55000 -#endif /* CUSTOMER_HW4 */ +#define KEEP_ALIVE_PERIOD 28000 #define NULL_PKT_STR "null_pkt" /* hooks for custom glom setting option via Makefile */ @@ -689,6 +688,21 @@ extern uint dhd_force_tx_queueing; #define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE #endif +/* hooks for custom Roaming Trigger setting via Makefile */ +#define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */ +#define DEFAULT_ROAM_TRIGGER_SETTING -1 +#ifndef CUSTOM_ROAM_TRIGGER_SETTING +#define CUSTOM_ROAM_TRIGGER_SETTING DEFAULT_ROAM_TRIGGER_VALUE +#endif + +/* hooks for custom Roaming Romaing setting via Makefile */ +#define DEFAULT_ROAM_DELTA_VALUE 10 /* dBm default roam delta all band */ +#define DEFAULT_ROAM_DELTA_SETTING -1 +#ifndef CUSTOM_ROAM_DELTA_SETTING +#define CUSTOM_ROAM_DELTA_SETTING DEFAULT_ROAM_DELTA_VALUE +#endif + + /* hooks for custom dhd_dpc_prio setting option via Makefile */ #define DEFAULT_DHP_DPC_PRIO 1 #ifndef CUSTOM_DPC_PRIO_SETTING diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index 46de6f4..cd44b92 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c 357848 2012-09-20 05:38:41Z $ + * $Id: dhd_cdc.c 355825 2012-09-10 03:22:40Z $ * * BDC is like CDC, except it includes a header for data packets to convey * packet priority over the bus, and flags (e.g. to indicate checksum status @@ -892,7 +892,7 @@ _dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf) if (PKTLEN(ctx->osh, pktbuf) < (h->dataOffset << 2)) { WLFC_DBGMESG(("%s: rx data too short (%d < %d)\n", __FUNCTION__, - PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2))); + PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2))); return BCME_ERROR; } /* pull wl-header */ @@ -958,7 +958,7 @@ _dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, else { /* remove header first */ rc = _dhd_wlfc_pullheader(ctx, p); - if (rc != BCME_OK) { + if (rc != BCME_OK) { WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); /* free the hanger slot */ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); @@ -1794,6 +1794,7 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) void* p; int fifo_id; + dhd_os_wlfc_block(dhd); if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { #ifdef PROP_TXSTATUS_DEBUG wlfc->stats.signal_only_pkts_freed++; @@ -1801,6 +1802,7 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) if (success) /* is this a signal-only packet? */ PKTFREE(wlfc->osh, txp, TRUE); + dhd_os_wlfc_unblock(dhd); return; } if (!success) { @@ -1835,6 +1837,7 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) PKTFREE(wlfc->osh, txp, TRUE); } + dhd_os_wlfc_unblock(dhd); return; } @@ -2466,6 +2469,8 @@ dhd_wlfc_cleanup(dhd_pub_t *dhd) if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; + h->items[i].pkt = NULL; + h->items[i].identifier = 0; } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { /* These are already freed from the psq */ @@ -2480,8 +2485,14 @@ dhd_wlfc_cleanup(dhd_pub_t *dhd) /* flush remained pkt in hanger queue, not in bus->txq */ for (i = 0; i < h->max_items; i++) { if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { - PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); + if (!dhd->hang_was_sent) { + PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); + } else { + printk("%s: Skip freeing skb %p\n", __func__, h->items[i].pkt); + } h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; + h->items[i].pkt = NULL; + h->items[i].identifier = 0; } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { /* These are freed from the psq so no need to free again */ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; @@ -2497,9 +2508,11 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) dhd->wlfc_state; - if (dhd->wlfc_state == NULL) + dhd_os_wlfc_block(dhd); + if (dhd->wlfc_state == NULL) { + dhd_os_wlfc_unblock(dhd); return; - + } #ifdef PROP_TXSTATUS_DEBUG { int i; @@ -2522,6 +2535,7 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) #if defined(CUSTOMER_HW4) && defined(DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS) dhdsdio_func_blocksize(dhd, 2, sd_f2_blocksize); #endif /* CUSTOMER_HW4 && DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS */ + dhd_os_wlfc_unblock(dhd); return; } #endif /* PROP_TXSTATUS */ @@ -2531,8 +2545,10 @@ dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) { bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid); #ifdef PROP_TXSTATUS + dhd_os_wlfc_block(dhdp); if (dhdp->wlfc_state) dhd_wlfc_dump(dhdp, strbuf); + dhd_os_wlfc_unblock(dhdp); #endif } diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index cc49465..e6a6837 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -80,14 +80,11 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) { dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); dhd->op_mode |= val; - WL_ERR(("Set : op_mode=%d\n", dhd->op_mode)); -#if defined(ARP_OFFLOAD_SUPPORT) - if ((dhd->op_mode & CONCURRENT_MULTI_CHAN) != - CONCURRENT_MULTI_CHAN) { - /* IF P2P is enabled, disable arpoe */ - dhd_arp_offload_set(dhd, 0); - dhd_arp_offload_enable(dhd, false); - } + WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode)); +#ifdef ARP_OFFLOAD_SUPPORT + /* IF P2P is enabled, disable arpoe */ + dhd_arp_offload_set(dhd, 0); + dhd_arp_offload_enable(dhd, false); #endif /* ARP_OFFLOAD_SUPPORT */ return 0; @@ -96,8 +93,8 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) { dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); - dhd->op_mode &= ~CONCURENT_MASK; - WL_ERR(("Clean : op_mode=%d\n", dhd->op_mode)); + dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE); + WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode)); #if defined(ARP_OFFLOAD_SUPPORT) /* IF P2P is disabled, enable arpoe back for STA mode. */ diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index b985a7c..dab9686 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 357867 2012-09-20 06:57:44Z $ + * $Id: dhd_common.c 356374 2012-09-12 10:37:44Z $ */ #include <typedefs.h> #include <osl.h> @@ -339,7 +339,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch else if (int_val & DHD_WL_VAL) wl_cfg80211_enable_trace(FALSE, WL_DBG_DBG); if (!(int_val & DHD_WL_VAL2)) -#endif +#endif /* WL_CFG80211 */ dhd_msg_level = int_val; break; case IOV_GVAL(IOV_BCMERRORSTR): @@ -1855,34 +1855,16 @@ exit: return bcn_li_dtim; } -/* Check if HostAPD or WFD mode setup */ -bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd) +/* Check if the mode supports STA MODE */ +bool dhd_support_sta_mode(dhd_pub_t *dhd) { -#if !defined(AP) && defined(WLP2P) - if ((dhd->op_mode & CONCURRENT_FW_MASK) == CONCURRENT_FW_MASK) - return FALSE; -#endif + #ifdef WL_CFG80211 -#ifndef WL_ENABLE_P2P_IF - /* To be back compatble with ICS MR1 release where p2p interface - * disable but wlan0 used for p2p - */ - if (((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) || - ((dhd->op_mode & WFD_MASK) == WFD_MASK)) { - return TRUE; - } - else -#else - /* concurent mode with p2p interface for wfd and wlan0 for sta */ - if (((dhd->op_mode & P2P_GO_ENABLED) == P2P_GO_ENABLED) || - ((dhd->op_mode & P2P_GC_ENABLED) == P2P_GC_ENABLED)) { - DHD_ERROR(("%s P2P enabled for mode=%d\n", __FUNCTION__, dhd->op_mode)); - return TRUE; - } + if (!(dhd->op_mode & DHD_FLAG_STA_MODE)) + return FALSE; else -#endif /* WL_ENABLE_P2P_IF */ #endif /* WL_CFG80211 */ - return FALSE; + return TRUE; } #if defined(PNO_SUPPORT) @@ -1927,7 +1909,8 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) return ret; } - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) +#ifndef WL_SCHED_SCAN + if (!dhd_support_sta_mode(dhd)) return (ret); memset(iovbuf, 0, sizeof(iovbuf)); @@ -1936,6 +1919,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__)); return ret; } +#endif /* !WL_SCHED_SCAN */ /* Enable/disable PNO */ if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) { @@ -1976,8 +1960,10 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, return err; } - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) - return (err); +#ifndef WL_SCHED_SCAN + if (!dhd_support_sta_mode(dhd)) + return err; +#endif /* !WL_SCHED_SCAN */ /* Check for broadcast ssid */ for (k = 0; k < nssid; k++) { @@ -2094,8 +2080,8 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) int str_len; int res = -1; - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) - return (res); + if (!dhd_support_sta_mode(dhd)) + return res; DHD_TRACE(("%s execution\n", __FUNCTION__)); diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c index 72a3a8e..1683501 100644 --- a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c @@ -97,6 +97,7 @@ const struct cntry_locales_custom translate_custom_table[] = { {"SI", "SI", 1}, {"SK", "SK", 1}, {"TR", "TR", 7}, + {"UA", "UA", 2}, {"TW", "TW", 2}, {"IR", "XZ", 11}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */ {"SD", "XZ", 11}, /* Universal if Country code is SUDAN */ @@ -107,23 +108,14 @@ const struct cntry_locales_custom translate_custom_table[] = { {"MH", "XZ", 11}, /* Universal if Country code is MARSHALL ISLANDS */ {"PK", "XZ", 11}, /* Universal if Country code is PAKISTAN */ #ifdef BCM4334_CHIP - {"RU", "RU", 13}, - {"SG", "SG", 4}, - {"US", "US", 46}, - {"UA", "UA", 8}, - {"CO", "CO", 4}, - {"ID", "ID", 1}, - {"LA", "LA", 1}, - {"LB", "LB", 2}, - {"VN", "VN", 4}, + {"RU", "RU", 5}, + {"SG", "SG", 4}, + {"US", "US", 46} #endif #ifdef BCM4330_CHIP - {"RU", "RU", 13}, - {"US", "US", 5}, - {"UA", "UY", 0}, - {"AD", "AL", 0}, + {"RU", "RU", 1}, + {"US", "US", 5} #endif - {"UA", "UA", 2} }; /* Customized Locale convertor diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index ea31b93..8702a44 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 358099 2012-09-21 04:38:52Z $ + * $Id: dhd_linux.c 358016 2012-09-20 22:36:51Z $ */ #include <typedefs.h> @@ -602,8 +602,8 @@ extern int register_pm_notifier(struct notifier_block *nb); extern int unregister_pm_notifier(struct notifier_block *nb); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ -#ifdef PKT_FILTER_SUPPORT void dhd_set_packet_filter(dhd_pub_t *dhd) +#ifdef PKT_FILTER_SUPPORT { int i; @@ -613,20 +613,23 @@ void dhd_set_packet_filter(dhd_pub_t *dhd) dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); } } +#endif } void dhd_enable_packet_filter(int value, dhd_pub_t *dhd) { +#ifdef PKT_FILTER_SUPPORT int i; DHD_TRACE(("%s: enter, value = %d\n", __FUNCTION__, value)); /* 1 - Enable packet filter, only allow unicast packet to send up */ /* 0 - Disable packet filter */ - if (dhd_pkt_filter_enable) { + if (dhd_pkt_filter_enable && (!value || + (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) { for (i = 0; i < dhd->pktfilter_count; i++) { #ifdef PASS_ARP_PACKET if (value && (i == dhd->pktfilter_count -1) && - !(dhd->op_mode & (P2P_GC_ENABLED | P2P_GO_ENABLED))) { + !(dhd->op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))) { DHD_TRACE_HW4(("Do not turn on ARP white list pkt filter:" "val %d, cnt %d, op_mode 0x%x\n", value, i, dhd->op_mode)); @@ -637,8 +640,8 @@ void dhd_enable_packet_filter(int value, dhd_pub_t *dhd) value, dhd_master_mode); } } -} #endif /* PKT_FILTER_SUPPORT */ +} static int dhd_set_suspend(int value, dhd_pub_t *dhd) { @@ -670,7 +673,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) dhd->early_suspended = 1; #endif /* Kernel suspended */ - DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__)); + DHD_ERROR(("%s: force extra Suspend setting\n", __FUNCTION__)); #ifndef SUPPORT_PM2_ONLY dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, @@ -716,7 +719,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) dhd->early_suspended = 0; #endif /* Kernel resumed */ - DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__)); + DHD_ERROR(("%s: Remove extra suspend setting\n", __FUNCTION__)); #ifndef SUPPORT_PM2_ONLY power_mode = PM_FAST; @@ -770,7 +773,7 @@ static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force) /* Set flag when early suspend was called */ dhdp->in_suspend = val; if ((force || !dhdp->suspend_disable_flag) && - (dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) + dhd_support_sta_mode(dhdp)) { ret = dhd_set_suspend(val, dhdp); } @@ -1047,7 +1050,7 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) #ifdef MCAST_LIST_ACCUMULATION DHD_TRACE(("_dhd_set_multicast_list: cnt " "%d " MACDBG "\n", - cnt_iface[i], STR_TO_MACD(ha->addr))); + cnt_iface[i], MAC2STRDBG(ha->addr))); cnt_iface[i]--; #else cnt--; @@ -1534,7 +1537,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) } else /* non-proptxstatus way */ - ret = dhd_bus_txdata(dhdp->bus, pktbuf); + ret = dhd_bus_txdata(dhdp->bus, pktbuf); #else ret = dhd_bus_txdata(dhdp->bus, pktbuf); #endif /* PROP_TXSTATUS */ @@ -1757,11 +1760,11 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) /* Dropping packets before registering net device to avoid kernel panic */ -#ifdef BCMDHDUSB +#ifndef PROP_TXSTATUS_VSDB if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) { #else if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || !dhd->pub.up) { -#endif /* BCMDHDUSB */ +#endif /* PROP_TXSTATUS_VSDB */ DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n", __FUNCTION__)); PKTFREE(dhdp->osh, pktbuf, TRUE); @@ -1794,10 +1797,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) */ ((athost_wl_status_info_t*)dhdp->wlfc_state)->stats.wlfc_header_only_pkt++; #ifdef CUSTOMER_HW4 - if (numpkt == 1 && pkt_free && (free_ptr == pktbuf)) { -/* DHD_ERROR(("DHD TRACE2(FREE):%d %d %p\n", - pkt_free, caller, free_ptr)); */ - } + /*if (numpkt == 1 && pkt_free && (free_ptr == pktbuf)) { + DHD_ERROR(("DHD TRACE2(FREE):%d %d %p\n", + pkt_free, caller, free_ptr)); + }*/ #endif PKTFREE(dhdp->osh, pktbuf, TRUE); continue; @@ -1845,7 +1848,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) } } else if (dump_data[0] & 1) { DHD_ERROR(("%s: MULTICAST: " MACDBG "\n", - __FUNCTION__, STR_TO_MACD(dump_data))); + __FUNCTION__, MAC2STRDBG(dump_data))); } if (protocol == ETHER_TYPE_802_1X) { @@ -2741,7 +2744,9 @@ dhd_stop(struct net_device *net) #endif #ifdef PROP_TXSTATUS + dhd_os_wlfc_block(&dhd->pub); dhd_wlfc_cleanup(&dhd->pub); + dhd_os_wlfc_unblock(&dhd->pub); #endif /* Stop the protocol module */ @@ -2810,7 +2815,6 @@ dhd_open(struct net_device *net) nvram_path[0] = '\0'; } - dhd->pub.dongle_trap_occured = 0; dhd->pub.hang_was_sent = 0; #if !defined(WL_CFG80211) @@ -3166,6 +3170,11 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #ifdef PROP_TXSTATUS spin_lock_init(&dhd->wlfc_spinlock); +#ifdef PROP_TXSTATUS_VSDB + dhd->pub.wlfc_enabled = FALSE; +#else + dhd->pub.wlfc_enabled = TRUE; +#endif /* PROP_TXSTATUS_VSDB */ #endif /* PROP_TXSTATUS */ /* Initialize other structure content */ @@ -3478,18 +3487,37 @@ dhd_bus_start(dhd_pub_t *dhdp) return 0; } +bool dhd_is_concurrent_mode(dhd_pub_t *dhd) +{ + if (!dhd) + return FALSE; + + if (dhd->op_mode & DHD_FLAG_CONCURR_MULTI_CHAN_MODE) + return TRUE; + else if ((dhd->op_mode & DHD_FLAG_CONCURR_SINGLE_CHAN_MODE) == + DHD_FLAG_CONCURR_SINGLE_CHAN_MODE) + return TRUE; + else + return FALSE; +} + #if !defined(AP) && defined(WLP2P) -/* For Android ICS MR2 release, the concurrent mode is enabled by default and the firmware +/* From Android JerryBean release, the concurrent mode is enabled by default and the firmware * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware * would still be named as fw_bcmdhd_apsta. */ -int +uint32 dhd_get_concurrent_capabilites(dhd_pub_t *dhd) { - int ret = 0; + int32 ret = 0; char buf[WLC_IOCTL_SMLEN]; - bool vsdb_supported = false; + bool mchan_supported = FALSE; + /* if dhd->op_mode is already set for HOSTAP, + * that means we only will use the mode as it is + */ + if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) + return 0; memset(buf, 0, sizeof(buf)); bcm_mkiovar("cap", 0, 0, buf, sizeof(buf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), @@ -3499,7 +3527,7 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd) return 0; } if (strstr(buf, "vsdb")) { - vsdb_supported = true; + mchan_supported = TRUE; } if (strstr(buf, "p2p") == NULL) { DHD_TRACE(("Chip does not support p2p\n")); @@ -3516,14 +3544,19 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd) } else { if (buf[0] == 1) { - /* Chip supports p2p, now lets check for vsdb */ - if (vsdb_supported) - return 2; - else -#ifdef WL_ENABLE_P2P_IF - return 1; + /* By default, chip supports single chan concurrency, + * now lets check for mchan + */ + ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE; + if (mchan_supported) + ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE; +#if defined(WL_ENABLE_P2P_IF) + /* For customer_hw4, although ICS, + * we still support concurrent mode + */ + return ret; #else - return 0; + return 0; #endif } } @@ -3556,7 +3589,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; #endif - int scan_assoc_time = DHD_SCAN_ACTIVE_TIME; + int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME; int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME; int scan_passive_time = DHD_SCAN_PASSIVE_TIME; char buf[WLC_IOCTL_SMLEN]; @@ -3564,12 +3597,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ #ifdef ROAM_ENABLE uint roamvar = 0; - int roam_trigger[2] = {-75, WLC_BAND_ALL}; + int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL}; int roam_scan_period[2] = {10, WLC_BAND_ALL}; - int roam_delta[2] = {10, WLC_BAND_ALL}; #ifdef ROAM_AP_ENV_DETECTION int roam_env_mode = AP_ENV_INDETERMINATE; #endif /* ROAM_AP_ENV_DETECTION */ + int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL}; #ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC int roam_fullscan_period = 60; #else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ @@ -3609,8 +3642,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) int interference_mode = 3; #endif #ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB dhd->wlfc_enabled = FALSE; /* enable WLFC only if the firmware is VSDB */ +#else + dhd->wlfc_enabled = TRUE; +#endif /* PROP_TXSTATUS_VSDB */ #endif /* PROP_TXSTATUS */ DHD_TRACE(("Enter %s\n", __FUNCTION__)); dhd->op_mode = 0; @@ -3643,11 +3680,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* GET_CUSTOM_MAC_ENABLE */ - if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == HOSTAPD_MASK)) { + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || + (op_mode == DHD_FLAG_HOSTAP_MODE)) { #ifdef SET_RANDOM_MAC_SOFTAP uint rand_mac; #endif - op_mode = HOSTAPD_MASK; + dhd->op_mode = DHD_FLAG_HOSTAP_MODE; #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; #endif @@ -3682,31 +3720,33 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } else { - int concurrent_capab = 0; - if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || (op_mode == WFD_MASK)) { + uint32 concurrent_mode = 0; + if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || + (op_mode == DHD_FLAG_P2P_MODE)) { #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; #endif #ifdef PKT_FILTER_SUPPORT dhd_pkt_filter_enable = FALSE; #endif - op_mode = WFD_MASK; + dhd->op_mode = DHD_FLAG_P2P_MODE; } else - op_mode = STA_MASK; + dhd->op_mode = DHD_FLAG_STA_MODE; #if !defined(AP) && defined(WLP2P) - if ((concurrent_capab = dhd_get_concurrent_capabilites(dhd)) > 0) { - op_mode = STA_MASK | WFD_MASK; - if (concurrent_capab == 2) - op_mode = STA_MASK | WFD_MASK | CONCURRENT_MULTI_CHAN; + if ((concurrent_mode = dhd_get_concurrent_capabilites(dhd))) { +#if defined(ARP_OFFLOAD_SUPPORT) + arpoe = 1; +#endif + dhd->op_mode |= concurrent_mode; } /* Check if we are enabling p2p */ - if (op_mode & WFD_MASK) { + if (dhd->op_mode & DHD_FLAG_P2P_MODE) { bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { - DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret)); + DHD_ERROR(("%s APSTA for P2P failed ret= %d\n", __FUNCTION__, ret)); } memcpy(&p2p_ea, &dhd->mac, ETHER_ADDR_LEN); @@ -3721,15 +3761,14 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } } #else - (void)concurrent_capab; -#endif + (void)concurrent_mode; +#endif } - dhd->op_mode = op_mode; - DHD_ERROR(("Firmware up: op_mode=%d, " + DHD_ERROR(("Firmware up: op_mode=0x%04x, " "Broadcom Dongle Host Driver mac="MACDBG"\n", dhd->op_mode, - STR_TO_MACD(dhd->mac.octet))); + MAC2STRDBG(dhd->mac.octet))); /* Set Country code */ if (dhd->dhd_cspec.ccode[0] != 0) { bcm_mkiovar("country", (char *)&dhd->dhd_cspec, @@ -3749,12 +3788,18 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); #endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */ #ifdef ROAM_ENABLE - dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), TRUE, 0); - dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, roam_scan_period, - sizeof(roam_scan_period), TRUE, 0); - dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta, sizeof(roam_delta), TRUE, 0); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, + sizeof(roam_trigger), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam trigger set failed %d\n", __FUNCTION__, ret)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, roam_scan_period, + sizeof(roam_scan_period), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam scan period set failed %d\n", __FUNCTION__, ret)); + if ((dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta, + sizeof(roam_delta), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam delta set failed %d\n", __FUNCTION__, ret)); bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam fullscan period set failed %d\n", __FUNCTION__, ret)); #ifdef ROAM_AP_ENV_DETECTION if (roam_trigger[0] == WL_AUTO_ROAM_TRIGGER) { bcm_mkiovar("roam_env_detection", (char *)&roam_env_mode, @@ -3783,9 +3828,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - DHD_INFO(("%s set glom=0x%X\n", __FUNCTION__, glom)); - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + if (glom != DEFAULT_GLOM_VALUE) { + DHD_INFO(("%s set glom=0x%X\n", __FUNCTION__, glom)); + bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + } /* Setup timeout if Beacons are lost and roam is off to report link down */ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); @@ -3819,7 +3866,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(SOFTAP) if (ap_fw_loaded == FALSE) #endif - if ((dhd->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) { + if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) { if ((res = dhd_keep_alive_onoff(dhd)) < 0) DHD_ERROR(("%s set keeplive failed %d\n", __FUNCTION__, res)); @@ -3874,7 +3921,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* BCMCCX */ #ifdef WL_CFG80211 setbit(eventmask, WLC_E_ESCAN_RESULT); - if ((dhd->op_mode & WFD_MASK) == WFD_MASK) { + if (dhd->op_mode & DHD_FLAG_P2P_MODE) { setbit(eventmask, WLC_E_ACTION_FRAME_RX); setbit(eventmask, WLC_E_ACTION_FRAME_COMPLETE); setbit(eventmask, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE); @@ -4158,7 +4205,7 @@ static int dhd_device_event(struct notifier_block *this, } #ifdef AOE_IP_ALIAS_SUPPORT - if ((dhd_pub->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) { + if (!(dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE)) { if (ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a) { /* 0x3a = ':' */ DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n", @@ -4176,20 +4223,21 @@ static int dhd_device_event(struct notifier_block *this, __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); dhd->pend_ipaddr = 0; #ifdef AOE_IP_ALIAS_SUPPORT - if ((dhd_pub->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) { - if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) { - /* 0x3a = ':' */ - DHD_ARPOE(("%s: primary interface is down, AOE clr all\n", - __FUNCTION__)); - dhd_aoe_hostip_clr(&dhd->pub); - dhd_aoe_arp_clr(&dhd->pub); - } else - aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE); - } + if (!(dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE)) { + if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) { + /* 0x3a = ':' */ + DHD_ARPOE(("%s: primary interface is down," + " AOE clr all\n", __FUNCTION__)); + dhd_aoe_hostip_clr(&dhd->pub); + dhd_aoe_arp_clr(&dhd->pub); + } else + aoe_update_host_ipv4_table(dhd_pub, + ifa->ifa_address, FALSE); + } #else dhd_aoe_hostip_clr(&dhd->pub); dhd_aoe_arp_clr(&dhd->pub); -#endif +#endif /* AOE_IP_ALIAS_SUPPORT */ break; default: @@ -4287,9 +4335,9 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) " MAC: "MACDBG"\n", net->name, #if defined(CUSTOMER_HW4) - STR_TO_MACD(dhd->pub.mac.octet)); + MAC2STRDBG(dhd->pub.mac.octet)); #else - STR_TO_MACD(net->dev_addr)); + MAC2STRDBG(net->dev_addr)); #endif /* CUSTOMER_HW4 */ #if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211) @@ -5149,6 +5197,9 @@ int net_os_set_suspend(struct net_device *dev, int val, int force) #else ret = dhd_suspend_resume_helper(dhd, val, force); #endif +#ifdef WL_CFG80211 + wl_cfg80211_update_power_mode(dev); +#endif } return ret; } @@ -5813,23 +5864,34 @@ extern int dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits); int dhd_wlfc_interface_event(struct dhd_info *dhd, ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) { - if (dhd->pub.wlfc_state == NULL) - return BCME_OK; + int ret = BCME_OK; - return dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); + dhd_os_wlfc_block(&dhd->pub); + if (dhd->pub.wlfc_state != NULL) + ret = dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); + dhd_os_wlfc_unblock(&dhd->pub); + return ret; } int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data) { - if (dhd->pub.wlfc_state == NULL) - return BCME_OK; + int ret = BCME_OK; - return dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); + dhd_os_wlfc_block(&dhd->pub); + if (dhd->pub.wlfc_state != NULL) + ret = dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); + dhd_os_wlfc_unblock(&dhd->pub); + return ret; } int dhd_wlfc_event(struct dhd_info *dhd) { - return dhd_wlfc_enable(&dhd->pub); + int ret; + + dhd_os_wlfc_block(&dhd->pub); + ret = dhd_wlfc_enable(&dhd->pub); + dhd_os_wlfc_unblock(&dhd->pub); + return ret; } #endif /* PROP_TXSTATUS */ diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 0617e16..422ad03 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 357912 2012-09-20 09:42:47Z $ + * $Id: dhd_sdio.c 357859 2012-09-20 06:34:26Z $ */ #include <typedefs.h> @@ -399,14 +399,13 @@ static bool sd1idle; static bool retrydata; #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) -#ifdef BCMSPI -/* At a watermark around 8 the spid hits underflow error. */ -static const uint watermark = 32; -static const uint mesbusyctrl = 0; +#if defined(SDIO_CRC_ERROR_FIX) +static uint watermark = 48; +static uint mesbusyctrl = 80; #else static const uint watermark = 8; static const uint mesbusyctrl = 0; -#endif /* BCMSPI */ +#endif static const uint firstread = DHD_FIRSTREAD; #define HDATLEN (firstread - (SDPCM_HDRLEN)) @@ -417,7 +416,6 @@ static const uint retry_limit = 2; /* Force even SD lengths (some host controllers mess up on odd bytes) */ static bool forcealign; - #define ALIGNMENT 4 #if defined(OOB_INTR_ONLY) && defined(HW_OOB) @@ -1111,11 +1109,12 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); } - else { - if (ht_avail_error == HT_AVAIL_ERROR_MAX) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + else if (ht_avail_error == HT_AVAIL_ERROR_MAX) { dhd_os_send_hang_message(bus->dhd); - } -return BCME_ERROR; + } +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */ + return BCME_ERROR; } else { ht_avail_error = 0; } @@ -2411,6 +2410,10 @@ enum { IOV_SDALIGN, IOV_DEVRESET, IOV_CPU, +#if defined(SDIO_CRC_ERROR_FIX) + IOV_WATERMARK, + IOV_MESBUSYCTRL, +#endif /* SDIO_CRC_ERROR_FIX */ #ifdef SDTEST IOV_PKTGEN, IOV_EXTLOOP, @@ -2471,6 +2474,10 @@ const bcm_iovar_t dhdsdio_iovars[] = { {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 }, {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) }, #endif /* SDTEST */ +#if defined(SDIO_CRC_ERROR_FIX) + {"watermark", IOV_WATERMARK, 0, IOVT_UINT32, 0 }, + {"mesbusyctrl", IOV_MESBUSYCTRL, 0, IOVT_UINT32, 0 }, +#endif /* SDIO_CRC_ERROR_FIX */ {"devcap", IOV_DEVCAP, 0, IOVT_UINT32, 0 }, {"dngl_isolation", IOV_DONGLEISOLATION, 0, IOVT_UINT32, 0 }, {"kso", IOV_KSO, 0, IOVT_UINT32, 0 }, @@ -3105,7 +3112,8 @@ dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror) if (bus->sih->chip == BCM4330_CHIP_ID) { uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB; } - else if (bus->sih->chip == BCM4334_CHIP_ID) { + else if (bus->sih->chip == BCM4334_CHIP_ID || + bus->sih->chip == BCM43341_CHIP_ID) { if (enable) { /* Moved to PMU chipcontrol 1 from 4330 */ int_val &= ~gpio_sel; @@ -3575,6 +3583,33 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch break; #endif /* SDTEST */ +#if defined(SDIO_CRC_ERROR_FIX) + case IOV_GVAL(IOV_WATERMARK): + int_val = (int32)watermark; + bcopy(&int_val, arg, val_size); + break; + + case IOV_SVAL(IOV_WATERMARK): + watermark = (uint)int_val; + watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark; + DHD_ERROR(("Setting watermark as 0x%x.\n", watermark)); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL); + break; + + case IOV_GVAL(IOV_MESBUSYCTRL): + int_val = (int32)mesbusyctrl; + bcopy(&int_val, arg, val_size); + break; + + case IOV_SVAL(IOV_MESBUSYCTRL): + mesbusyctrl = (uint)int_val; + mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK) + ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl; + DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl)); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, + ((uint8)mesbusyctrl | 0x80), NULL); + break; +#endif /* SDIO_CRC_ERROR_FIX */ case IOV_GVAL(IOV_DONGLEISOLATION): int_val = bus->dhd->dongle_isolation; @@ -4078,51 +4113,57 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) if (enforce_mutex) dhd_os_sdlock(bus->dhd); - BUS_WAKE(bus); + if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) { + bus->dhd->busstate = DHD_BUS_DOWN; + bus->hostintmask = 0; + bcmsdh_intr_disable(bus->sdh); + } else { + BUS_WAKE(bus); - if (KSO_ENAB(bus)) { - /* Mask the interrupt */ - dat = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL); - dat &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, dat, NULL); - } + if (KSO_ENAB(bus)) { + /* Mask the interrupt */ + dat = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL); + dat &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, dat, NULL); + } - /* Change our idea of bus state */ - bus->dhd->busstate = DHD_BUS_DOWN; + /* Change our idea of bus state */ + bus->dhd->busstate = DHD_BUS_DOWN; - if (KSO_ENAB(bus)) { + if (KSO_ENAB(bus)) { - /* Enable clock for device interrupts */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + /* Enable clock for device interrupts */ + dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - /* Disable and clear interrupts at the chip level also */ - W_SDREG(0, &bus->regs->hostintmask, retries); - local_hostintmask = bus->hostintmask; - bus->hostintmask = 0; + /* Disable and clear interrupts at the chip level also */ + W_SDREG(0, &bus->regs->hostintmask, retries); + local_hostintmask = bus->hostintmask; + bus->hostintmask = 0; - /* Force clocks on backplane to be sure F2 interrupt propagates */ - saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); - if (!err) { - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - (saveclk | SBSDIO_FORCE_HT), &err); - } - if (err) { - DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); - } + /* Force clocks on backplane to be sure F2 interrupt propagates */ + saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); + if (!err) { + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, + (saveclk | SBSDIO_FORCE_HT), &err); + } + if (err) { + DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); + } - /* Turn off the bus (F2), free any pending packets */ - DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); - bcmsdh_intr_disable(bus->sdh); + /* Turn off the bus (F2), free any pending packets */ + DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); + bcmsdh_intr_disable(bus->sdh); #ifndef BCMSPI - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); -#endif /* !BCMSPI */ + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); +#endif - /* Clear any pending interrupts now that F2 is disabled */ - W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); - } + /* Clear any pending interrupts now that F2 is disabled */ + W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); + } - /* Turn off the backplane clock (only) */ - dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); + /* Turn off the backplane clock (only) */ + dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); + } /* Clear the data packet queues */ pktq_flush(osh, &bus->txq, TRUE, NULL, 0); @@ -4281,8 +4322,19 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) } #endif /* BCMSPI */ W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); +#ifdef SDIO_CRC_ERROR_FIX + if (bus->blocksize < 512) { + mesbusyctrl = watermark = bus->blocksize / 4; + } +#endif /* SDIO_CRC_ERROR_FIX */ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err); +#ifdef SDIO_CRC_ERROR_FIX + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, + (uint8)mesbusyctrl|0x80, &err); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, + SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK, NULL); +#endif /* SDIO_CRC_ERROR_FIX */ /* Set bus state according to enable result */ dhdp->busstate = DHD_BUS_DATA; @@ -4843,18 +4895,12 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) free_ptr = pfirst; #endif PKTFREE(bus->dhd->osh, pfirst, FALSE); - if (plast) { - PKTSETNEXT(osh, plast, pnext); - } continue; } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf, &reorder_info_len) != 0) { DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__)); bus->dhd->rx_errors++; PKTFREE(osh, pfirst, FALSE); - if (plast) { - PKTSETNEXT(osh, plast, pnext); - } continue; } if (reorder_info_len) { @@ -4867,9 +4913,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) reorder_info_len, &ppfirst, &free_buf_count); if (free_buf_count == 0) { - if (plast) { - PKTSETNEXT(osh, plast, pnext); - } continue; } else { @@ -4889,14 +4932,12 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) PKTSETNEXT(osh, list_tail[ifidx], ppfirst); list_tail[ifidx] = pfirst; } - plast = pfirst; } num += (uint8)free_buf_count; } else { /* this packet will go up, link back into chain and count it */ - plast = pfirst; if (list_tail[ifidx] == NULL) { list_head[ifidx] = list_tail[ifidx] = pfirst; @@ -5764,6 +5805,7 @@ dhdsdio_hostmail(dhd_bus_t *bus) if (hmb_data & HMB_DATA_FWHALT) { DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED\n")); dhdsdio_checkdied(bus, NULL, 0); + bus->dhd->busstate = DHD_BUS_DOWN; } #endif /* DHD_DEBUG */ @@ -6041,7 +6083,7 @@ clkwait: /* Resched the DPC if ctrl cmd is pending on bus credit */ if (bus->ctrl_frame_stat) { DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n", - __FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate)); + __FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate)); resched = TRUE; } @@ -6668,6 +6710,8 @@ dhdsdio_chipmatch(uint16 chipid) return TRUE; if (chipid == BCM4334_CHIP_ID) return TRUE; + if (chipid == BCM43341_CHIP_ID) + return TRUE; if (chipid == BCM43239_CHIP_ID) return TRUE; if (chipid == BCM4324_CHIP_ID) diff --git a/drivers/net/wireless/bcmdhd/dhd_sec_feature.h b/drivers/net/wireless/bcmdhd/dhd_sec_feature.h index fdad958..fdad958 100644..100755 --- a/drivers/net/wireless/bcmdhd/dhd_sec_feature.h +++ b/drivers/net/wireless/bcmdhd/dhd_sec_feature.h diff --git a/drivers/net/wireless/bcmdhd/include/Makefile b/drivers/net/wireless/bcmdhd/include/Makefile index eca939f..eca939f 100644..100755 --- a/drivers/net/wireless/bcmdhd/include/Makefile +++ b/drivers/net/wireless/bcmdhd/include/Makefile diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h index 99b412a..25cd55b 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.h 313732 2012-02-08 19:49:00Z $ + * $Id: bcmsdh_sdmmc.h 355594 2012-09-07 10:22:02Z $ */ #ifndef __BCMSDH_SDMMC_H__ @@ -34,6 +34,8 @@ #define sd_data(x) #define sd_ctrl(x) +#define sd_trace_hw4 sd_trace + #define sd_sync_dma(sd, read, nbytes) #define sd_init_dma(sd) #define sd_ack_intr(sd) diff --git a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h index 13d6557..d94e9e4 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h +++ b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h @@ -1,168 +1,168 @@ -/* - * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer - * - * Copyright (C) 1999-2012, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmspibrcm.h 354197 2012-08-30 09:05:59Z $ - */ -#ifndef _BCM_SPI_BRCM_H -#define _BCM_SPI_BRCM_H - -#ifndef SPI_MAX_IOFUNCS -/* Maximum number of I/O funcs */ -#define SPI_MAX_IOFUNCS 4 -#endif -/* global msglevel for debug messages - bitvals come from sdiovar.h */ - -#if defined(DHD_DEBUG) -#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0) -#define sd_trace(x) do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0) -#define sd_info(x) do { if (sd_msglevel & SDH_INFO_VAL) printf x; } while (0) -#define sd_debug(x) do { if (sd_msglevel & SDH_DEBUG_VAL) printf x; } while (0) -#define sd_data(x) do { if (sd_msglevel & SDH_DATA_VAL) printf x; } while (0) -#define sd_ctrl(x) do { if (sd_msglevel & SDH_CTRL_VAL) printf x; } while (0) -#else -#define sd_err(x) -#define sd_trace(x) -#define sd_info(x) -#define sd_debug(x) -#define sd_data(x) -#define sd_ctrl(x) -#endif - -#define sd_log(x) - -#define SDIOH_ASSERT(exp) \ - do { if (!(exp)) \ - printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ - } while (0) - -#define BLOCK_SIZE_F1 64 -#define BLOCK_SIZE_F2 2048 -#define BLOCK_SIZE_F3 2048 - -/* internal return code */ -#define SUCCESS 0 -#undef ERROR -#define ERROR 1 -#define ERROR_UF 2 -#define ERROR_OF 3 - -/* private bus modes */ -#define SDIOH_MODE_SPI 0 - -#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ -#define USE_MULTIBLOCK 0x4 - -struct sdioh_info { - uint cfg_bar; /* pci cfg address for bar */ - uint32 caps; /* cached value of capabilities reg */ -#ifndef BCMSPI_ANDROID - void *bar0; /* BAR0 for PCI Device */ -#endif /* !BCMSPI_ANDROID */ - osl_t *osh; /* osh handler */ - void *controller; /* Pointer to SPI Controller's private data struct */ -#ifndef BCMSPI_ANDROID - uint lockcount; /* nest count of spi_lock() calls */ - bool client_intr_enabled; /* interrupt connnected flag */ - bool intr_handler_valid; /* client driver interrupt handler valid */ - sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ - void *intr_handler_arg; /* argument to call interrupt handler */ -#endif /* !BCMSPI_ANDROID */ - bool initialized; /* card initialized */ - uint32 target_dev; /* Target device ID */ - uint32 intmask; /* Current active interrupts */ -#ifndef BCMSPI_ANDROID - void *sdos_info; /* Pointer to per-OS private data */ -#endif /* !BCMSPI_ANDROID */ - uint32 controller_type; /* Host controller type */ - uint8 version; /* Host Controller Spec Compliance Version */ - uint irq; /* Client irq */ - uint32 intrcount; /* Client interrupts */ - uint32 local_intrcount; /* Controller interrupts */ - bool host_init_done; /* Controller initted */ - bool card_init_done; /* Client SDIO interface initted */ - bool polled_mode; /* polling for command completion */ - - bool sd_use_dma; /* DMA on CMD53 */ - bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ - /* Must be on for sd_multiblock to be effective */ - bool use_client_ints; /* If this is false, make sure to restore */ - /* polling hack in wl_linux.c:wl_timer() */ - int adapter_slot; /* Maybe dealing with multiple slots/controllers */ - int sd_mode; /* SD1/SD4/SPI */ - int client_block_size[SPI_MAX_IOFUNCS]; /* Blocksize */ - uint32 data_xfer_count; /* Current transfer */ - uint16 card_rca; /* Current Address */ - uint8 num_funcs; /* Supported funcs on client */ - uint32 card_dstatus; /* 32bit device status */ - uint32 com_cis_ptr; - uint32 func_cis_ptr[SPI_MAX_IOFUNCS]; - void *dma_buf; - ulong dma_phys; - int r_cnt; /* rx count */ - int t_cnt; /* tx_count */ - uint32 wordlen; /* host processor 16/32bits */ - uint32 prev_fun; - uint32 chip; - uint32 chiprev; - bool resp_delay_all; - bool dwordmode; - bool resp_delay_new; - - struct spierrstats_t spierrstats; -}; - -/************************************************************ - * Internal interfaces: per-port references into bcmspibrcm.c - */ - -/* Global message bits */ -extern uint sd_msglevel; - -/************************************************************** - * Internal interfaces: bcmspibrcm.c references to per-port code - */ - -/* Interrupt (de)registration routines */ -extern int spi_register_irq(sdioh_info_t *sd, uint irq); -extern void spi_free_irq(uint irq, sdioh_info_t *sd); - -/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ -extern void spi_lock(sdioh_info_t *sd); -extern void spi_unlock(sdioh_info_t *sd); - -/* Allocate/init/free per-OS private data */ -extern int spi_osinit(sdioh_info_t *sd); -extern void spi_osfree(sdioh_info_t *sd); - -#define SPI_RW_FLAG_M BITFIELD_MASK(1) /* Bit [31] - R/W Command Bit */ -#define SPI_RW_FLAG_S 31 -#define SPI_ACCESS_M BITFIELD_MASK(1) /* Bit [30] - Fixed/Incr Access */ -#define SPI_ACCESS_S 30 -#define SPI_FUNCTION_M BITFIELD_MASK(2) /* Bit [29:28] - Function Number */ -#define SPI_FUNCTION_S 28 -#define SPI_REG_ADDR_M BITFIELD_MASK(17) /* Bit [27:11] - Address */ -#define SPI_REG_ADDR_S 11 -#define SPI_LEN_M BITFIELD_MASK(11) /* Bit [10:0] - Packet length */ -#define SPI_LEN_S 0 - -#endif /* _BCM_SPI_BRCM_H */ +/*
+ * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer
+ *
+ * Copyright (C) 1999-2012, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmspibrcm.h 354176 2012-08-30 07:34:33Z $
+ */
+#ifndef _BCM_SPI_BRCM_H
+#define _BCM_SPI_BRCM_H
+
+#ifndef SPI_MAX_IOFUNCS
+/* Maximum number of I/O funcs */
+#define SPI_MAX_IOFUNCS 4
+#endif
+/* global msglevel for debug messages - bitvals come from sdiovar.h */
+
+#if defined(DHD_DEBUG)
+#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
+#define sd_trace(x) do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0)
+#define sd_info(x) do { if (sd_msglevel & SDH_INFO_VAL) printf x; } while (0)
+#define sd_debug(x) do { if (sd_msglevel & SDH_DEBUG_VAL) printf x; } while (0)
+#define sd_data(x) do { if (sd_msglevel & SDH_DATA_VAL) printf x; } while (0)
+#define sd_ctrl(x) do { if (sd_msglevel & SDH_CTRL_VAL) printf x; } while (0)
+#else
+#define sd_err(x)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+#endif
+
+#define sd_log(x)
+
+#define SDIOH_ASSERT(exp) \
+ do { if (!(exp)) \
+ printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
+ } while (0)
+
+#define BLOCK_SIZE_F1 64
+#define BLOCK_SIZE_F2 2048
+#define BLOCK_SIZE_F3 2048
+
+/* internal return code */
+#define SUCCESS 0
+#undef ERROR
+#define ERROR 1
+#define ERROR_UF 2
+#define ERROR_OF 3
+
+/* private bus modes */
+#define SDIOH_MODE_SPI 0
+
+#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */
+#define USE_MULTIBLOCK 0x4
+
+struct sdioh_info {
+ uint cfg_bar; /* pci cfg address for bar */
+ uint32 caps; /* cached value of capabilities reg */
+#ifndef BCMSPI_ANDROID
+ void *bar0; /* BAR0 for PCI Device */
+#endif /* !BCMSPI_ANDROID */
+ osl_t *osh; /* osh handler */
+ void *controller; /* Pointer to SPI Controller's private data struct */
+#ifndef BCMSPI_ANDROID
+ uint lockcount; /* nest count of spi_lock() calls */
+ bool client_intr_enabled; /* interrupt connnected flag */
+ bool intr_handler_valid; /* client driver interrupt handler valid */
+ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
+ void *intr_handler_arg; /* argument to call interrupt handler */
+#endif /* !BCMSPI_ANDROID */
+ bool initialized; /* card initialized */
+ uint32 target_dev; /* Target device ID */
+ uint32 intmask; /* Current active interrupts */
+#ifndef BCMSPI_ANDROID
+ void *sdos_info; /* Pointer to per-OS private data */
+#endif /* !BCMSPI_ANDROID */
+ uint32 controller_type; /* Host controller type */
+ uint8 version; /* Host Controller Spec Compliance Version */
+ uint irq; /* Client irq */
+ uint32 intrcount; /* Client interrupts */
+ uint32 local_intrcount; /* Controller interrupts */
+ bool host_init_done; /* Controller initted */
+ bool card_init_done; /* Client SDIO interface initted */
+ bool polled_mode; /* polling for command completion */
+
+ bool sd_use_dma; /* DMA on CMD53 */
+ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
+ /* Must be on for sd_multiblock to be effective */
+ bool use_client_ints; /* If this is false, make sure to restore */
+ /* polling hack in wl_linux.c:wl_timer() */
+ int adapter_slot; /* Maybe dealing with multiple slots/controllers */
+ int sd_mode; /* SD1/SD4/SPI */
+ int client_block_size[SPI_MAX_IOFUNCS]; /* Blocksize */
+ uint32 data_xfer_count; /* Current transfer */
+ uint16 card_rca; /* Current Address */
+ uint8 num_funcs; /* Supported funcs on client */
+ uint32 card_dstatus; /* 32bit device status */
+ uint32 com_cis_ptr;
+ uint32 func_cis_ptr[SPI_MAX_IOFUNCS];
+ void *dma_buf;
+ ulong dma_phys;
+ int r_cnt; /* rx count */
+ int t_cnt; /* tx_count */
+ uint32 wordlen; /* host processor 16/32bits */
+ uint32 prev_fun;
+ uint32 chip;
+ uint32 chiprev;
+ bool resp_delay_all;
+ bool dwordmode;
+ bool resp_delay_new;
+
+ struct spierrstats_t spierrstats;
+};
+
+/************************************************************
+ * Internal interfaces: per-port references into bcmspibrcm.c
+ */
+
+/* Global message bits */
+extern uint sd_msglevel;
+
+/**************************************************************
+ * Internal interfaces: bcmspibrcm.c references to per-port code
+ */
+
+/* Interrupt (de)registration routines */
+extern int spi_register_irq(sdioh_info_t *sd, uint irq);
+extern void spi_free_irq(uint irq, sdioh_info_t *sd);
+
+/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
+extern void spi_lock(sdioh_info_t *sd);
+extern void spi_unlock(sdioh_info_t *sd);
+
+/* Allocate/init/free per-OS private data */
+extern int spi_osinit(sdioh_info_t *sd);
+extern void spi_osfree(sdioh_info_t *sd);
+
+#define SPI_RW_FLAG_M BITFIELD_MASK(1) /* Bit [31] - R/W Command Bit */
+#define SPI_RW_FLAG_S 31
+#define SPI_ACCESS_M BITFIELD_MASK(1) /* Bit [30] - Fixed/Incr Access */
+#define SPI_ACCESS_S 30
+#define SPI_FUNCTION_M BITFIELD_MASK(2) /* Bit [29:28] - Function Number */
+#define SPI_FUNCTION_S 28
+#define SPI_REG_ADDR_M BITFIELD_MASK(17) /* Bit [27:11] - Address */
+#define SPI_REG_ADDR_S 11
+#define SPI_LEN_M BITFIELD_MASK(11) /* Bit [10:0] - Packet length */
+#define SPI_LEN_S 0
+
+#endif /* _BCM_SPI_BRCM_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h index b735090..cbbd7ef 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmutils.h +++ b/drivers/net/wireless/bcmdhd/include/bcmutils.h @@ -659,12 +659,11 @@ extern void *_bcmutils_dummy_fn; (ea).octet[5] #if !defined(SIMPLE_MAC_PRINT) #define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x" -#define STR_TO_MACD(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] +#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] #else #define MACDBG "%02x:%02x:%02x" -#define STR_TO_MACD(ea) (ea)[0], (ea)[4], (ea)[5] -#endif - +#define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5] +#endif /* SIMPLE_MAC_PRINT */ typedef struct bcm_bit_desc { uint32 bit; diff --git a/drivers/net/wireless/bcmdhd/include/bcmwifi.h b/drivers/net/wireless/bcmdhd/include/bcmwifi.h new file mode 100644 index 0000000..e5207e9 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/bcmwifi.h @@ -0,0 +1,165 @@ +/* + * Misc utility routines for WL and Apps + * This header file housing the define and function prototype use by + * both the wl driver, tools & Apps. + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: bcmwifi.h 277737 2011-08-16 17:54:59Z $ + */ + + +#ifndef _bcmwifi_h_ +#define _bcmwifi_h_ + + + +typedef uint16 chanspec_t; + + +#define CH_UPPER_SB 0x01 +#define CH_LOWER_SB 0x02 +#define CH_EWA_VALID 0x04 +#define CH_20MHZ_APART 4 +#define CH_10MHZ_APART 2 +#define CH_5MHZ_APART 1 +#define CH_MAX_2G_CHANNEL 14 +#define WLC_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL +#define MAXCHANNEL 224 + +#define WL_CHANSPEC_CHAN_MASK 0x00ff +#define WL_CHANSPEC_CHAN_SHIFT 0 + +#define WL_CHANSPEC_CTL_SB_MASK 0x0300 +#define WL_CHANSPEC_CTL_SB_SHIFT 8 +#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 +#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 +#define WL_CHANSPEC_CTL_SB_NONE 0x0300 + +#define WL_CHANSPEC_BW_MASK 0x0C00 +#define WL_CHANSPEC_BW_SHIFT 10 +#define WL_CHANSPEC_BW_10 0x0400 +#define WL_CHANSPEC_BW_20 0x0800 +#define WL_CHANSPEC_BW_40 0x0C00 + +#define WL_CHANSPEC_BAND_MASK 0xf000 +#define WL_CHANSPEC_BAND_SHIFT 12 +#define WL_CHANSPEC_BAND_5G 0x1000 +#define WL_CHANSPEC_BAND_2G 0x2000 +#define INVCHANSPEC 255 + + +#define WF_CHAN_FACTOR_2_4_G 4814 +#define WF_CHAN_FACTOR_5_G 10000 +#define WF_CHAN_FACTOR_4_G 8000 + + +#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) +#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ + ((channel) + CH_10MHZ_APART) : 0) +#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) +#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ + WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ + WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) +#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ + ((channel) + CH_20MHZ_APART) : 0) +#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ + ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ + ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ + WL_CHANSPEC_BAND_5G)) +#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) +#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) + + +#define CHSPEC_CTL_SB(chspec) (chspec & WL_CHANSPEC_CTL_SB_MASK) +#define CHSPEC_BW(chspec) (chspec & WL_CHANSPEC_BW_MASK) + +#ifdef WL11N_20MHZONLY + +#define CHSPEC_IS10(chspec) 0 +#define CHSPEC_IS20(chspec) 1 +#ifndef CHSPEC_IS40 +#define CHSPEC_IS40(chspec) 0 +#endif + +#else + +#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) +#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) +#ifndef CHSPEC_IS40 +#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) +#endif + +#endif + +#define CHSPEC_IS20_UNCOND(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) + +#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) +#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) +#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) +#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) +#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) +#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ + (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ + (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) +#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) + +#define CHANSPEC_STR_LEN 8 + + +#define WLC_MAXRATE 108 +#define WLC_RATE_1M 2 +#define WLC_RATE_2M 4 +#define WLC_RATE_5M5 11 +#define WLC_RATE_11M 22 +#define WLC_RATE_6M 12 +#define WLC_RATE_9M 18 +#define WLC_RATE_12M 24 +#define WLC_RATE_18M 36 +#define WLC_RATE_24M 48 +#define WLC_RATE_36M 72 +#define WLC_RATE_48M 96 +#define WLC_RATE_54M 108 + +#define WLC_2G_25MHZ_OFFSET 5 + + +extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); + + +extern chanspec_t wf_chspec_aton(char *a); + + +extern bool wf_chspec_malformed(chanspec_t chanspec); + + +extern uint8 wf_chspec_ctlchan(chanspec_t chspec); + + +extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); + + +extern int wf_mhz2channel(uint freq, uint start_factor); + + +extern int wf_channel2mhz(uint channel, uint start_factor); + +#endif diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h index b36fa0c..11fff55 100644 --- a/drivers/net/wireless/bcmdhd/include/dhdioctl.h +++ b/drivers/net/wireless/bcmdhd/include/dhdioctl.h @@ -25,7 +25,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhdioctl.h 357867 2012-09-20 06:57:44Z $ + * $Id: dhdioctl.h 354894 2012-09-04 12:34:07Z $ */ #ifndef _dhdioctl_h_ diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 2d4b886..60f9838 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -30,26 +30,26 @@ #define EPI_MINOR_VERSION 28 -#define EPI_RC_NUMBER 11 +#define EPI_RC_NUMBER 13 -#define EPI_INCREMENTAL_NUMBER 12 +#define EPI_INCREMENTAL_NUMBER 1 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 1, 28, 11, 12 +#define EPI_VERSION 1, 28, 13, 1 -#define EPI_VERSION_NUM 0x011c0b0c +#define EPI_VERSION_NUM 0x011c0d01 -#define EPI_VERSION_DEV 1.28.11 +#define EPI_VERSION_DEV 1.28.13 /* Driver Version String, ASCII, 32 chars max */ #ifdef BCMINTERNAL -#define EPI_VERSION_STR "1.28.11.12 (r BCMINT)" +#define EPI_VERSION_STR "1.28.13.1 (r BCMINT)" #else #ifdef WLTEST -#define EPI_VERSION_STR "1.28.11.12 (r WLTEST)" +#define EPI_VERSION_STR "1.28.13.1 (r WLTEST)" #else -#define EPI_VERSION_STR "1.28.11.12 (Add_p2pPatch_1012)" +#define EPI_VERSION_STR "1.28.13.1 (r)" #endif #endif /* BCMINTERNAL */ diff --git a/drivers/net/wireless/bcmdhd/include/htsf.h b/drivers/net/wireless/bcmdhd/include/htsf.h new file mode 100644 index 0000000..d875edb --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/htsf.h @@ -0,0 +1,74 @@ +/* + * Time stamps for latency measurements + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: htsf.h 277737 2011-08-16 17:54:59Z $ + */ +#ifndef _HTSF_H_ +#define _HTSF_H_ + +#define HTSFMAGIC 0xCDCDABAB /* in network order for tcpdump */ +#define HTSFENDMAGIC 0xEFEFABAB /* to distinguish from RT2 magic */ +#define HTSF_HOSTOFFSET 102 +#define HTSF_DNGLOFFSET HTSF_HOSTOFFSET - 4 +#define HTSF_DNGLOFFSET2 HTSF_HOSTOFFSET + 106 +#define HTSF_MIN_PKTLEN 200 +#define ETHER_TYPE_BRCM_PKTDLYSTATS 0x886d + +typedef enum htsfts_type { + T10, + T20, + T30, + T40, + T50, + T60, + T70, + T80, + T90, + TA0, + TE0 +} htsf_timestamp_t; + +typedef struct { + uint32 magic; + uint32 prio; + uint32 seqnum; + uint32 misc; + uint32 c10; + uint32 t10; + uint32 c20; + uint32 t20; + uint32 t30; + uint32 t40; + uint32 t50; + uint32 t60; + uint32 t70; + uint32 t80; + uint32 t90; + uint32 cA0; + uint32 tA0; + uint32 cE0; + uint32 tE0; + uint32 endmagic; +} htsfts_t; + +#endif /* _HTSF_H_ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/p2p.h b/drivers/net/wireless/bcmdhd/include/proto/p2p.h index 206effc..2b6fef6 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/p2p.h +++ b/drivers/net/wireless/bcmdhd/include/proto/p2p.h @@ -376,8 +376,7 @@ typedef struct wifi_p2p_pub_act_frame wifi_p2p_pub_act_frame_t; #define P2P_PAF_DEVDIS_RSP 6 #define P2P_PAF_PROVDIS_REQ 7 #define P2P_PAF_PROVDIS_RSP 8 -#define P2P_PAF_SUBTYPE_INVALID 255 - +#define P2P_PAF_SUBTYPE_INVALID 255 /* Invalid Subtype */ #define P2P_TYPE_MNREQ P2P_PAF_GON_REQ #define P2P_TYPE_MNRSP P2P_PAF_GON_RSP diff --git a/drivers/net/wireless/bcmdhd/include/sbsdio.h b/drivers/net/wireless/bcmdhd/include/sbsdio.h index 00e44d2..0e9ad7d 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsdio.h +++ b/drivers/net/wireless/bcmdhd/include/sbsdio.h @@ -120,6 +120,7 @@ #define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */ #define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */ #define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */ +#define SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK 0x10 /* Enable function 2 tx for each block */ /* SBSDIO_FUNC1_CHIPCLKCSR */ diff --git a/drivers/net/wireless/bcmdhd/include/spid.h b/drivers/net/wireless/bcmdhd/include/spid.h index f1ecc22..6d2d403 100644 --- a/drivers/net/wireless/bcmdhd/include/spid.h +++ b/drivers/net/wireless/bcmdhd/include/spid.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: spid.h 354197 2012-08-30 09:05:59Z $ + * $Id: spid.h 354172 2012-08-30 07:19:26Z $ */ #ifndef _SPI_H diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index 5205c07..33811a1 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h 357629 2012-09-19 12:51:08Z $ + * $Id: wlioctl.h 357627 2012-09-19 12:42:22Z $ */ #ifndef _wlioctl_h_ diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c index ddb8372..d03a095 100644 --- a/drivers/net/wireless/bcmdhd/linux_osl.c +++ b/drivers/net/wireless/bcmdhd/linux_osl.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.c 350283 2012-08-12 07:47:25Z $ + * $Id: linux_osl.c 355147 2012-09-05 15:03:49Z $ */ #define LINUX_PORT @@ -191,7 +191,7 @@ osl_attach(void *pdev, uint bustype, bool pkttag) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) gfp_t flags; - flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; osh = kmalloc(sizeof(osl_t), flags); #else osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); @@ -288,7 +288,7 @@ osl_detach(osl_t *osh) static struct sk_buff *osl_alloc_skb(unsigned int len) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - gfp_t flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + gfp_t flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; return __dev_alloc_skb(len, flags); #else @@ -373,7 +373,7 @@ osl_ctfpool_init(osl_t *osh, uint numobj, uint size) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) gfp_t flags; - flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; osh->ctfpool = kmalloc(sizeof(ctfpool_t), flags); #else osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); @@ -896,7 +896,7 @@ original: #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; if ((addr = kmalloc(size, flags)) == NULL) { #else if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { @@ -1058,7 +1058,7 @@ osl_pktdup(osl_t *osh, void *skb) PKTCTFMAP(osh, skb); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; if ((p = skb_clone((struct sk_buff *)skb, flags)) == NULL) #else if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 0470a9c..00b6969 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_android.c 354184 2012-08-30 08:08:08Z $ + * $Id: wl_android.c 358186 2012-09-21 14:36:14Z $ */ #include <linux/module.h> @@ -141,8 +141,6 @@ typedef struct cmd_tlv { #define CMD_COUNTRYREV_GET "GETCOUNTRYREV" #endif /* ROAM_API */ -#define CMD_SETROAMMODE "SETROAMMODE" - #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) #define CMD_GETROAMSCANCONTROL "GETROAMSCANCONTROL" #define CMD_SETROAMSCANCONTROL "SETROAMSCANCONTROL" @@ -227,6 +225,10 @@ int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) #endif /* WL_CFG80211 */ extern int dhd_os_check_if_up(void *dhdp); extern void *bcmsdh_get_drvdata(void); +#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) +extern int dhd_wlfc_init(dhd_pub_t *dhd); +extern void dhd_wlfc_deinit(dhd_pub_t *dhd); +#endif #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) /* wl_roam.c */ @@ -242,9 +244,7 @@ extern bool ap_fw_loaded; extern char iface_name[IFNAMSIZ]; #endif -#ifndef WIFI_TURNOFF_DELAY #define WIFI_TURNOFF_DELAY 0 -#endif /** * Local (static) functions and variables */ @@ -1241,6 +1241,9 @@ int wl_android_wifi_on(struct net_device *dev) if (dhd_dev_init_ioctl(dev) < 0) ret = -EFAULT; } +#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) + dhd_wlfc_init(bcmsdh_get_drvdata()); +#endif g_wifi_on = TRUE; } @@ -1262,6 +1265,9 @@ int wl_android_wifi_off(struct net_device *dev) dhd_net_if_lock(dev); if (g_wifi_on) { +#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) + dhd_wlfc_deinit(bcmsdh_get_drvdata()); +#endif ret = dhd_dev_reset(dev, TRUE); sdioh_stop(NULL); dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); @@ -1413,7 +1419,7 @@ wl_android_sta_diassoc(struct net_device *dev, const char* straddr) bcm_ether_atoe(straddr, &scbval.ea); DHD_INFO(("%s: deauth STA: "MACDBG "\n", __FUNCTION__, - STR_TO_MACD(scbval.ea.octet))); + MAC2STRDBG(scbval.ea.octet))); wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scb_val_t), true); @@ -1517,29 +1523,6 @@ wl_android_set_ampdu_mpdu(struct net_device *dev, const char* string_num) } #endif /* SUPPORT_AMPDU_MPDU_CMD */ -int wl_android_set_roam_mode(struct net_device *dev, -char *command, int total_len) -{ - int error = 0; - int mode = 0; - - if (sscanf(command, "%*s %d", &mode) != 1) { - DHD_ERROR(("wl_android_set_roam_mode:"\ - "Failed to get Parameter\n")); - return -1; - } - - error = wldev_iovar_setint(dev, "roam_off", mode); - if (error) { - DHD_ERROR(("wl_android_set_roam_mode:"\ - "Failed to set roaming Mode %d, error = %d\n", mode, error)); - return -1; - } else { - DHD_ERROR(("wl_android_set_roam_mode:"\ - "succeeded to set roaming Mode %d, error = %d\n", mode, error)); - } - return error; -} int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) { #define PRIVATE_COMMAND_MAX_LEN 8192 @@ -1658,7 +1641,16 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) } else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; +#ifdef WL_HOST_BAND_MGMT + if (wl_cfg80211_set_band(net, band) < 0) { + bytes_written = -1; + goto exit; + } + if (band == WLC_BAND_AUTO) + bytes_written = wldev_set_band(net, band); +#else bytes_written = wldev_set_band(net, band); +#endif /* WL_HOST_BAND_MGMT */ } else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { bytes_written = wl_android_get_band(net, command, priv_cmd.total_len); @@ -1874,10 +1866,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0) bytes_written = wl_android_ch_res_rl(net, false); #endif /* CUSTOMER_HW4 */ - else if (strnicmp(command, CMD_SETROAMMODE, - strlen(CMD_SETROAMMODE)) == 0) - bytes_written = wl_android_set_roam_mode(net, - command, priv_cmd.total_len); else { DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); snprintf(command, 3, "OK"); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index a0e8616..7324e53 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfg80211.c 358102 2012-09-21 04:45:06Z $ + * $Id: wl_cfg80211.c 359682 2012-09-28 20:23:14Z $ */ #include <typedefs.h> @@ -59,10 +59,6 @@ #include <wl_cfg80211.h> #include <wl_cfgp2p.h> -#ifdef PROP_TXSTATUS -#include <dhd_wlfc.h> -#endif - #ifdef WL11U #ifndef WL_ENABLE_P2P_IF #error "You should enable WL_ENABLE_P2P_IF and Only supported in JB" @@ -259,6 +255,10 @@ static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx); static s32 wl_cfg80211_resume(struct wiphy *wiphy); +static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct net_device *dev, u64 cookie); +static s32 wl_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8* mac_addr); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); #else @@ -373,9 +373,10 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev); static void wl_free_wdev(struct wl_priv *wl); static s32 wl_inform_bss(struct wl_priv *wl); -static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 roam_done_flag); -static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 roam_done_flag); +static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi); +static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev); static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); +static s32 wl_cfg80211_40MHz_to_20MHz_Channel(chanspec_t chspec); static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, const u8 *mac_addr, @@ -484,11 +485,11 @@ do { \ extern int dhd_wait_pend8021x(struct net_device *dev); -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB extern int disable_proptx; extern int dhd_wlfc_init(dhd_pub_t *dhd); extern void dhd_wlfc_deinit(dhd_pub_t *dhd); -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ #if (WL_DBG_LEVEL > 0) #define WL_DBG_ESTR_MAX 50 @@ -848,7 +849,8 @@ static void swap_key_to_BE(struct wl_wsec_key *key) key->iv_initialized = dtoh32(key->iv_initialized); } -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) +//#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) +#if 0 /* For debug: Dump the contents of the encoded wps ie buffe */ static void wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc) @@ -934,6 +936,37 @@ wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc) } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ +static s32 +wl_cfg80211_40MHz_to_20MHz_Channel(chanspec_t chspec) +{ + u32 channel = chspec & WL_CHANSPEC_CHAN_MASK; + + /* If chspec is not for 40MHz. Do nothing */ + if (!(chspec & WL_CHANSPEC_BW_40)) + return channel; + + if ((channel < 0) || (channel > MAXCHANNEL)) + return -1; + + switch (channel) { + /* 5G Channels */ + case 38: + case 46: + case 151: + case 159: + if (chspec & WL_CHANSPEC_CTL_SB_LOWER) + channel = channel - CH_10MHZ_APART; + else if (chspec & WL_CHANSPEC_CTL_SB_UPPER) + channel = channel + CH_10MHZ_APART; + break; + default: + /* Mhz adjustment not required. Use as is */ + WL_ERR(("Unsupported channel: %d \n", channel)); + } + + return channel; +} + static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) { chanspec_t chspec; @@ -962,7 +995,12 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) else { bss = (struct wl_bss_info *) (wl->extra_buf + 4); chspec = bss->chanspec; - WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec)); + if (chspec & WL_CHANSPEC_BW_40) { + uint32 channel = wl_cfg80211_40MHz_to_20MHz_Channel(chspec); + chspec = wl_ch_host_to_driver(channel); + } + + WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec)); } return chspec; } @@ -991,26 +1029,24 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, s32 wlif_type = -1; s32 mode = 0; s32 val = 0; -#if defined(WL_ENABLE_P2P_IF) s32 dhd_mode = 0; -#endif /* (WL_ENABLE_P2P_IF) */ chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); struct net_device *_ndev; struct ether_addr primary_mac; int (*net_attach)(void *dhdp, int ifidx); bool rollback_lock = false; -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB s32 up = 1; dhd_pub_t *dhd; -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ if (!wl) return ERR_PTR(-EINVAL); -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB dhd = (dhd_pub_t *)(wl->pub); -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ /* Use primary I/F for sending cmds down to firmware */ @@ -1081,10 +1117,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, return ERR_PTR(-ENOMEM); } -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB if (!dhd) return ERR_PTR(-ENODEV); -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ if (!wl->p2p || !wl->p2p->vir_ifname) return ERR_PTR(-ENODEV); @@ -1101,7 +1137,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); wl_notify_escan_complete(wl, _ndev, true, true); -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB if (!wl->wlfc_on && !disable_proptx) { dhd->wlfc_enabled = true; dhd_wlfc_init(dhd); @@ -1110,7 +1146,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, WL_ERR(("WLC_UP return err:%d\n", err)); wl->wlfc_on = true; } -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ /* In concurrency case, STA may be already associated in a particular channel. * so retrieve the current channel of primary interface and then start the virtual @@ -1171,13 +1207,11 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, "created net attach done\n", wl->p2p->vir_ifname)); if (mode == WL_MODE_AP) wl_set_drv_status(wl, CONNECTED, _ndev); -#if defined(WL_ENABLE_P2P_IF) if (type == NL80211_IFTYPE_P2P_CLIENT) - dhd_mode = P2P_GC_ENABLED; + dhd_mode = DHD_FLAG_P2P_GC_MODE; else if (type == NL80211_IFTYPE_P2P_GO) - dhd_mode = P2P_GO_ENABLED; + dhd_mode = DHD_FLAG_P2P_GO_MODE; DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); -#endif /* (WL_ENABLE_P2P_IF) */ } else { /* put back the rtnl_lock again */ if (rollback_lock) @@ -1194,13 +1228,13 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname)); memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); wl->p2p->vif_created = false; -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB if (dhd->wlfc_enabled && wl->wlfc_on) { dhd->wlfc_enabled = false; dhd_wlfc_deinit(dhd); wl->wlfc_on = false; } -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ } } fail: @@ -1246,9 +1280,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) (&wl->iface_disable, msecs_to_jiffies(500)); } wl_set_p2p_status(wl, IF_DELETING); -#if defined(WL_ENABLE_P2P_IF) DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl)); -#endif /* (WL_ENABLE_P2P_IF)) */ /* for GO */ if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { @@ -1307,7 +1339,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, s32 mode = 0; chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); - + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); WL_DBG(("Enter type %d\n", type)); switch (type) { case NL80211_IFTYPE_MONITOR: @@ -1334,7 +1366,8 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, default: return -EINVAL; } - + if (!dhd) + return -EINVAL; if (ap) { wl_set_mode_by_netdev(wl, ndev, mode); if (wl->p2p_supported && wl->p2p->vif_created) { @@ -1359,6 +1392,8 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, (wl_get_p2p_status(wl, IF_CHANGED) == true), msecs_to_jiffies(MAX_WAIT_TIME)); wl_set_mode_by_netdev(wl, ndev, mode); + dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE; + dhd->op_mode |= DHD_FLAG_P2P_GO_MODE; wl_clr_p2p_status(wl, IF_CHANGING); wl_clr_p2p_status(wl, IF_CHANGED); if (mode == WL_MODE_AP) @@ -1429,9 +1464,9 @@ wl_cfg80211_ifdel_ops(struct net_device *ndev) struct wl_priv *wl = wlcfg_drv_priv; bool rollback_lock = false; s32 index = 0; -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ if (!ndev || (strlen(ndev->name) == 0)) { WL_ERR(("net is NULL\n")); return 0; @@ -1463,15 +1498,13 @@ wl_cfg80211_ifdel_ops(struct net_device *ndev) wl_cfgp2p_clear_management_ie(wl, index); WL_DBG(("index : %d\n", index)); -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB if (dhd->wlfc_enabled && wl->wlfc_on) { - dhd_os_wlfc_block(dhd); dhd->wlfc_enabled = false; dhd_wlfc_deinit(dhd); wl->wlfc_on = false; - dhd_os_wlfc_unblock(dhd); } -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ wl_clr_drv_status(wl, CONNECTED, ndev); } /* Wake up any waiting thread */ @@ -1573,7 +1606,7 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req u32 n_channels; u16 channel; chanspec_t chanspec; - s32 i = 0, offset; + s32 i = 0, j = 0, offset; char *ptr; wlc_ssid_t ssid; struct wl_priv *wl = wlcfg_drv_priv; @@ -1619,25 +1652,39 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN))) continue; - if (request->channels[i]->band == IEEE80211_BAND_2GHZ) + if (request->channels[i]->band == IEEE80211_BAND_2GHZ) { +#ifdef WL_HOST_BAND_MGMT + if (wl->curr_band == WLC_BAND_5G) { + WL_DBG(("In 5G only mode, omit 2G channel:%d\n", channel)); + continue; + } +#endif /* WL_HOST_BAND_MGMT */ chanspec |= WL_CHANSPEC_BAND_2G; - else + } else { +#ifdef WL_HOST_BAND_MGMT + if (wl->curr_band == WLC_BAND_2G) { + WL_DBG(("In 2G only mode, omit 5G channel:%d\n", channel)); + continue; + } +#endif /* WL_HOST_BAND_MGMT */ chanspec |= WL_CHANSPEC_BAND_5G; + } chanspec |= WL_CHANSPEC_BW_20; chanspec |= WL_CHANSPEC_CTL_SB_NONE; - params->channel_list[i] = channel; - params->channel_list[i] &= WL_CHANSPEC_CHAN_MASK; - params->channel_list[i] |= chanspec; + params->channel_list[j] = channel; + params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK; + params->channel_list[j] |= chanspec; WL_SCAN(("Chan : %d, Channel spec: %x \n", - channel, params->channel_list[i])); - params->channel_list[i] = wl_chspec_host_to_driver(params->channel_list[i]); + channel, params->channel_list[j])); + params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]); + j++; } } else { WL_SCAN(("Scanning all channels\n")); } - n_channels = i; + n_channels = j; /* Copy ssid array if applicable */ WL_SCAN(("### List of SSIDs to scan ###\n")); if (n_ssids > 0) { @@ -1737,7 +1784,7 @@ static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), false); + &passive_scan, sizeof(passive_scan), true); if (unlikely(err)) { WL_DBG(("error (%d)\n", err)); return err; @@ -1794,6 +1841,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, #ifdef USE_INITIAL_2G_SCAN bool is_first_init_2g_scan = false; #endif /* USE_INITIAL_2G_SCAN */ + WL_DBG(("Enter \n")); if (!request || !wl) { @@ -1833,6 +1881,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, #endif /* USE_INITIAL_2G_SCAN */ + /* if scan request is not empty parse scan request paramters */ + if (request != NULL) { n_channels = request->n_channels; n_ssids = request->n_ssids; /* Allocate space for populating ssids in wl_iscan_params struct */ @@ -1844,6 +1894,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, /* Allocate space for populating ssids in wl_iscan_params struct */ params_size += sizeof(struct wlc_ssid) * n_ssids; + } params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL); if (params == NULL) { err = -ENOMEM; @@ -1895,20 +1946,33 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, n_valid_chan = dtoh32(list->count); for (i = 0; i < num_chans; i++) { +#ifdef WL_HOST_BAND_MGMT + int channel_band = 0; +#endif /* WL_HOST_BAND_MGMT */ _freq = request->channels[i]->center_freq; channel = ieee80211_frequency_to_channel(_freq); - /* remove DFS channels */ - if (!(request->channels[i]->flags & +#ifdef WL_HOST_BAND_MGMT + channel_band = (channel > CH_MAX_2G_CHANNEL) ? + WLC_BAND_5G : WLC_BAND_2G; + if ((wl->curr_band != WLC_BAND_AUTO) && + (wl->curr_band != channel_band) && + !IS_P2P_SOCIAL_CHANNEL(channel)) + continue; +#endif /* WL_HOST_BAND_MGMT */ + + /* ignore DFS channels */ + if (request->channels[i]->flags & (IEEE80211_CHAN_RADAR - | IEEE80211_CHAN_PASSIVE_SCAN))) { - for (j = 0; j < n_valid_chan; j++) { - /* allows only supported channel on - * current reguatory - */ - if (channel == (dtoh32(list->element[j]))) - default_chan_list[n_nodfs++] = - channel; - } + | IEEE80211_CHAN_PASSIVE_SCAN)) + continue; + + for (j = 0; j < n_valid_chan; j++) { + /* allows only supported channel on + * current reguatory + */ + if (channel == (dtoh32(list->element[j]))) + default_chan_list[n_nodfs++] = + channel; } } @@ -1969,7 +2033,7 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING; passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), false); + &passive_scan, sizeof(passive_scan), true); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); goto exit; @@ -2183,7 +2247,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, WL_SCAN(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len)); passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), false); + &passive_scan, sizeof(passive_scan), true); if (unlikely(err)) { WL_SCAN(("WLC_SET_PASSIVE_SCAN error (%d)\n", err)); goto scan_out; @@ -2235,7 +2299,7 @@ scan_out: if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) WL_ERR(("FW is connected with " MACDBG "/n", - STR_TO_MACD(bssid.octet))); + MAC2STRDBG(bssid.octet))); else WL_ERR(("GET BSSID failed with %d\n", ret)); @@ -2302,7 +2366,7 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l) u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL); retry = htod32(retry); - err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), false); + err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true); if (unlikely(err)) { WL_ERR(("cmd (%d) , error (%d)\n", cmd, err)); return err; @@ -2420,7 +2484,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, - sizeof(join_params), false); + sizeof(join_params), true); if (unlikely(err)) { WL_ERR(("Error (%d)\n", err)); return err; @@ -2903,7 +2967,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, scbval.val = htod32(scbval.val); WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n", - STR_TO_MACD(bssid.octet))); + MAC2STRDBG(bssid.octet))); err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); if (unlikely(err)) { @@ -3057,8 +3121,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, /* increate dwell time to receive probe response or detect Beacon * from target AP at a noisy air only during connect command */ - ext_join_params->scan.active_time = DHD_SCAN_ACTIVE_TIME*8; - ext_join_params->scan.passive_time = DHD_SCAN_PASSIVE_TIME*3; + ext_join_params->scan.active_time = WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS; + ext_join_params->scan.passive_time = WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS; /* Set up join scan parameters */ ext_join_params->scan.scan_type = -1; ext_join_params->scan.nprobes @@ -3641,7 +3705,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, } if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) { WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n", - STR_TO_MACD(mac), STR_TO_MACD(curmacp))); + MAC2STRDBG(mac), MAC2STRDBG(curmacp))); } /* Report the current tx rate */ @@ -3692,6 +3756,24 @@ get_station_err: return err; } +/* Function to update sta power save mode for Kernel wifi stack */ +int wl_cfg80211_update_power_mode(struct net_device *dev) +{ + int pm = -1; + int err; + + err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), false); + if (err || (pm == -1)) { + WL_ERR(("error (%d)\n", err)); + } else { + pm = (pm == PM_OFF) ? false : true; + WL_DBG(("%s: %d\n", __func__, pm)); + if (dev->ieee80211_ptr) + dev->ieee80211_ptr->ps = pm; + } + return err; +} + static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, s32 timeout) @@ -3700,6 +3782,9 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, s32 err = 0; struct wl_priv *wl = wiphy_priv(wiphy); struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev); +#ifndef SUPPORT_PM2_ONLY + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +#endif CHECK_SYS_UP(wl); @@ -3707,7 +3792,13 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, return err; } + /* android has special hooks to change pm when kernel suspended */ +#ifndef SUPPORT_PM2_ONLY + pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF; +#else pm = enabled ? PM_FAST : PM_OFF; +#endif + /* Do not enable the power save after assoc if it is p2p interface */ if (_net_info->pm_block || wl->vsdb_mode) { WL_DBG(("Do not enable the power save\n")); @@ -4003,13 +4094,6 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, } else { ndev = dev; } - - if (!wl->p2p) { - WL_DBG(("wl->p2p is not initialized\n")); - err = BCME_ERROR; - goto exit; - } - #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST if (wl_get_drv_status(wl, SCANNING, ndev)) { wl_notify_escan_complete(wl, ndev, true, true); @@ -4344,7 +4428,6 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, u8 category, action; s32 tx_retry; struct p2p_config_af_params config_af_params; - dhd_pub_t *dhd; #ifdef VSDB ulong off_chan_started_jiffies = 0; #endif @@ -4421,16 +4504,8 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, } else if (category == P2P_AF_CATEGORY) { /* do not configure anything. it will be sent with a default configuration */ } else { - dhd = (dhd_pub_t *)(wl->pub); - if ((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) { - WL_ERR(("Unknown Frame: category 0x%x, action 0x%x\n", - category, action)); - wl_clr_drv_status(wl, SENDING_ACT_FRM, dev); - return false; - } else { - WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n", - category, action)); - } + WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n", + category, action)); } /* To make sure to send successfully action frame, we have to turn off mpc */ @@ -4593,10 +4668,12 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, const u8* buf, size_t len, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +#if 1 bool no_cck, #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) +#if 1 bool dont_wait_for_ack, #endif u64 *cookie) @@ -4658,8 +4735,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, ieee80211_is_deauth(mgmt->frame_control)) { memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN); scb_val.val = mgmt->u.disassoc.reason_code; - wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, + err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, sizeof(scb_val_t), true); + if (err < 0) + WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err)); WL_DBG(("Disconnect STA : %s scb_val.val %d\n", bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val)); @@ -5233,7 +5312,8 @@ wl_cfg80211_bcn_validate_sec( } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#if 1 static s32 wl_cfg80211_bcn_set_params( struct cfg80211_ap_settings *info, struct net_device *dev, @@ -5407,7 +5487,8 @@ exit: return err; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#if 1 s32 wl_cfg80211_parse_set_ies( struct net_device *dev, @@ -5531,7 +5612,53 @@ static s32 wl_cfg80211_hostapd_sec( return 0; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +static s32 +wl_cfg80211_del_station( + struct wiphy *wiphy, + struct net_device *ndev, + u8* mac_addr) +{ + struct net_device *dev; + struct wl_priv *wl = wiphy_priv(wiphy); + scb_val_t scb_val; + s8 eabuf[ETHER_ADDR_STR_LEN]; + + WL_DBG(("Entry\n")); + if (mac_addr == NULL) { + WL_DBG(("mac_addr is NULL ignore it\n")); + return 0; + } + + if (ndev == wl->p2p_net) { + dev = wl_to_prmry_ndev(wl); + } else { + dev = ndev; + } + + if (p2p_is_on(wl)) { + /* Suspend P2P discovery search-listen to prevent it from changing the + * channel. + */ + if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) { + WL_ERR(("Can not disable discovery mode\n")); + return -EFAULT; + } + } + + memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN); + scb_val.val = DOT11_RC_DEAUTH_LEAVING; + if (wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, + sizeof(scb_val_t), true)) + WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON failed\n")); + WL_DBG(("Disconnect STA : %s scb_val.val %d\n", + bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), + scb_val.val)); + wl_delay(400); + return 0; +} + +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#if 1 static s32 wl_cfg80211_start_ap( struct wiphy *wiphy, @@ -5661,50 +5788,6 @@ exit: return err; } static s32 -wl_cfg80211_del_station( - struct wiphy *wiphy, - struct net_device *ndev, - u8* mac_addr) -{ - struct net_device *dev; - struct wl_priv *wl = wiphy_priv(wiphy); - scb_val_t scb_val; - s8 eabuf[ETHER_ADDR_STR_LEN]; - - WL_DBG(("Entry\n")); - if (mac_addr == NULL) { - WL_DBG(("mac_addr is NULL ignore it\n")); - return 0; - } - - if (ndev == wl->p2p_net) { - dev = wl_to_prmry_ndev(wl); - } else { - dev = ndev; - } - - if (p2p_is_on(wl)) { - /* Suspend P2P discovery search-listen to prevent it from changing the - * channel. - */ - if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) { - WL_ERR(("Can not disable discovery mode\n")); - return -EFAULT; - } - } - - memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN); - scb_val.val = DOT11_RC_DEAUTH_LEAVING; - wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, - sizeof(scb_val_t), true); - WL_DBG(("Disconnect STA : %s scb_val.val %d\n", - bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), - scb_val.val)); - wl_delay(400); - return 0; -} - -static s32 wl_cfg80211_change_beacon( struct wiphy *wiphy, struct net_device *dev, @@ -5902,15 +5985,21 @@ static struct cfg80211_ops wl_cfg80211_ops = { .mgmt_frame_register = wl_cfg80211_mgmt_frame_register, .change_bss = wl_cfg80211_change_bss, .set_channel = wl_cfg80211_set_channel, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) +//#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) +#if 0 .set_beacon = wl_cfg80211_add_set_beacon, .add_beacon = wl_cfg80211_add_set_beacon, #else .change_beacon = wl_cfg80211_change_beacon, .start_ap = wl_cfg80211_start_ap, .stop_ap = wl_cfg80211_stop_ap, - .del_station = wl_cfg80211_del_station, #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ +#ifdef WL_SCHED_SCAN + .sched_scan_start = wl_cfg80211_sched_scan_start, + .sched_scan_stop = wl_cfg80211_sched_scan_stop, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ + .del_station = wl_cfg80211_del_station, + .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait, }; s32 wl_mode_to_nl80211_iftype(s32 mode) @@ -5980,14 +6069,17 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev * to let Supplicant to provide channel info and FW letter may roam * if needed so DON'T advertise that featur eto Supplicant. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +#if 1 /* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */ #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) +#if 1 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_OFFCHAN_TX; #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#if 1 /* From 3.4 kernel ownards AP_SME flag can be advertised * to remove the patch from supplicant */ @@ -6042,7 +6134,7 @@ static s32 wl_inform_bss(struct wl_priv *wl) #ifdef ROAM_CHANNEL_CACHE add_roam_cache(bi); #endif - err = wl_inform_single_bss(wl, bi, 0); + err = wl_inform_single_bss(wl, bi); if (unlikely(err)) break; } @@ -6052,7 +6144,7 @@ static s32 wl_inform_bss(struct wl_priv *wl) return err; } -static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 roam_done_flag) +static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) { struct wiphy *wiphy = wl_to_wiphy(wl); struct ieee80211_mgmt *mgmt; @@ -6067,7 +6159,6 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 r u32 freq; s32 err = 0; gfp_t aflags; - u8 *ie_offset=NULL; if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) { WL_DBG(("Beacon is larger than buffer. Discarding\n")); @@ -6108,35 +6199,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 r beacon_proberesp->capab_info = cpu_to_le16(bi->capability); wl_rst_ie(wl); -#define WLAN_EID_SSID 0 - ie_offset = ((u8 *) bi) + bi->ie_offset; - - if ( roam_done_flag && ((int)(*(ie_offset)) == WLAN_EID_SSID && ((int)(*(ie_offset+1)) == 0 || (int)(*(ie_offset+2)) == 0))) { - u8 *ie_new_offset = NULL; - uint8 ie_new_length; - - WL_ERR(("Changing the SSID Info\n")); - - ie_new_offset = (u8 *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); - if (ie_new_offset) { - *(ie_new_offset) = WLAN_EID_SSID; - *(ie_new_offset+1) = bi->SSID_len; - memcpy(ie_new_offset+2, bi->SSID, bi->SSID_len); - ie_new_length = bi->ie_length - *(ie_offset+1) + bi->SSID_len; - - /* Copy the remaining IE apart from SSID IE from bi */ - memcpy( ie_new_offset+2 + bi->SSID_len, - ie_offset+2 + *(ie_offset+1), - bi->ie_length - 2 - *(ie_offset+1)); - wl_mrg_ie(wl, ie_new_offset , ie_new_length); - kfree(ie_new_offset); - } else { - wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); - } - } else { - wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); - } - + wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX - offsetof(struct wl_cfg80211_bss_info, frame_buf)); notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, @@ -6159,9 +6222,9 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 r return -EINVAL; } WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM" - "mgmt_type 0x%x, mgmt->frame_control=0x%x, frame_len %d\n", bi->SSID, + "mgmt_type %d frame_len %d\n", bi->SSID, notif_bss_info->rssi, notif_bss_info->channel, - mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,mgmt->frame_control, + mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type, notif_bss_info->frame_len)); signal = notif_bss_info->rssi * 100; @@ -6266,7 +6329,8 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, u32 reason = ntoh32(e->reason); u32 len = ntoh32(e->datalen); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) +//#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) +#if 0 bool isfree = false; u8 *mgmt_frame; u8 bsscfgidx = e->bsscfgidx; @@ -6284,6 +6348,7 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, struct station_info sinfo; #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !WL_CFG80211_STA_EVENT */ + WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason)); /* if link down, bsscfg is disabled. */ if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS && wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) { @@ -6292,7 +6357,8 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, return 0; } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) +//#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) +#if 0 body = kzalloc(len, GFP_KERNEL); WL_DBG(("Enter \n")); if (!len && (event == WLC_E_DEAUTH)) { @@ -6465,7 +6531,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, } else { if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { printk("wl_bss_connect_done succeeded with " MACDBG "\n", - STR_TO_MACD((u8*)(&e->addr))); + MAC2STRDBG((u8*)(&e->addr))); wl_bss_connect_done(wl, ndev, e, data, true); WL_DBG(("joined in BSS network \"%s\"\n", ((struct wlc_ssid *) @@ -6496,11 +6562,11 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, printk("link down if %s may call cfg80211_disconnected. " "event : %d, reason=%d from " MACDBG "\n", ndev->name, event, ntoh32(e->reason), - STR_TO_MACD((u8*)(&e->addr))); + MAC2STRDBG((u8*)(&e->addr))); if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) { WL_ERR(("BSSID of event is not the connected BSSID" "(ignore it) cur: " MACDBG " event: " MACDBG"\n", - STR_TO_MACD(curbssid), STR_TO_MACD((u8*)(&e->addr)))); + MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr)))); return 0; } wl_clr_drv_status(wl, CONNECTED, ndev); @@ -6696,7 +6762,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params, } } -static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 roam_done_flag) +static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) { struct cfg80211_bss *bss; struct wl_bss_info *bi; @@ -6706,6 +6772,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 ro s32 dtim_period; size_t ie_len; u8 *ie; + u8 *ssidie; u8 *curbssid; s32 err = 0; struct wiphy *wiphy; @@ -6736,7 +6803,14 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 ro err = -EIO; goto update_bss_info_out; } - err = wl_inform_single_bss(wl, bi, roam_done_flag); + + ie = ((u8 *)bi) + bi->ie_offset; + ie_len = bi->ie_length; + ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie, ie_len); + if (ssidie && ssidie[1] == bi->SSID_len && !ssidie[2] && bi->SSID[0]) + memcpy(ssidie + 2, bi->SSID, bi->SSID_len); + + err = wl_inform_single_bss(wl, bi); if (unlikely(err)) goto update_bss_info_out; @@ -6787,10 +6861,10 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, wl_get_assoc_ies(wl, ndev); wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - wl_update_bss_info(wl, ndev, 1); + wl_update_bss_info(wl, ndev); wl_update_pmklist(ndev, wl->pmk_list, err); printk("wl_bss_roaming_done succeeded to " MACDBG "\n", - STR_TO_MACD((u8*)(&e->addr))); + MAC2STRDBG((u8*)(&e->addr))); cfg80211_roamed(ndev, @@ -6822,6 +6896,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); if (!sec) { WL_ERR(("sec is NULL\n")); + return -ENODEV; } WL_DBG((" enter\n")); #ifdef ESCAN_RESULT_PATCH @@ -6854,7 +6929,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, wl_get_assoc_ies(wl, ndev); wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - wl_update_bss_info(wl, ndev, 0); + wl_update_bss_info(wl, ndev); wl_update_pmklist(ndev, wl->pmk_list, err); wl_set_drv_status(wl, CONNECTED, ndev); #ifdef ROAM_AP_ENV_DETECTION @@ -6902,6 +6977,28 @@ wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, return 0; } +#ifdef PNO_SUPPORT +static s32 +wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + WL_ERR((">>> PNO Event\n")); + +#ifndef WL_SCHED_SCAN + mutex_lock(&wl->usr_sync); + /* TODO: Use cfg80211_sched_scan_results(wiphy); */ + cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); + mutex_unlock(&wl->usr_sync); +#else + /* If cfg80211 scheduled scan is supported, report the pno results via sched + * scan results + */ + wl_notify_sched_scan_results(wl, ndev, e, data); +#endif /* WL_SCHED_SCAN */ + return 0; +} +#endif /* PNO_SUPPORT */ + static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) @@ -7173,7 +7270,9 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr", NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync); - wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); + err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); + if (err < 0) + WL_ERR(("WLC_GET_BSSID error %d\n", err)); memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid, &mgmt_frame, &mgmt_frame_len, @@ -7312,7 +7411,8 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#if 1 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); #else cfg80211_rx_mgmt(ndev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); @@ -7836,13 +7936,13 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); dev = ndev; } - if (fw_abort) { + if (fw_abort && !in_atomic()) { /* Our scan params only need space for 1 channel and 0 ssids */ params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); if (params == NULL) { WL_ERR(("scan params allocation failed \n")); err = -ENOMEM; - } else if (!in_atomic()) { + } else { /* Do a scan abort to stop the driver's scan engine */ err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); if (err < 0) { @@ -7970,7 +8070,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, s32 channel = CHSPEC_CHANNEL( wl_chspec_driver_to_host(bi->chanspec)); WL_DBG(("ACTION FRAME SCAN : Peer " MACDBG " found, channel : %d\n", - STR_TO_MACD(wl->afx_hdl->tx_dst_addr.octet), channel)); + MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet), channel)); wl_clr_p2p_status(wl, SCANNING); wl->afx_hdl->peer_chan = channel; complete(&wl->act_frm_scan); @@ -7991,6 +8091,10 @@ static s32 wl_escan_handler(struct wl_priv *wl, #else if (p2p_is_on(wl) && p2p_scan(wl)) { #endif +#ifdef WL_HOST_BAND_MGMT + s32 channel = 0; + s32 channel_band = 0; +#endif /* WL_HOST_BAND_MGMT */ /* p2p scan && allow only probe response */ if (bi->flags & WL_BSS_FLAGS_FROM_BEACON) goto exit; @@ -8000,6 +8104,20 @@ static s32 wl_escan_handler(struct wl_priv *wl, " response/beacon\n")); goto exit; } +#ifdef WL_HOST_BAND_MGMT + channel = CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec)); + channel_band = (channel > CH_MAX_2G_CHANNEL) ? + WLC_BAND_5G : WLC_BAND_2G; + + + if ((wl->curr_band == WLC_BAND_5G) && + (channel_band == WLC_BAND_2G)) { + /* Avoid sending the GO results in band conflict */ + if (wl_cfgp2p_retreive_p2pattrib(p2p_ie, + P2P_SEID_GROUP_ID) != NULL) + goto exit; + } +#endif /* WL_HOST_BAND_MGMT */ } for (i = 0; i < list->count; i++) { bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) @@ -8020,7 +8138,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d" " flags 0x%x, new: RSSI %d flags 0x%x\n", - bss->SSID, STR_TO_MACD(bi->BSSID.octet), i, + bss->SSID, MAC2STRDBG(bi->BSSID.octet), i, bss->RSSI, bss->flags, bi->RSSI, bi->flags)); if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == @@ -8030,7 +8148,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, */ WL_SCAN(("%s("MACDBG"), same onchan" ", RSSI: prev %d new %d\n", - bss->SSID, STR_TO_MACD(bi->BSSID.octet), + bss->SSID, MAC2STRDBG(bi->BSSID.octet), bss->RSSI, bi->RSSI)); bi->RSSI = MAX(bss->RSSI, bi->RSSI); } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) && @@ -8040,7 +8158,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, */ WL_SCAN(("%s("MACDBG"), prev onchan" ", RSSI: prev %d new %d\n", - bss->SSID, STR_TO_MACD(bi->BSSID.octet), + bss->SSID, MAC2STRDBG(bi->BSSID.octet), bss->RSSI, bi->RSSI)); bi->RSSI = bss->RSSI; bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL; @@ -8052,7 +8170,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, " is occured(bcast:%d->probresp%d)\n", bss->ie_length, bi->ie_length)); WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n", - bss->SSID, STR_TO_MACD(bi->BSSID.octet), + bss->SSID, MAC2STRDBG(bi->BSSID.octet), prev_len, bi_length)); if (list->buflen - prev_len + bi_length @@ -8249,6 +8367,8 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in WL_ERR(("error" " (%d)\n", err)); break; + } else { + wl_cfg80211_update_power_mode(iter->ndev); } } if (connected_cnt > 1) { @@ -8316,6 +8436,8 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in WL_ERR(("error" " (%d)\n", err)); break; + } else { + wl_cfg80211_update_power_mode(iter->ndev); } } } @@ -8476,7 +8598,11 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) return -ENODEV; } wl = wlcfg_drv_priv; - if (wl && !wl_get_drv_status(wl, READY, ndev)) { + if (unlikely(!wl)) { + WL_ERR(("wl is invaild\n")); + return -EINVAL; + } + if (!wl_get_drv_status(wl, READY, ndev)) { if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { #if !defined(WL_ENABLE_P2P_IF) @@ -8494,7 +8620,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) wl->p2p_net->dev_addr[0] |= 0x02; WL_ERR(("%s: p2p_dev_addr="MACDBG "\n", wl->p2p_net->name, - STR_TO_MACD(wl->p2p_net->dev_addr))); + MAC2STRDBG(wl->p2p_net->dev_addr))); } else { WL_ERR(("p2p_net not yet populated." " Couldn't update the MAC Address for p2p0 \n")); @@ -8504,8 +8630,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) wl->p2p_supported = true; } - } else - return -ENODEV; + } wl_set_drv_status(wl, READY, ndev); fail: return err; @@ -8866,7 +8991,8 @@ s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) s8 eventmask[WL_EVENTING_MASK_LEN]; s32 err = 0; - + if (!ndev) + return -ENODEV; /* Setup event_msgs */ bcm_mkiovar("event_msgs", NULL, 0, iovbuf, sizeof(iovbuf)); @@ -9106,6 +9232,8 @@ s32 wl_update_wiphybands(struct wl_priv *wl) wiphy->bands[index]->ht_cap.ht_supported = TRUE; wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + /* An HT shall support all EQM rates for one spatial stream */ + wiphy->bands[index]->ht_cap.mcs.rx_mask[0] = 0xff; } } @@ -9140,6 +9268,15 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) err = dhd_monitor_init(wl->pub); err = wl_invoke_iscan(wl); + +#ifdef WL_HOST_BAND_MGMT + /* By default the curr_band is initialized to BAND_AUTO */ + if (wl_cfg80211_set_band(ndev, WLC_BAND_AUTO) < 0) { + WL_ERR(("roam_band set failed\n")); + err = -1; + } +#endif /* WL_HOST_BAND_MGMT */ + wl_set_drv_status(wl, READY, ndev); return err; } @@ -9159,6 +9296,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) /* Check if cfg80211 interface is already down */ if (!wl_get_drv_status(wl, READY, ndev)) return err; /* it is even not ready */ + for_each_ndev(wl, iter, next) wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); @@ -9182,14 +9320,10 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) } wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; -#ifdef WL_ENABLE_P2P_IF #if !defined(CUSTOMER_HW4) - if ((p2p_net) && (p2p_net->flags & IFF_UP)) { - /* p2p0 interface is still UP. Bring it down */ - p2p_net->flags &= ~IFF_UP; - } + if (p2p_net) + dev_close(p2p_net); #endif -#endif /* WL_ENABLE_P2P_IF */ DNGL_FUNC(dhd_cfg80211_down, (wl)); wl_flush_eq(wl); wl_link_down(wl); @@ -9227,14 +9361,15 @@ s32 wl_cfg80211_up(void *para) mutex_lock(&wl->usr_sync); dhd = (dhd_pub_t *)(wl->pub); - if ((dhd->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) { - wl_cfg80211_attach_post(wl_to_prmry_ndev(wl)); + if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) { + err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl)); + if (unlikely(err)) + return err; } err = __wl_cfg80211_up(wl); - if (err) + if (unlikely(err)) WL_ERR(("__wl_cfg80211_up failed\n")); mutex_unlock(&wl->usr_sync); - return err; } @@ -9768,3 +9903,16 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s return err; } #endif /* WL11U */ + +static s32 +wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct net_device *dev, u64 cookie) +{ + /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION + * is passed with CMD_FRAME. This callback is supposed to cancel + * the OFFCHANNEL Wait. Since we are already taking care of that + * with the tx_mgmt logic, do nothing here. + */ + + return 0; +} diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index a712617..35a4f05 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfg80211.h 357867 2012-09-20 06:57:44Z $ + * $Id: wl_cfg80211.h 358186 2012-09-21 14:36:14Z $ */ #ifndef _wl_cfg80211_h_ @@ -156,9 +156,11 @@ do { \ #define WL_MIN_DWELL_TIME 100 #define WL_LONG_DWELL_TIME 1000 #define IFACE_MAX_CNT 2 -#define WL_SCAN_CONNECT_DWELL_TIME_MS 200 -#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20 -#define WL_AF_TX_MAX_RETRY 5 +#define WL_SCAN_CONNECT_DWELL_TIME_MS 200 +#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20 +#define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320 +#define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400 +#define WL_AF_TX_MAX_RETRY 5 #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ #define WL_CHANNEL_SYNC_RETRY 5 @@ -577,6 +579,13 @@ struct wl_priv { u8 iw_ie[IW_IES_MAX_BUF_LEN]; u32 iw_ie_len; #endif /* WL11U */ + bool sched_scan_running; /* scheduled scan req status */ +#ifdef WL_SCHED_SCAN + struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */ +#endif /* WL_SCHED_SCAN */ +#ifdef WL_HOST_BAND_MGMT + u8 curr_band; +#endif /* WL_HOST_BAND_MGMT */ }; @@ -839,4 +848,6 @@ extern s32 wl_cfg80211_if_is_group_owner(void); extern chanspec_t wl_ch_host_to_driver(u16 channel); extern s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); extern void wl_stop_wait_next_action_frame(struct wl_priv *wl, struct net_device *ndev); +extern s32 wl_cfg80211_set_band(struct net_device *ndev, int band); +extern int wl_cfg80211_update_power_mode(struct net_device *dev); #endif /* _wl_cfg80211_h_ */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index a0f113e..7a9cbea 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfgp2p.c 357864 2012-09-20 06:41:42Z $ + * $Id: wl_cfgp2p.c 358702 2012-09-25 06:48:56Z $ * */ #include <typedefs.h> @@ -409,7 +409,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); CFGP2P_DBG(("---wl p2p_ifadd "MACDBG" %s %u\n", - STR_TO_MACD(ifreq.addr.octet), + MAC2STRDBG(ifreq.addr.octet), (if_type == WL_P2P_IF_GO) ? "go" : "client", (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT)); @@ -438,7 +438,7 @@ wl_cfgp2p_ifdisable(struct wl_priv *wl, struct ether_addr *mac) struct net_device *netdev = wl_to_prmry_ndev(wl); CFGP2P_INFO(("------primary idx %d : wl p2p_ifdis "MACDBG"\n", - netdev->ifindex, STR_TO_MACD(mac->octet))); + netdev->ifindex, MAC2STRDBG(mac->octet))); ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (unlikely(ret < 0)) { @@ -459,7 +459,7 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac) struct net_device *netdev = wl_to_prmry_ndev(wl); CFGP2P_INFO(("------primary idx %d : wl p2p_ifdel "MACDBG"\n", - netdev->ifindex, STR_TO_MACD(mac->octet))); + netdev->ifindex, MAC2STRDBG(mac->octet))); ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (unlikely(ret < 0)) { @@ -488,7 +488,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); CFGP2P_INFO(("---wl p2p_ifchange "MACDBG" %s %u" - " chanspec 0x%04x\n", STR_TO_MACD(ifreq.addr.octet), + " chanspec 0x%04x\n", MAC2STRDBG(ifreq.addr.octet), (if_type == WL_P2P_IF_GO) ? "go" : "client", (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT, ifreq.chspec)); @@ -520,7 +520,7 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index) u8 getbuf[64]; struct net_device *dev = wl_to_prmry_ndev(wl); - CFGP2P_INFO(("---wl p2p_if "MACDBG"\n", STR_TO_MACD(mac->octet))); + CFGP2P_INFO(("---wl p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet))); ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf, sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY), NULL); @@ -1698,11 +1698,6 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, CFGP2P_INFO(("channel : %u , dwell time : %u\n", af_params->channel, af_params->dwell_time)); -#if defined(CONFIG_MACH_M3_JPN_DCM) - if (!wl) - return BCME_ERROR; -#endif - wl_clr_p2p_status(wl, ACTION_TX_COMPLETED); wl_clr_p2p_status(wl, ACTION_TX_NOACK); #define MAX_WAIT_TIME 2000 @@ -2047,10 +2042,16 @@ wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int } if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) { +#ifdef SUPPORT_PM2_ONLY + if (legacy_ps == PM_MAX) + legacy_ps = PM_FAST; +#endif ret = wldev_ioctl(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true); if (unlikely(ret)) { CFGP2P_ERR(("error (%d)\n", ret)); + } else { + wl_cfg80211_update_power_mode(ndev); } } else @@ -2301,21 +2302,22 @@ static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd static int wl_cfgp2p_if_open(struct net_device *net) { + extern struct wl_priv *wlcfg_drv_priv; struct wireless_dev *wdev = net->ieee80211_ptr; - - if (!wdev) + struct wl_priv *wl = NULL; + wl = wlcfg_drv_priv; + if (!wdev || !wl || !wl->p2p) return -EINVAL; - + WL_TRACE(("Enter\n")); /* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now, * do it here. This will make sure that in concurrent mode, supplicant * is not dependent on a particular order of interface initialization. * i.e you may give wpa_supp -iwlan0 -N -ip2p0 or wpa_supp -ip2p0 -N * -iwlan0. */ - wl_cfg80211_do_driver_init(net); - wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)); + wl_cfg80211_do_driver_init(net); return 0; } @@ -2346,10 +2348,5 @@ static int wl_cfgp2p_if_stop(struct net_device *net) wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes) & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO))); -#if defined(CUSTOMER_HW4) - if (net->flags & IFF_UP) - net->flags &= ~IFF_UP; -#endif - return 0; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 808e576..31b8dab 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfgp2p.h 354184 2012-08-30 08:08:08Z $ + * $Id: wl_cfgp2p.h 358702 2012-09-25 06:48:56Z $ */ #ifndef _wl_cfgp2p_h_ #define _wl_cfgp2p_h_ @@ -46,7 +46,7 @@ typedef enum { /* vendor ies max buffer length for probe response or beacon */ #define VNDR_IES_MAX_BUF_LEN 1400 /* normal vendor ies buffer length */ -#define VNDR_IES_BUF_LEN 512 +#define VNDR_IES_BUF_LEN 512 /* Structure to hold all saved P2P and WPS IEs for a BSSCFG */ struct p2p_saved_ie { @@ -299,6 +299,9 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl); #define SOCIAL_CHAN_1 1 #define SOCIAL_CHAN_2 6 #define SOCIAL_CHAN_3 11 +#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \ + (channel == SOCIAL_CHAN_2) || \ + (channel == SOCIAL_CHAN_3)) #define SOCIAL_CHAN_CNT 3 #define AF_PEER_SEARCH_CNT 2 #define WL_P2P_WILDCARD_SSID "DIRECT-" diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c index ef51480..8e0ed4d 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/bcmdhd/wldev_common.c @@ -327,7 +327,7 @@ int wldev_set_band( int error = -1; if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { - error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), 1); + error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true); if (!error) dhd_bus_band_set(dev, band); } @@ -353,7 +353,7 @@ int wldev_set_country( if ((error < 0) || (strncmp(country_code, smbuf, WLC_CNTRY_BUF_SZ) != 0)) { bzero(&scbval, sizeof(scb_val_t)); - error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), 1); + error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); if (error < 0) { WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n", __FUNCTION__, error)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 592b0cf..2aed7a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -878,6 +878,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || (priv->bt_full_concurrent != full_concurrent)) { priv->bt_full_concurrent = full_concurrent; + priv->last_bt_traffic_load = priv->bt_traffic_load; /* Update uCode's rate table. */ tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 0bd722c..5c9999d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -477,7 +477,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, sizeof(struct iwl_keyinfo)); priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; - priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; + priv->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index e5dfdc3..d2358cf 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -267,7 +267,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, else last_seq = priv->rx_seq[tid]; - if (last_seq >= new_node->start_win) + if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && + last_seq >= new_node->start_win) new_node->start_win = last_seq + 1; new_node->win_size = win_size; @@ -612,5 +613,5 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); - memset(priv->rx_seq, 0, sizeof(priv->rx_seq)); + mwifiex_reset_11n_rx_seq_num(priv); } diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index f3ca8c8..7576c2a 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -37,6 +37,13 @@ #define ADDBA_RSP_STATUS_ACCEPT 0 +#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff + +static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) +{ + memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq)); +} + int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *, u16 seqNum, u16 tid, u8 *ta, diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index d425dbd..3b1217f 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -122,7 +122,6 @@ static int mwifiex_sdio_suspend(struct device *dev) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; - int hs_actived = 0; int i; int ret = 0; @@ -149,12 +148,14 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; /* Enable the Host Sleep */ - hs_actived = mwifiex_enable_hs(adapter); - if (hs_actived) { - pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (!mwifiex_enable_hs(adapter)) { + dev_err(adapter->dev, "cmd: failed to suspend\n"); + return -EFAULT; } + dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + /* Indicate device suspended */ adapter->is_suspended = true; diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 91634da..2cdb41a 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -406,6 +406,8 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; + mwifiex_reset_11n_rx_seq_num(priv); + atomic_set(&priv->wmm.tx_pkts_queued, 0); atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index a8f3bc7..f1fa763 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -41,11 +41,12 @@ MODULE_FIRMWARE("isl3887usb"); * whenever you add a new device. */ -static struct usb_device_id p54u_table[] __devinitdata = { +static struct usb_device_id p54u_table[] = { /* Version 1 devices (pci chip + net2280) */ {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ + {USB_DEVICE(0x0675, 0x0530)}, /* DrayTek Vigor 530 */ {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ @@ -81,6 +82,8 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ + {USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */ + {USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ @@ -100,6 +103,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ + /* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */ {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ {USB_DEVICE(0x1740, 0x1000)}, /* Senao NUB-350 */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 937f9e8..1493171 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1618,6 +1618,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1631,6 +1632,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_BIT8, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + + /* * Initialize hw specifications. */ retval = rt2400pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68..7564ae9 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,6 +670,7 @@ #define GPIOCSR_BIT5 FIELD32(0x00000020) #define GPIOCSR_BIT6 FIELD32(0x00000040) #define GPIOCSR_BIT7 FIELD32(0x00000080) +#define GPIOCSR_BIT8 FIELD32(0x00000100) /* * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d27d7b8..cdd480f 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1936,6 +1936,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1949,6 +1950,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_DIR0, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + + /* * Initialize hw specifications. */ retval = rt2500pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 15237c2..f124a1b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) u16 reg; rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - return rt2x00_get_field32(reg, MAC_CSR19_BIT7); + return rt2x00_get_field16(reg, MAC_CSR19_BIT7); } #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u16 reg; /* * Allocate eeprom data. @@ -1781,6 +1782,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); + rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + + /* * Initialize hw specifications. */ retval = rt2500usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306..196bd51 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,14 +189,15 @@ * MAC_CSR19: GPIO control register. */ #define MAC_CSR19 0x0426 -#define MAC_CSR19_BIT0 FIELD32(0x0001) -#define MAC_CSR19_BIT1 FIELD32(0x0002) -#define MAC_CSR19_BIT2 FIELD32(0x0004) -#define MAC_CSR19_BIT3 FIELD32(0x0008) -#define MAC_CSR19_BIT4 FIELD32(0x0010) -#define MAC_CSR19_BIT5 FIELD32(0x0020) -#define MAC_CSR19_BIT6 FIELD32(0x0040) -#define MAC_CSR19_BIT7 FIELD32(0x0080) +#define MAC_CSR19_BIT0 FIELD16(0x0001) +#define MAC_CSR19_BIT1 FIELD16(0x0002) +#define MAC_CSR19_BIT2 FIELD16(0x0004) +#define MAC_CSR19_BIT3 FIELD16(0x0008) +#define MAC_CSR19_BIT4 FIELD16(0x0010) +#define MAC_CSR19_BIT5 FIELD16(0x0020) +#define MAC_CSR19_BIT6 FIELD16(0x0040) +#define MAC_CSR19_BIT7 FIELD16(0x0080) +#define MAC_CSR19_BIT8 FIELD16(0x0100) /* * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index e6e174c..d44ce30 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1935,7 +1935,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) /* * Check if temperature compensation is supported. */ - if (tssi_bounds[4] == 0xff) + if (tssi_bounds[4] == 0xff || step == 0xff) return 0; /* diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index dab7dc1..e947d3a 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -941,6 +941,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -954,6 +955,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + + /* * Initialize hw specifications. */ retval = rt2800_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 0781fb0..9366ef0 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -600,6 +600,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -613,6 +614,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + + /* * Initialize hw specifications. */ retval = rt2800_probe_hw_mode(rt2x00dev); @@ -829,6 +838,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0411, 0x015d) }, { USB_DEVICE(0x0411, 0x016f) }, { USB_DEVICE(0x0411, 0x01a2) }, + { USB_DEVICE(0x0411, 0x01ee) }, /* Corega */ { USB_DEVICE(0x07aa, 0x002f) }, { USB_DEVICE(0x07aa, 0x003c) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 54f0b13..99fa416 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -426,8 +426,8 @@ void rt2x00usb_kick_queue(struct data_queue *queue) case QID_RX: if (!rt2x00queue_full(queue)) rt2x00queue_for_each_entry(queue, - Q_INDEX_DONE, Q_INDEX, + Q_INDEX_DONE, NULL, rt2x00usb_kick_rx_entry); break; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 9d35ec1..17de24e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2254,8 +2254,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) { - struct ieee80211_conf conf = { .flags = 0 }; - struct rt2x00lib_conf libconf = { .conf = &conf }; + struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf }; rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } @@ -2841,6 +2840,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Disable power saving. @@ -2859,6 +2859,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + + /* * Initialize hw specifications. */ retval = rt61pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db..8f3da5a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) /* * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ad20953..1a06231 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -2190,6 +2191,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) return retval; /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); + rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + + /* * Initialize hw specifications. */ retval = rt73usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470..df1cc11 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) +#define MAC_CSR13_BIT14 FIELD32(0x00004000) +#define MAC_CSR13_BIT15 FIELD32(0x00008000) /* * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 1e0be14..bf01d21 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -43,7 +43,7 @@ MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>"); MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); -static struct usb_device_id rtl8187_table[] __devinitdata = { +static struct usb_device_id rtl8187_table[] = { /* Asus */ {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, /* Belkin */ diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c index 2e0de2f..c2d5b49 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c @@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, radio_on = true; } else if (radio_on) { radio_on = false; - cancel_delayed_work_sync(&priv->led_on); + cancel_delayed_work(&priv->led_on); ieee80211_queue_delayed_work(hw, &priv->led_off, 0); } } else if (radio_on) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 942f7a3..354f9b1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -295,6 +295,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { /*=== Customer ID ===*/ /****** 8188CU ********/ {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ + {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index e4272b9..dbcf5a9 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -542,8 +542,8 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) WARN_ON(skb_queue_empty(&rx_queue)); while (!skb_queue_empty(&rx_queue)) { _skb = skb_dequeue(&rx_queue); - _rtl_usb_rx_process_agg(hw, skb); - ieee80211_rx_irqsafe(hw, skb); + _rtl_usb_rx_process_agg(hw, _skb); + ieee80211_rx_irqsafe(hw, _skb); } } diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c index 85a7101..4cf5c2e 100644 --- a/drivers/net/wireless/wl1251/sdio.c +++ b/drivers/net/wireless/wl1251/sdio.c @@ -259,6 +259,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, } if (wl->irq) { + irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); if (ret < 0) { wl1251_error("request_irq() failed: %d", ret); @@ -266,7 +267,6 @@ static int wl1251_sdio_probe(struct sdio_func *func, } irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - disable_irq(wl->irq); wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c index af6448c..49f3651 100644 --- a/drivers/net/wireless/wl1251/spi.c +++ b/drivers/net/wireless/wl1251/spi.c @@ -280,6 +280,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi) wl->use_eeprom = pdata->use_eeprom; + irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl); if (ret < 0) { wl1251_error("request_irq() failed: %d", ret); @@ -288,8 +289,6 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi) irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - disable_irq(wl->irq); - ret = wl1251_init_ieee80211(wl); if (ret) goto out_irq; diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 161f207..810a472 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -152,6 +152,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); /* Notify xenvif that ring now has space to send an skb to the frontend */ void xenvif_notify_tx_completion(struct xenvif *vif); +/* Prevent the device from generating any further traffic. */ +void xenvif_carrier_off(struct xenvif *vif); + /* Returns number of ring slots required to send an skb to the frontend */ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 1825629..5925e0b 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -342,17 +342,22 @@ err: return err; } -void xenvif_disconnect(struct xenvif *vif) +void xenvif_carrier_off(struct xenvif *vif) { struct net_device *dev = vif->dev; - if (netif_carrier_ok(dev)) { - rtnl_lock(); - netif_carrier_off(dev); /* discard queued packets */ - if (netif_running(dev)) - xenvif_down(vif); - rtnl_unlock(); - xenvif_put(vif); - } + + rtnl_lock(); + netif_carrier_off(dev); /* discard queued packets */ + if (netif_running(dev)) + xenvif_down(vif); + rtnl_unlock(); + xenvif_put(vif); +} + +void xenvif_disconnect(struct xenvif *vif) +{ + if (netif_carrier_ok(vif->dev)) + xenvif_carrier_off(vif); atomic_dec(&vif->refcnt); wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 0e4851b..9068d32 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -143,7 +143,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif) atomic_dec(&netbk->netfront_count); } -static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); +static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, + u8 status); static void make_tx_response(struct xenvif *vif, struct xen_netif_tx_request *txp, s8 st); @@ -838,7 +839,7 @@ static void netbk_tx_err(struct xenvif *vif, do { make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - if (cons >= end) + if (cons == end) break; txp = RING_GET_REQUEST(&vif->tx, cons++); } while (1); @@ -847,6 +848,13 @@ static void netbk_tx_err(struct xenvif *vif, xenvif_put(vif); } +static void netbk_fatal_tx_err(struct xenvif *vif) +{ + netdev_err(vif->dev, "fatal error; disabling device\n"); + xenvif_carrier_off(vif); + xenvif_put(vif); +} + static int netbk_count_requests(struct xenvif *vif, struct xen_netif_tx_request *first, struct xen_netif_tx_request *txp, @@ -860,19 +868,22 @@ static int netbk_count_requests(struct xenvif *vif, do { if (frags >= work_to_do) { - netdev_dbg(vif->dev, "Need more frags\n"); + netdev_err(vif->dev, "Need more frags\n"); + netbk_fatal_tx_err(vif); return -frags; } if (unlikely(frags >= MAX_SKB_FRAGS)) { - netdev_dbg(vif->dev, "Too many frags\n"); + netdev_err(vif->dev, "Too many frags\n"); + netbk_fatal_tx_err(vif); return -frags; } memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), sizeof(*txp)); if (txp->size > first->size) { - netdev_dbg(vif->dev, "Frags galore\n"); + netdev_err(vif->dev, "Frag is bigger than frame.\n"); + netbk_fatal_tx_err(vif); return -frags; } @@ -880,8 +891,9 @@ static int netbk_count_requests(struct xenvif *vif, frags++; if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { - netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", + netdev_err(vif->dev, "txp->offset: %x, size: %u\n", txp->offset, txp->size); + netbk_fatal_tx_err(vif); return -frags; } } while ((txp++)->flags & XEN_NETTXF_more_data); @@ -925,7 +937,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, pending_idx = netbk->pending_ring[index]; page = xen_netbk_alloc_page(netbk, skb, pending_idx); if (!page) - return NULL; + goto err; netbk->mmap_pages[pending_idx] = page; @@ -949,6 +961,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, } return gop; +err: + /* Unwind, freeing all pages and sending error responses. */ + while (i-- > start) { + xen_netbk_idx_release(netbk, (unsigned long)shinfo->frags[i].page, + XEN_NETIF_RSP_ERROR); + } + /* The head too, if necessary. */ + if (start) + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); + + return NULL; } static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, @@ -957,30 +980,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, { struct gnttab_copy *gop = *gopp; int pending_idx = *((u16 *)skb->data); - struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; - struct xenvif *vif = pending_tx_info[pending_idx].vif; - struct xen_netif_tx_request *txp; struct skb_shared_info *shinfo = skb_shinfo(skb); int nr_frags = shinfo->nr_frags; int i, err, start; /* Check status of header. */ err = gop->status; - if (unlikely(err)) { - pending_ring_idx_t index; - index = pending_index(netbk->pending_prod++); - txp = &pending_tx_info[pending_idx].req; - make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - netbk->pending_ring[index] = pending_idx; - xenvif_put(vif); - } + if (unlikely(err)) + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); /* Skip first skb fragment if it is on same page as header fragment. */ - start = ((unsigned long)shinfo->frags[0].page == pending_idx); + start = ((unsigned long)shinfo->frags[i].page == pending_idx); for (i = start; i < nr_frags; i++) { int j, newerr; - pending_ring_idx_t index; pending_idx = (unsigned long)shinfo->frags[i].page; @@ -989,16 +1002,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, if (likely(!newerr)) { /* Had a previous error? Invalidate this fragment. */ if (unlikely(err)) - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); continue; } /* Error on this fragment: respond to client with an error. */ - txp = &netbk->pending_tx_info[pending_idx].req; - make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - index = pending_index(netbk->pending_prod++); - netbk->pending_ring[index] = pending_idx; - xenvif_put(vif); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); /* Not the first error? Preceding frags already invalidated. */ if (err) @@ -1006,10 +1015,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, /* First error: invalidate header and preceding fragments. */ pending_idx = *((u16 *)skb->data); - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); for (j = start; j < i; j++) { pending_idx = (unsigned long)shinfo->frags[i].page; - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } /* Remember the error: invalidate all subsequent fragments. */ @@ -1044,7 +1053,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) /* Take an extra reference to offset xen_netbk_idx_release */ get_page(netbk->mmap_pages[pending_idx]); - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } } @@ -1057,7 +1066,8 @@ static int xen_netbk_get_extras(struct xenvif *vif, do { if (unlikely(work_to_do-- <= 0)) { - netdev_dbg(vif->dev, "Missing extra info\n"); + netdev_err(vif->dev, "Missing extra info\n"); + netbk_fatal_tx_err(vif); return -EBADR; } @@ -1066,8 +1076,9 @@ static int xen_netbk_get_extras(struct xenvif *vif, if (unlikely(!extra.type || extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { vif->tx.req_cons = ++cons; - netdev_dbg(vif->dev, + netdev_err(vif->dev, "Invalid extra type: %d\n", extra.type); + netbk_fatal_tx_err(vif); return -EINVAL; } @@ -1083,13 +1094,15 @@ static int netbk_set_skb_gso(struct xenvif *vif, struct xen_netif_extra_info *gso) { if (!gso->u.gso.size) { - netdev_dbg(vif->dev, "GSO size must not be zero.\n"); + netdev_err(vif->dev, "GSO size must not be zero.\n"); + netbk_fatal_tx_err(vif); return -EINVAL; } /* Currently only TCPv4 S.O. is supported. */ if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { - netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); + netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); + netbk_fatal_tx_err(vif); return -EINVAL; } @@ -1226,9 +1239,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) /* Get a netif from the list with work to do. */ vif = poll_net_schedule_list(netbk); + /* This can sometimes happen because the test of + * list_empty(net_schedule_list) at the top of the + * loop is unlocked. Just go back and have another + * look. + */ if (!vif) continue; + if (vif->tx.sring->req_prod - vif->tx.req_cons > + XEN_NETIF_TX_RING_SIZE) { + netdev_err(vif->dev, + "Impossible number of requests. " + "req_prod %d, req_cons %d, size %ld\n", + vif->tx.sring->req_prod, vif->tx.req_cons, + XEN_NETIF_TX_RING_SIZE); + netbk_fatal_tx_err(vif); + continue; + } + RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); if (!work_to_do) { xenvif_put(vif); @@ -1256,17 +1285,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) work_to_do = xen_netbk_get_extras(vif, extras, work_to_do); idx = vif->tx.req_cons; - if (unlikely(work_to_do < 0)) { - netbk_tx_err(vif, &txreq, idx); + if (unlikely(work_to_do < 0)) continue; - } } ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); - if (unlikely(ret < 0)) { - netbk_tx_err(vif, &txreq, idx - ret); + if (unlikely(ret < 0)) continue; - } + idx += ret; if (unlikely(txreq.size < ETH_HLEN)) { @@ -1278,11 +1304,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) /* No crossing a page as the payload mustn't fragment. */ if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { - netdev_dbg(vif->dev, + netdev_err(vif->dev, "txreq.offset: %x, size: %u, end: %lu\n", txreq.offset, txreq.size, (txreq.offset&~PAGE_MASK) + txreq.size); - netbk_tx_err(vif, &txreq, idx); + netbk_fatal_tx_err(vif); continue; } @@ -1310,8 +1336,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; if (netbk_set_skb_gso(vif, skb, gso)) { + /* Failure in netbk_set_skb_gso is fatal. */ kfree_skb(skb); - netbk_tx_err(vif, &txreq, idx); continue; } } @@ -1412,7 +1438,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) txp->size -= data_len; } else { /* Schedule a response immediately. */ - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } if (txp->flags & XEN_NETTXF_csum_blank) @@ -1467,7 +1493,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk) } -static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) +static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, + u8 status) { struct xenvif *vif; struct pending_tx_info *pending_tx_info; @@ -1481,7 +1508,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) vif = pending_tx_info->vif; - make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); + make_tx_response(vif, &pending_tx_info->req, status); index = pending_index(netbk->pending_prod++); netbk->pending_ring[index] = pending_idx; |