diff options
Diffstat (limited to 'drivers/net')
166 files changed, 3614 insertions, 1072 deletions
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 209fbb7..776a478 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_ATL2) += atlx/ obj-$(CONFIG_ATL1E) += atl1e/ obj-$(CONFIG_ATL1C) += atl1c/ obj-$(CONFIG_GIANFAR) += gianfar_driver.o +obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o obj-$(CONFIG_TEHUTI) += tehuti.o obj-$(CONFIG_ENIC) += enic/ obj-$(CONFIG_JME) += jme.o diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 9eb9b98..de51e84 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -30,9 +30,12 @@ #include <linux/etherdevice.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/net_tstamp.h> #include <linux/phy.h> #include <linux/platform_device.h> +#include <linux/ptp_classify.h> #include <linux/slab.h> +#include <mach/ixp46x_ts.h> #include <mach/npe.h> #include <mach/qmgr.h> @@ -67,6 +70,10 @@ #define RXFREE_QUEUE(port_id) (NPE_ID(port_id) + 26) #define TXDONE_QUEUE 31 +#define PTP_SLAVE_MODE 1 +#define PTP_MASTER_MODE 2 +#define PORT2CHANNEL(p) NPE_ID(p->id) + /* TX Control Registers */ #define TX_CNTRL0_TX_EN 0x01 #define TX_CNTRL0_HALFDUPLEX 0x02 @@ -171,6 +178,8 @@ struct port { int id; /* logical port ID */ int speed, duplex; u8 firmware[4]; + int hwts_tx_en; + int hwts_rx_en; }; /* NPE message structure */ @@ -246,6 +255,172 @@ static int ports_open; static struct port *npe_port_tab[MAX_NPES]; static struct dma_pool *dma_pool; +static struct sock_filter ptp_filter[] = { + PTP_FILTER +}; + +static int ixp_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid) +{ + u8 *data = skb->data; + unsigned int offset; + u16 *hi, *id; + u32 lo; + + if (sk_run_filter(skb, ptp_filter) != PTP_CLASS_V1_IPV4) + return 0; + + offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN; + + if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid)) + return 0; + + hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID); + id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID); + + memcpy(&lo, &hi[1], sizeof(lo)); + + return (uid_hi == ntohs(*hi) && + uid_lo == ntohl(lo) && + seqid == ntohs(*id)); +} + +static void ixp_rx_timestamp(struct port *port, struct sk_buff *skb) +{ + struct skb_shared_hwtstamps *shhwtstamps; + struct ixp46x_ts_regs *regs; + u64 ns; + u32 ch, hi, lo, val; + u16 uid, seq; + + if (!port->hwts_rx_en) + return; + + ch = PORT2CHANNEL(port); + + regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT; + + val = __raw_readl(®s->channel[ch].ch_event); + + if (!(val & RX_SNAPSHOT_LOCKED)) + return; + + lo = __raw_readl(®s->channel[ch].src_uuid_lo); + hi = __raw_readl(®s->channel[ch].src_uuid_hi); + + uid = hi & 0xffff; + seq = (hi >> 16) & 0xffff; + + if (!ixp_ptp_match(skb, htons(uid), htonl(lo), htons(seq))) + goto out; + + lo = __raw_readl(®s->channel[ch].rx_snap_lo); + hi = __raw_readl(®s->channel[ch].rx_snap_hi); + ns = ((u64) hi) << 32; + ns |= lo; + ns <<= TICKS_NS_SHIFT; + + shhwtstamps = skb_hwtstamps(skb); + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + shhwtstamps->hwtstamp = ns_to_ktime(ns); +out: + __raw_writel(RX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); +} + +static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb) +{ + struct skb_shared_hwtstamps shhwtstamps; + struct ixp46x_ts_regs *regs; + struct skb_shared_info *shtx; + u64 ns; + u32 ch, cnt, hi, lo, val; + + shtx = skb_shinfo(skb); + if (unlikely(shtx->tx_flags & SKBTX_HW_TSTAMP && port->hwts_tx_en)) + shtx->tx_flags |= SKBTX_IN_PROGRESS; + else + return; + + ch = PORT2CHANNEL(port); + + regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT; + + /* + * This really stinks, but we have to poll for the Tx time stamp. + * Usually, the time stamp is ready after 4 to 6 microseconds. + */ + for (cnt = 0; cnt < 100; cnt++) { + val = __raw_readl(®s->channel[ch].ch_event); + if (val & TX_SNAPSHOT_LOCKED) + break; + udelay(1); + } + if (!(val & TX_SNAPSHOT_LOCKED)) { + shtx->tx_flags &= ~SKBTX_IN_PROGRESS; + return; + } + + lo = __raw_readl(®s->channel[ch].tx_snap_lo); + hi = __raw_readl(®s->channel[ch].tx_snap_hi); + ns = ((u64) hi) << 32; + ns |= lo; + ns <<= TICKS_NS_SHIFT; + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + shhwtstamps.hwtstamp = ns_to_ktime(ns); + skb_tstamp_tx(skb, &shhwtstamps); + + __raw_writel(TX_SNAPSHOT_LOCKED, ®s->channel[ch].ch_event); +} + +static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct hwtstamp_config cfg; + struct ixp46x_ts_regs *regs; + struct port *port = netdev_priv(netdev); + int ch; + + if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) + return -EFAULT; + + if (cfg.flags) /* reserved for future extensions */ + return -EINVAL; + + ch = PORT2CHANNEL(port); + regs = (struct ixp46x_ts_regs __iomem *) IXP4XX_TIMESYNC_BASE_VIRT; + + switch (cfg.tx_type) { + case HWTSTAMP_TX_OFF: + port->hwts_tx_en = 0; + break; + case HWTSTAMP_TX_ON: + port->hwts_tx_en = 1; + break; + default: + return -ERANGE; + } + + switch (cfg.rx_filter) { + case HWTSTAMP_FILTER_NONE: + port->hwts_rx_en = 0; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + port->hwts_rx_en = PTP_SLAVE_MODE; + __raw_writel(0, ®s->channel[ch].ch_control); + break; + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + port->hwts_rx_en = PTP_MASTER_MODE; + __raw_writel(MASTER_MODE, ®s->channel[ch].ch_control); + break; + default: + return -ERANGE; + } + + /* Clear out any old time stamps. */ + __raw_writel(TX_SNAPSHOT_LOCKED | RX_SNAPSHOT_LOCKED, + ®s->channel[ch].ch_event); + + return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; +} static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location, int write, u16 cmd) @@ -573,6 +748,7 @@ static int eth_poll(struct napi_struct *napi, int budget) debug_pkt(dev, "eth_poll", skb->data, skb->len); + ixp_rx_timestamp(port, skb); skb->protocol = eth_type_trans(skb, dev); dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; @@ -679,14 +855,12 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); - dev_kfree_skb(skb); #endif phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); if (dma_mapping_error(&dev->dev, phys)) { -#ifdef __ARMEB__ dev_kfree_skb(skb); -#else +#ifndef __ARMEB__ kfree(mem); #endif dev->stats.tx_dropped++; @@ -728,6 +902,13 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) #if DEBUG_TX printk(KERN_DEBUG "%s: eth_xmit end\n", dev->name); #endif + + ixp_tx_timestamp(port, skb); + skb_tx_timestamp(skb); + +#ifndef __ARMEB__ + dev_kfree_skb(skb); +#endif return NETDEV_TX_OK; } @@ -783,6 +964,9 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd) if (!netif_running(dev)) return -EINVAL; + if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP) + return hwtstamp_ioctl(dev, req, cmd); + return phy_mii_ioctl(port->phydev, req, cmd); } @@ -1171,6 +1355,11 @@ static int __devinit eth_init_one(struct platform_device *pdev) char phy_id[MII_BUS_ID_SIZE + 3]; int err; + if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) { + pr_err("ixp4xx_eth: bad ptp filter\n"); + return -EINVAL; + } + if (!(dev = alloc_etherdev(sizeof(struct port)))) return -ENOMEM; diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 2463b1c..81654ae 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1703,7 +1703,8 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size) { struct be_mcc_wrb *wrb; struct be_cmd_req_rss_config *req; - u32 myhash[10]; + u32 myhash[10] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF, + 0x0123, 0x4567, 0x89AB, 0xCDEF, 0x01EF}; int status; if (mutex_lock_interruptible(&adapter->mbox_lock)) diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index d5bd35b..2890443 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -2675,7 +2675,7 @@ alloc_mem_err: * Min size diferent for TPA and non-TPA queues */ if (ring_size < (fp->disable_tpa ? - MIN_RX_SIZE_TPA : MIN_RX_SIZE_NONTPA)) { + MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) { /* release memory allocated for this queue */ bnx2x_free_fp_mem_at(bp, index); return -ENOMEM; diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index a97d9be..4b70311 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -2222,12 +2222,13 @@ static void bnx2x_pmf_update(struct bnx2x *bp) u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param) { int mb_idx = BP_FW_MB_IDX(bp); - u32 seq = ++bp->fw_seq; + u32 seq; u32 rc = 0; u32 cnt = 1; u8 delay = CHIP_REV_IS_SLOW(bp) ? 100 : 10; mutex_lock(&bp->fw_mb_mutex); + seq = ++bp->fw_seq; SHMEM_WR(bp, func_mb[mb_idx].drv_mb_param, param); SHMEM_WR(bp, func_mb[mb_idx].drv_mb_header, (command | seq)); diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 8f2d2e7..2df9276 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -163,8 +163,6 @@ static int tlb_initialize(struct bonding *bond) struct tlb_client_info *new_hashtbl; int i; - spin_lock_init(&(bond_info->tx_hashtbl_lock)); - new_hashtbl = kzalloc(size, GFP_KERNEL); if (!new_hashtbl) { pr_err("%s: Error: Failed to allocate TLB hash table\n", @@ -747,8 +745,6 @@ static int rlb_initialize(struct bonding *bond) int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info); int i; - spin_lock_init(&(bond_info->rx_hashtbl_lock)); - new_hashtbl = kmalloc(size, GFP_KERNEL); if (!new_hashtbl) { pr_err("%s: Error: Failed to allocate RLB hash table\n", diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6dc4284..6141667 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -852,7 +852,7 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) static void bond_resend_igmp_join_requests_delayed(struct work_struct *work) { struct bonding *bond = container_of(work, struct bonding, - mcast_work.work); + mcast_work.work); bond_resend_igmp_join_requests(bond); } @@ -1172,10 +1172,12 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) } /* resend IGMP joins since active slave has changed or - * all were sent on curr_active_slave */ - if (((USES_PRIMARY(bond->params.mode) && new_active) || - bond->params.mode == BOND_MODE_ROUNDROBIN) && - netif_running(bond->dev)) { + * all were sent on curr_active_slave. + * resend only if bond is brought up with the affected + * bonding modes and the retransmission is enabled */ + if (netif_running(bond->dev) && (bond->params.resend_igmp > 0) && + ((USES_PRIMARY(bond->params.mode) && new_active) || + bond->params.mode == BOND_MODE_ROUNDROBIN)) { bond->igmp_retrans = bond->params.resend_igmp; queue_delayed_work(bond->wq, &bond->mcast_work, 0); } @@ -1542,12 +1544,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_dev->name, slave_dev->name); } - /* bond must be initialized by bond_open() before enslaving */ - if (!(bond_dev->flags & IFF_UP)) { - pr_warning("%s: master_dev is not up in bond_enslave\n", - bond_dev->name); - } - /* already enslaved */ if (slave_dev->flags & IFF_SLAVE) { pr_debug("Error, Device was already enslaved\n"); @@ -4834,9 +4830,19 @@ static int bond_init(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id); + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); pr_debug("Begin bond_init for %s\n", bond_dev->name); + /* + * Initialize locks that may be required during + * en/deslave operations. All of the bond_open work + * (of which this is part) should really be moved to + * a phase prior to dev_open + */ + spin_lock_init(&(bond_info->tx_hashtbl_lock)); + spin_lock_init(&(bond_info->rx_hashtbl_lock)); + bond->wq = create_singlethread_workqueue(bond_dev->name); if (!bond->wq) return -ENOMEM; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 4059bfc..88fcb25 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -227,12 +227,6 @@ static ssize_t bonding_store_slaves(struct device *d, struct net_device *dev; struct bonding *bond = to_bond(d); - /* Quick sanity check -- is the bond interface up? */ - if (!(bond->dev->flags & IFF_UP)) { - pr_warning("%s: doing slave updates when interface is down.\n", - bond->dev->name); - } - if (!rtnl_trylock()) return restart_syscall(); @@ -1539,8 +1533,8 @@ static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR, * Show and set the number of IGMP membership reports to send on link failure */ static ssize_t bonding_show_resend_igmp(struct device *d, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct bonding *bond = to_bond(d); @@ -1548,8 +1542,8 @@ static ssize_t bonding_show_resend_igmp(struct device *d, } static ssize_t bonding_store_resend_igmp(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { int new_value, ret = count; struct bonding *bond = to_bond(d); @@ -1561,7 +1555,7 @@ static ssize_t bonding_store_resend_igmp(struct device *d, goto out; } - if (new_value < 0) { + if (new_value < 0 || new_value > 255) { pr_err("%s: Invalid resend_igmp value %d not in range 0-255; rejected.\n", bond->dev->name, new_value); ret = -EINVAL; diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 587fba4..f1942ca 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -15,7 +15,6 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/platform_device.h> -#include <linux/mfd/core.h> #include <linux/netdevice.h> #include <linux/can.h> @@ -1644,7 +1643,7 @@ static int __devinit ican3_probe(struct platform_device *pdev) struct device *dev; int ret; - pdata = mfd_get_data(pdev); + pdata = pdev->dev.platform_data; if (!pdata) return -ENXIO; diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c index c11bb4d..c0e1b1e 100644 --- a/drivers/net/can/softing/softing_cs.c +++ b/drivers/net/can/softing/softing_cs.c @@ -315,7 +315,7 @@ pcmcia_failed: return ret ?: -ENODEV; } -static /*const*/ struct pcmcia_device_id softingcs_ids[] = { +static const struct pcmcia_device_id softingcs_ids[] = { /* softing */ PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002), diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 6a0a8fc..3fd5a24 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -2083,7 +2083,7 @@ static void ehea_set_multicast_list(struct net_device *dev) struct netdev_hw_addr *ha; int ret; - if (dev->flags & IFF_PROMISC) { + if (port->promisc) { ehea_promiscuous(dev, 1); return; } diff --git a/drivers/net/gianfar_ptp.c b/drivers/net/gianfar_ptp.c new file mode 100644 index 0000000..d8e1753 --- /dev/null +++ b/drivers/net/gianfar_ptp.c @@ -0,0 +1,588 @@ +/* + * PTP 1588 clock using the eTSEC + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/device.h> +#include <linux/hrtimer.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/timex.h> +#include <linux/io.h> + +#include <linux/ptp_clock_kernel.h> + +#include "gianfar.h" + +/* + * gianfar ptp registers + * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010 + */ +struct gianfar_ptp_registers { + u32 tmr_ctrl; /* Timer control register */ + u32 tmr_tevent; /* Timestamp event register */ + u32 tmr_temask; /* Timer event mask register */ + u32 tmr_pevent; /* Timestamp event register */ + u32 tmr_pemask; /* Timer event mask register */ + u32 tmr_stat; /* Timestamp status register */ + u32 tmr_cnt_h; /* Timer counter high register */ + u32 tmr_cnt_l; /* Timer counter low register */ + u32 tmr_add; /* Timer drift compensation addend register */ + u32 tmr_acc; /* Timer accumulator register */ + u32 tmr_prsc; /* Timer prescale */ + u8 res1[4]; + u32 tmroff_h; /* Timer offset high */ + u32 tmroff_l; /* Timer offset low */ + u8 res2[8]; + u32 tmr_alarm1_h; /* Timer alarm 1 high register */ + u32 tmr_alarm1_l; /* Timer alarm 1 high register */ + u32 tmr_alarm2_h; /* Timer alarm 2 high register */ + u32 tmr_alarm2_l; /* Timer alarm 2 high register */ + u8 res3[48]; + u32 tmr_fiper1; /* Timer fixed period interval */ + u32 tmr_fiper2; /* Timer fixed period interval */ + u32 tmr_fiper3; /* Timer fixed period interval */ + u8 res4[20]; + u32 tmr_etts1_h; /* Timestamp of general purpose external trigger */ + u32 tmr_etts1_l; /* Timestamp of general purpose external trigger */ + u32 tmr_etts2_h; /* Timestamp of general purpose external trigger */ + u32 tmr_etts2_l; /* Timestamp of general purpose external trigger */ +}; + +/* Bit definitions for the TMR_CTRL register */ +#define ALM1P (1<<31) /* Alarm1 output polarity */ +#define ALM2P (1<<30) /* Alarm2 output polarity */ +#define FS (1<<28) /* FIPER start indication */ +#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */ +#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */ +#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */ +#define TCLK_PERIOD_MASK (0x3ff) +#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */ +#define FRD (1<<14) /* FIPER Realignment Disable */ +#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */ +#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */ +#define ETEP2 (1<<9) /* External trigger 2 edge polarity */ +#define ETEP1 (1<<8) /* External trigger 1 edge polarity */ +#define COPH (1<<7) /* Generated clock output phase. */ +#define CIPH (1<<6) /* External oscillator input clock phase */ +#define TMSR (1<<5) /* Timer soft reset. */ +#define BYP (1<<3) /* Bypass drift compensated clock */ +#define TE (1<<2) /* 1588 timer enable. */ +#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source */ +#define CKSEL_MASK (0x3) + +/* Bit definitions for the TMR_TEVENT register */ +#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */ +#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */ +#define ALM2 (1<<17) /* Current time = alarm time register 2 */ +#define ALM1 (1<<16) /* Current time = alarm time register 1 */ +#define PP1 (1<<7) /* periodic pulse generated on FIPER1 */ +#define PP2 (1<<6) /* periodic pulse generated on FIPER2 */ +#define PP3 (1<<5) /* periodic pulse generated on FIPER3 */ + +/* Bit definitions for the TMR_TEMASK register */ +#define ETS2EN (1<<25) /* External trigger 2 timestamp enable */ +#define ETS1EN (1<<24) /* External trigger 1 timestamp enable */ +#define ALM2EN (1<<17) /* Timer ALM2 event enable */ +#define ALM1EN (1<<16) /* Timer ALM1 event enable */ +#define PP1EN (1<<7) /* Periodic pulse event 1 enable */ +#define PP2EN (1<<6) /* Periodic pulse event 2 enable */ + +/* Bit definitions for the TMR_PEVENT register */ +#define TXP2 (1<<9) /* PTP transmitted timestamp im TXTS2 */ +#define TXP1 (1<<8) /* PTP transmitted timestamp in TXTS1 */ +#define RXP (1<<0) /* PTP frame has been received */ + +/* Bit definitions for the TMR_PEMASK register */ +#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */ +#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */ +#define RXPEN (1<<0) /* Receive PTP packet event enable */ + +/* Bit definitions for the TMR_STAT register */ +#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */ +#define STAT_VEC_MASK (0x3f) + +/* Bit definitions for the TMR_PRSC register */ +#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */ +#define PRSC_OCK_MASK (0xffff) + + +#define DRIVER "gianfar_ptp" +#define DEFAULT_CKSEL 1 +#define N_ALARM 1 /* first alarm is used internally to reset fipers */ +#define N_EXT_TS 2 +#define REG_SIZE sizeof(struct gianfar_ptp_registers) + +struct etsects { + struct gianfar_ptp_registers *regs; + spinlock_t lock; /* protects regs */ + struct ptp_clock *clock; + struct ptp_clock_info caps; + struct resource *rsrc; + int irq; + u64 alarm_interval; /* for periodic alarm */ + u64 alarm_value; + u32 tclk_period; /* nanoseconds */ + u32 tmr_prsc; + u32 tmr_add; + u32 cksel; + u32 tmr_fiper1; + u32 tmr_fiper2; +}; + +/* + * Register access functions + */ + +/* Caller must hold etsects->lock. */ +static u64 tmr_cnt_read(struct etsects *etsects) +{ + u64 ns; + u32 lo, hi; + + lo = gfar_read(&etsects->regs->tmr_cnt_l); + hi = gfar_read(&etsects->regs->tmr_cnt_h); + ns = ((u64) hi) << 32; + ns |= lo; + return ns; +} + +/* Caller must hold etsects->lock. */ +static void tmr_cnt_write(struct etsects *etsects, u64 ns) +{ + u32 hi = ns >> 32; + u32 lo = ns & 0xffffffff; + + gfar_write(&etsects->regs->tmr_cnt_l, lo); + gfar_write(&etsects->regs->tmr_cnt_h, hi); +} + +/* Caller must hold etsects->lock. */ +static void set_alarm(struct etsects *etsects) +{ + u64 ns; + u32 lo, hi; + + ns = tmr_cnt_read(etsects) + 1500000000ULL; + ns = div_u64(ns, 1000000000UL) * 1000000000ULL; + ns -= etsects->tclk_period; + hi = ns >> 32; + lo = ns & 0xffffffff; + gfar_write(&etsects->regs->tmr_alarm1_l, lo); + gfar_write(&etsects->regs->tmr_alarm1_h, hi); +} + +/* Caller must hold etsects->lock. */ +static void set_fipers(struct etsects *etsects) +{ + u32 tmr_ctrl = gfar_read(&etsects->regs->tmr_ctrl); + + gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl & (~TE)); + gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc); + gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); + gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); + set_alarm(etsects); + gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|TE); +} + +/* + * Interrupt service routine + */ + +static irqreturn_t isr(int irq, void *priv) +{ + struct etsects *etsects = priv; + struct ptp_clock_event event; + u64 ns; + u32 ack = 0, lo, hi, mask, val; + + val = gfar_read(&etsects->regs->tmr_tevent); + + if (val & ETS1) { + ack |= ETS1; + hi = gfar_read(&etsects->regs->tmr_etts1_h); + lo = gfar_read(&etsects->regs->tmr_etts1_l); + event.type = PTP_CLOCK_EXTTS; + event.index = 0; + event.timestamp = ((u64) hi) << 32; + event.timestamp |= lo; + ptp_clock_event(etsects->clock, &event); + } + + if (val & ETS2) { + ack |= ETS2; + hi = gfar_read(&etsects->regs->tmr_etts2_h); + lo = gfar_read(&etsects->regs->tmr_etts2_l); + event.type = PTP_CLOCK_EXTTS; + event.index = 1; + event.timestamp = ((u64) hi) << 32; + event.timestamp |= lo; + ptp_clock_event(etsects->clock, &event); + } + + if (val & ALM2) { + ack |= ALM2; + if (etsects->alarm_value) { + event.type = PTP_CLOCK_ALARM; + event.index = 0; + event.timestamp = etsects->alarm_value; + ptp_clock_event(etsects->clock, &event); + } + if (etsects->alarm_interval) { + ns = etsects->alarm_value + etsects->alarm_interval; + hi = ns >> 32; + lo = ns & 0xffffffff; + spin_lock(&etsects->lock); + gfar_write(&etsects->regs->tmr_alarm2_l, lo); + gfar_write(&etsects->regs->tmr_alarm2_h, hi); + spin_unlock(&etsects->lock); + etsects->alarm_value = ns; + } else { + gfar_write(&etsects->regs->tmr_tevent, ALM2); + spin_lock(&etsects->lock); + mask = gfar_read(&etsects->regs->tmr_temask); + mask &= ~ALM2EN; + gfar_write(&etsects->regs->tmr_temask, mask); + spin_unlock(&etsects->lock); + etsects->alarm_value = 0; + etsects->alarm_interval = 0; + } + } + + if (val & PP1) { + ack |= PP1; + event.type = PTP_CLOCK_PPS; + ptp_clock_event(etsects->clock, &event); + } + + if (ack) { + gfar_write(&etsects->regs->tmr_tevent, ack); + return IRQ_HANDLED; + } else + return IRQ_NONE; +} + +/* + * PTP clock operations + */ + +static int ptp_gianfar_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + u64 adj; + u32 diff, tmr_add; + int neg_adj = 0; + struct etsects *etsects = container_of(ptp, struct etsects, caps); + + if (ppb < 0) { + neg_adj = 1; + ppb = -ppb; + } + tmr_add = etsects->tmr_add; + adj = tmr_add; + adj *= ppb; + diff = div_u64(adj, 1000000000ULL); + + tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; + + gfar_write(&etsects->regs->tmr_add, tmr_add); + + return 0; +} + +static int ptp_gianfar_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + s64 now; + unsigned long flags; + struct etsects *etsects = container_of(ptp, struct etsects, caps); + + spin_lock_irqsave(&etsects->lock, flags); + + now = tmr_cnt_read(etsects); + now += delta; + tmr_cnt_write(etsects, now); + + spin_unlock_irqrestore(&etsects->lock, flags); + + set_fipers(etsects); + + return 0; +} + +static int ptp_gianfar_gettime(struct ptp_clock_info *ptp, struct timespec *ts) +{ + u64 ns; + u32 remainder; + unsigned long flags; + struct etsects *etsects = container_of(ptp, struct etsects, caps); + + spin_lock_irqsave(&etsects->lock, flags); + + ns = tmr_cnt_read(etsects); + + spin_unlock_irqrestore(&etsects->lock, flags); + + ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); + ts->tv_nsec = remainder; + return 0; +} + +static int ptp_gianfar_settime(struct ptp_clock_info *ptp, + const struct timespec *ts) +{ + u64 ns; + unsigned long flags; + struct etsects *etsects = container_of(ptp, struct etsects, caps); + + ns = ts->tv_sec * 1000000000ULL; + ns += ts->tv_nsec; + + spin_lock_irqsave(&etsects->lock, flags); + + tmr_cnt_write(etsects, ns); + set_fipers(etsects); + + spin_unlock_irqrestore(&etsects->lock, flags); + + return 0; +} + +static int ptp_gianfar_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct etsects *etsects = container_of(ptp, struct etsects, caps); + unsigned long flags; + u32 bit, mask; + + switch (rq->type) { + case PTP_CLK_REQ_EXTTS: + switch (rq->extts.index) { + case 0: + bit = ETS1EN; + break; + case 1: + bit = ETS2EN; + break; + default: + return -EINVAL; + } + spin_lock_irqsave(&etsects->lock, flags); + mask = gfar_read(&etsects->regs->tmr_temask); + if (on) + mask |= bit; + else + mask &= ~bit; + gfar_write(&etsects->regs->tmr_temask, mask); + spin_unlock_irqrestore(&etsects->lock, flags); + return 0; + + case PTP_CLK_REQ_PPS: + spin_lock_irqsave(&etsects->lock, flags); + mask = gfar_read(&etsects->regs->tmr_temask); + if (on) + mask |= PP1EN; + else + mask &= ~PP1EN; + gfar_write(&etsects->regs->tmr_temask, mask); + spin_unlock_irqrestore(&etsects->lock, flags); + return 0; + + default: + break; + } + + return -EOPNOTSUPP; +} + +static struct ptp_clock_info ptp_gianfar_caps = { + .owner = THIS_MODULE, + .name = "gianfar clock", + .max_adj = 512000, + .n_alarm = N_ALARM, + .n_ext_ts = N_EXT_TS, + .n_per_out = 0, + .pps = 1, + .adjfreq = ptp_gianfar_adjfreq, + .adjtime = ptp_gianfar_adjtime, + .gettime = ptp_gianfar_gettime, + .settime = ptp_gianfar_settime, + .enable = ptp_gianfar_enable, +}; + +/* OF device tree */ + +static int get_of_u32(struct device_node *node, char *str, u32 *val) +{ + int plen; + const u32 *prop = of_get_property(node, str, &plen); + + if (!prop || plen != sizeof(*prop)) + return -1; + *val = *prop; + return 0; +} + +static int gianfar_ptp_probe(struct platform_device *dev) +{ + struct device_node *node = dev->dev.of_node; + struct etsects *etsects; + struct timespec now; + int err = -ENOMEM; + u32 tmr_ctrl; + unsigned long flags; + + etsects = kzalloc(sizeof(*etsects), GFP_KERNEL); + if (!etsects) + goto no_memory; + + err = -ENODEV; + + etsects->caps = ptp_gianfar_caps; + etsects->cksel = DEFAULT_CKSEL; + + if (get_of_u32(node, "fsl,tclk-period", &etsects->tclk_period) || + get_of_u32(node, "fsl,tmr-prsc", &etsects->tmr_prsc) || + get_of_u32(node, "fsl,tmr-add", &etsects->tmr_add) || + get_of_u32(node, "fsl,tmr-fiper1", &etsects->tmr_fiper1) || + get_of_u32(node, "fsl,tmr-fiper2", &etsects->tmr_fiper2) || + get_of_u32(node, "fsl,max-adj", &etsects->caps.max_adj)) { + pr_err("device tree node missing required elements\n"); + goto no_node; + } + + etsects->irq = platform_get_irq(dev, 0); + + if (etsects->irq == NO_IRQ) { + pr_err("irq not in device tree\n"); + goto no_node; + } + if (request_irq(etsects->irq, isr, 0, DRIVER, etsects)) { + pr_err("request_irq failed\n"); + goto no_node; + } + + etsects->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!etsects->rsrc) { + pr_err("no resource\n"); + goto no_resource; + } + if (request_resource(&ioport_resource, etsects->rsrc)) { + pr_err("resource busy\n"); + goto no_resource; + } + + spin_lock_init(&etsects->lock); + + etsects->regs = ioremap(etsects->rsrc->start, + 1 + etsects->rsrc->end - etsects->rsrc->start); + if (!etsects->regs) { + pr_err("ioremap ptp registers failed\n"); + goto no_ioremap; + } + getnstimeofday(&now); + ptp_gianfar_settime(&etsects->caps, &now); + + tmr_ctrl = + (etsects->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | + (etsects->cksel & CKSEL_MASK) << CKSEL_SHIFT; + + spin_lock_irqsave(&etsects->lock, flags); + + gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl); + gfar_write(&etsects->regs->tmr_add, etsects->tmr_add); + gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc); + gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); + gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); + set_alarm(etsects); + gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE); + + spin_unlock_irqrestore(&etsects->lock, flags); + + etsects->clock = ptp_clock_register(&etsects->caps); + if (IS_ERR(etsects->clock)) { + err = PTR_ERR(etsects->clock); + goto no_clock; + } + + dev_set_drvdata(&dev->dev, etsects); + + return 0; + +no_clock: +no_ioremap: + release_resource(etsects->rsrc); +no_resource: + free_irq(etsects->irq, etsects); +no_node: + kfree(etsects); +no_memory: + return err; +} + +static int gianfar_ptp_remove(struct platform_device *dev) +{ + struct etsects *etsects = dev_get_drvdata(&dev->dev); + + gfar_write(&etsects->regs->tmr_temask, 0); + gfar_write(&etsects->regs->tmr_ctrl, 0); + + ptp_clock_unregister(etsects->clock); + iounmap(etsects->regs); + release_resource(etsects->rsrc); + free_irq(etsects->irq, etsects); + kfree(etsects); + + return 0; +} + +static struct of_device_id match_table[] = { + { .compatible = "fsl,etsec-ptp" }, + {}, +}; + +static struct platform_driver gianfar_ptp_driver = { + .driver = { + .name = "gianfar_ptp", + .of_match_table = match_table, + .owner = THIS_MODULE, + }, + .probe = gianfar_ptp_probe, + .remove = gianfar_ptp_remove, +}; + +/* module operations */ + +static int __init ptp_gianfar_init(void) +{ + return platform_driver_register(&gianfar_ptp_driver); +} + +module_init(ptp_gianfar_init); + +static void __exit ptp_gianfar_exit(void) +{ + platform_driver_unregister(&gianfar_ptp_driver); +} + +module_exit(ptp_gianfar_exit); + +MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>"); +MODULE_DESCRIPTION("PTP clock using the eTSEC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 96c9561..32f07f8 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -915,7 +915,7 @@ static void ioc3_alloc_rings(struct net_device *dev) skb = ioc3_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC); if (!skb) { - show_free_areas(); + show_free_areas(0); continue; } diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c index f940dfa..9d4ce1a 100644 --- a/drivers/net/irda/bfin_sir.c +++ b/drivers/net/irda/bfin_sir.c @@ -67,27 +67,27 @@ static void bfin_sir_stop_tx(struct bfin_sir_port *port) disable_dma(port->tx_dma_channel); #endif - while (!(SIR_UART_GET_LSR(port) & THRE)) { + while (!(UART_GET_LSR(port) & THRE)) { cpu_relax(); continue; } - SIR_UART_STOP_TX(port); + UART_CLEAR_IER(port, ETBEI); } static void bfin_sir_enable_tx(struct bfin_sir_port *port) { - SIR_UART_ENABLE_TX(port); + UART_SET_IER(port, ETBEI); } static void bfin_sir_stop_rx(struct bfin_sir_port *port) { - SIR_UART_STOP_RX(port); + UART_CLEAR_IER(port, ERBFI); } static void bfin_sir_enable_rx(struct bfin_sir_port *port) { - SIR_UART_ENABLE_RX(port); + UART_SET_IER(port, ERBFI); } static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) @@ -116,7 +116,7 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) do { udelay(utime); - lsr = SIR_UART_GET_LSR(port); + lsr = UART_GET_LSR(port); } while (!(lsr & TEMT) && count--); /* The useconds for 1 bits to transmit */ @@ -125,27 +125,27 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) /* Clear UCEN bit to reset the UART state machine * and control registers */ - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); val &= ~UCEN; - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); /* Set DLAB in LCR to Access THR RBR IER */ - SIR_UART_SET_DLAB(port); + UART_SET_DLAB(port); SSYNC(); - SIR_UART_PUT_DLL(port, quot & 0xFF); - SIR_UART_PUT_DLH(port, (quot >> 8) & 0xFF); + UART_PUT_DLL(port, quot & 0xFF); + UART_PUT_DLH(port, (quot >> 8) & 0xFF); SSYNC(); /* Clear DLAB in LCR */ - SIR_UART_CLEAR_DLAB(port); + UART_CLEAR_DLAB(port); SSYNC(); - SIR_UART_PUT_LCR(port, lcr); + UART_PUT_LCR(port, lcr); - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); val |= UCEN; - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); ret = 0; break; @@ -154,12 +154,12 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) break; } - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); /* If not add the 'RPOLC', we can't catch the receive interrupt. * It's related with the HW layout and the IR transiver. */ val |= IREN | RPOLC; - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); return ret; } @@ -168,7 +168,7 @@ static int bfin_sir_is_receiving(struct net_device *dev) struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_port *port = self->sir_port; - if (!(SIR_UART_GET_IER(port) & ERBFI)) + if (!(UART_GET_IER(port) & ERBFI)) return 0; return self->rx_buff.state != OUTSIDE_FRAME; } @@ -182,7 +182,7 @@ static void bfin_sir_tx_chars(struct net_device *dev) if (self->tx_buff.len != 0) { chr = *(self->tx_buff.data); - SIR_UART_PUT_CHAR(port, chr); + UART_PUT_CHAR(port, chr); self->tx_buff.data++; self->tx_buff.len--; } else { @@ -206,8 +206,8 @@ static void bfin_sir_rx_chars(struct net_device *dev) struct bfin_sir_port *port = self->sir_port; unsigned char ch; - SIR_UART_CLEAR_LSR(port); - ch = SIR_UART_GET_CHAR(port); + UART_CLEAR_LSR(port); + ch = UART_GET_CHAR(port); async_unwrap_char(dev, &self->stats, &self->rx_buff, ch); dev->last_rx = jiffies; } @@ -219,7 +219,7 @@ static irqreturn_t bfin_sir_rx_int(int irq, void *dev_id) struct bfin_sir_port *port = self->sir_port; spin_lock(&self->lock); - while ((SIR_UART_GET_LSR(port) & DR)) + while ((UART_GET_LSR(port) & DR)) bfin_sir_rx_chars(dev); spin_unlock(&self->lock); @@ -233,7 +233,7 @@ static irqreturn_t bfin_sir_tx_int(int irq, void *dev_id) struct bfin_sir_port *port = self->sir_port; spin_lock(&self->lock); - if (SIR_UART_GET_LSR(port) & THRE) + if (UART_GET_LSR(port) & THRE) bfin_sir_tx_chars(dev); spin_unlock(&self->lock); @@ -312,7 +312,7 @@ static void bfin_sir_dma_rx_chars(struct net_device *dev) struct bfin_sir_port *port = self->sir_port; int i; - SIR_UART_CLEAR_LSR(port); + UART_CLEAR_LSR(port); for (i = port->rx_dma_buf.head; i < port->rx_dma_buf.tail; i++) async_unwrap_char(dev, &self->stats, &self->rx_buff, port->rx_dma_buf.buf[i]); @@ -430,11 +430,10 @@ static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev unsigned short val; bfin_sir_stop_rx(port); - SIR_UART_DISABLE_INTS(port); - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); val &= ~(UCEN | IREN | RPOLC); - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); #ifdef CONFIG_SIR_BFIN_DMA disable_dma(port->tx_dma_channel); @@ -518,12 +517,12 @@ static void bfin_sir_send_work(struct work_struct *work) * sending data. We also can set the speed, which will * reset all the UART. */ - val = SIR_UART_GET_GCTL(port); + val = UART_GET_GCTL(port); val &= ~(IREN | RPOLC); - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); SSYNC(); val |= IREN | RPOLC; - SIR_UART_PUT_GCTL(port, val); + UART_PUT_GCTL(port, val); SSYNC(); /* bfin_sir_set_speed(port, self->speed); */ diff --git a/drivers/net/irda/bfin_sir.h b/drivers/net/irda/bfin_sir.h index e3b285a..29cbde8 100644 --- a/drivers/net/irda/bfin_sir.h +++ b/drivers/net/irda/bfin_sir.h @@ -26,7 +26,6 @@ #include <asm/cacheflush.h> #include <asm/dma.h> #include <asm/portmux.h> -#include <mach/bfin_serial_5xx.h> #undef DRIVER_NAME #ifdef CONFIG_SIR_BFIN_DMA @@ -83,64 +82,10 @@ struct bfin_sir_self { #define DRIVER_NAME "bfin_sir" -#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR) -#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL) -#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH) -#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR) -#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL) - -#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v) -#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v) -#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v) -#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v) -#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v) - -#ifdef CONFIG_BF54x -#define SIR_UART_GET_LSR(port) bfin_read16((port)->membase + OFFSET_LSR) -#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER_SET) -#define SIR_UART_SET_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_SET), v) -#define SIR_UART_CLEAR_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_CLEAR), v) -#define SIR_UART_PUT_LSR(port, v) bfin_write16(((port)->membase + OFFSET_LSR), v) -#define SIR_UART_CLEAR_LSR(port) bfin_write16(((port)->membase + OFFSET_LSR), -1) - -#define SIR_UART_SET_DLAB(port) -#define SIR_UART_CLEAR_DLAB(port) - -#define SIR_UART_ENABLE_INTS(port, v) SIR_UART_SET_IER(port, v) -#define SIR_UART_DISABLE_INTS(port) SIR_UART_CLEAR_IER(port, 0xF) -#define SIR_UART_STOP_TX(port) do { SIR_UART_PUT_LSR(port, TFI); SIR_UART_CLEAR_IER(port, ETBEI); } while (0) -#define SIR_UART_ENABLE_TX(port) do { SIR_UART_SET_IER(port, ETBEI); } while (0) -#define SIR_UART_STOP_RX(port) do { SIR_UART_CLEAR_IER(port, ERBFI); } while (0) -#define SIR_UART_ENABLE_RX(port) do { SIR_UART_SET_IER(port, ERBFI); } while (0) -#else - -#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR) -#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER) -#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v) - -#define SIR_UART_SET_DLAB(port) do { SIR_UART_PUT_LCR(port, SIR_UART_GET_LCR(port) | DLAB); } while (0) -#define SIR_UART_CLEAR_DLAB(port) do { SIR_UART_PUT_LCR(port, SIR_UART_GET_LCR(port) & ~DLAB); } while (0) - -#define SIR_UART_ENABLE_INTS(port, v) SIR_UART_PUT_IER(port, v) -#define SIR_UART_DISABLE_INTS(port) SIR_UART_PUT_IER(port, 0) -#define SIR_UART_STOP_TX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) & ~ETBEI); } while (0) -#define SIR_UART_ENABLE_TX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) | ETBEI); } while (0) -#define SIR_UART_STOP_RX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) & ~ERBFI); } while (0) -#define SIR_UART_ENABLE_RX(port) do { SIR_UART_PUT_IER(port, SIR_UART_GET_IER(port) | ERBFI); } while (0) - -static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port) -{ - unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR); - port->lsr |= (lsr & (BI|FE|PE|OE)); - return lsr | port->lsr; -} - -static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port) -{ - port->lsr = 0; - bfin_read16(port->membase + OFFSET_LSR); -} -#endif +#define port_membase(port) (((struct bfin_sir_port *)(port))->membase) +#define get_lsr_cache(port) (((struct bfin_sir_port *)(port))->lsr) +#define put_lsr_cache(port, v) (((struct bfin_sir_port *)(port))->lsr = (v)) +#include <asm/bfin_serial.h> static const unsigned short per[][4] = { /* rx pin tx pin NULL uart_number */ diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c index f0d8346..4d40626 100644 --- a/drivers/net/ks8842.c +++ b/drivers/net/ks8842.c @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/mfd/core.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> @@ -1146,7 +1145,7 @@ static int __devinit ks8842_probe(struct platform_device *pdev) struct resource *iomem; struct net_device *netdev; struct ks8842_adapter *adapter; - struct ks8842_platform_data *pdata = mfd_get_data(pdev); + struct ks8842_platform_data *pdata = pdev->dev.platform_data; u16 id; unsigned i; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 81ac330..34c5e1c 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -1150,7 +1150,7 @@ static int el3_close(struct net_device *dev) return 0; } -static struct pcmcia_device_id tc574_ids[] = { +static const struct pcmcia_device_id tc574_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "cis/3CCFEM556.cis"), PCMCIA_DEVICE_NULL, diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 79b9ca0..4a1a358 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -908,7 +908,7 @@ static int el3_close(struct net_device *dev) return 0; } -static struct pcmcia_device_id tc589_ids[] = { +static const struct pcmcia_device_id tc589_ids[] = { PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562), PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 3077d72..9953db7 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -687,7 +687,7 @@ static void block_output(struct net_device *dev, int count, outsw(nic_base + AXNET_DATAPORT, buf, count>>1); } -static struct pcmcia_device_id axnet_ids[] = { +static const struct pcmcia_device_id axnet_ids[] = { PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081), PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301), PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328), diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 27bfad7..980e65c 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -316,7 +316,7 @@ static int com20020_resume(struct pcmcia_device *link) return 0; } -static struct pcmcia_device_id com20020_ids[] = { +static const struct pcmcia_device_id com20020_ids[] = { PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), PCMCIA_DEVICE_PROD_ID12("SoHard AG", diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 530ab5a..723815e 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -667,7 +667,7 @@ static int fmvj18x_resume(struct pcmcia_device *link) /*====================================================================*/ -static struct pcmcia_device_id fmvj18x_ids[] = { +static const struct pcmcia_device_id fmvj18x_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004), PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59), PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922), diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 15d57f5..6006d54 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -340,7 +340,7 @@ static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase) outb(0x40, dev->base_addr); } -static struct pcmcia_device_id ibmtr_ids[] = { +static const struct pcmcia_device_id ibmtr_ids[] = { PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e), PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47), PCMCIA_DEVICE_NULL, diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 76683d9..9d70b65 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -1494,7 +1494,7 @@ static void set_multicast_list(struct net_device *dev) } /* set_multicast_list */ -static struct pcmcia_device_id nmclan_ids[] = { +static const struct pcmcia_device_id nmclan_ids[] = { PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941), PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet+", 0xebf1d60, 0xad673aaf), PCMCIA_DEVICE_NULL, diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index e953793..b4fd7c3 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1463,7 +1463,7 @@ failed: /*====================================================================*/ -static struct pcmcia_device_id pcnet_ids[] = { +static const struct pcmcia_device_id pcnet_ids[] = { PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15), diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 288e4f1..1cd9394 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -2014,7 +2014,7 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) return rc; } -static struct pcmcia_device_id smc91c92_ids[] = { +static const struct pcmcia_device_id smc91c92_ids[] = { PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0109, 0x0501), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0140, 0x000a), PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63), diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index a46b7fd..e33b190 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1738,7 +1738,7 @@ do_stop(struct net_device *dev) return 0; } -static struct pcmcia_device_id xirc2ps_ids[] = { +static const struct pcmcia_device_id xirc2ps_ids[] = { PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0089, 0x110a), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0138, 0x110a), PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 13bebab..2333215 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_FIXED_PHY) += fixed.o obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o obj-$(CONFIG_NATIONAL_PHY) += national.o +obj-$(CONFIG_DP83640_PHY) += dp83640.o obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c new file mode 100644 index 0000000..b0c9522 --- /dev/null +++ b/drivers/net/phy/dp83640.c @@ -0,0 +1,1100 @@ +/* + * Driver for the National Semiconductor DP83640 PHYTER + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/ethtool.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/mii.h> +#include <linux/module.h> +#include <linux/net_tstamp.h> +#include <linux/netdevice.h> +#include <linux/phy.h> +#include <linux/ptp_classify.h> +#include <linux/ptp_clock_kernel.h> + +#include "dp83640_reg.h" + +#define DP83640_PHY_ID 0x20005ce1 +#define PAGESEL 0x13 +#define LAYER4 0x02 +#define LAYER2 0x01 +#define MAX_RXTS 4 +#define MAX_TXTS 4 +#define N_EXT_TS 1 +#define PSF_PTPVER 2 +#define PSF_EVNT 0x4000 +#define PSF_RX 0x2000 +#define PSF_TX 0x1000 +#define EXT_EVENT 1 +#define EXT_GPIO 1 +#define CAL_EVENT 2 +#define CAL_GPIO 9 +#define CAL_TRIGGER 2 + +/* phyter seems to miss the mark by 16 ns */ +#define ADJTIME_FIX 16 + +#if defined(__BIG_ENDIAN) +#define ENDIAN_FLAG 0 +#elif defined(__LITTLE_ENDIAN) +#define ENDIAN_FLAG PSF_ENDIAN +#endif + +#define SKB_PTP_TYPE(__skb) (*(unsigned int *)((__skb)->cb)) + +struct phy_rxts { + u16 ns_lo; /* ns[15:0] */ + u16 ns_hi; /* overflow[1:0], ns[29:16] */ + u16 sec_lo; /* sec[15:0] */ + u16 sec_hi; /* sec[31:16] */ + u16 seqid; /* sequenceId[15:0] */ + u16 msgtype; /* messageType[3:0], hash[11:0] */ +}; + +struct phy_txts { + u16 ns_lo; /* ns[15:0] */ + u16 ns_hi; /* overflow[1:0], ns[29:16] */ + u16 sec_lo; /* sec[15:0] */ + u16 sec_hi; /* sec[31:16] */ +}; + +struct rxts { + struct list_head list; + unsigned long tmo; + u64 ns; + u16 seqid; + u8 msgtype; + u16 hash; +}; + +struct dp83640_clock; + +struct dp83640_private { + struct list_head list; + struct dp83640_clock *clock; + struct phy_device *phydev; + struct work_struct ts_work; + int hwts_tx_en; + int hwts_rx_en; + int layer; + int version; + /* remember state of cfg0 during calibration */ + int cfg0; + /* remember the last event time stamp */ + struct phy_txts edata; + /* list of rx timestamps */ + struct list_head rxts; + struct list_head rxpool; + struct rxts rx_pool_data[MAX_RXTS]; + /* protects above three fields from concurrent access */ + spinlock_t rx_lock; + /* queues of incoming and outgoing packets */ + struct sk_buff_head rx_queue; + struct sk_buff_head tx_queue; +}; + +struct dp83640_clock { + /* keeps the instance in the 'phyter_clocks' list */ + struct list_head list; + /* we create one clock instance per MII bus */ + struct mii_bus *bus; + /* protects extended registers from concurrent access */ + struct mutex extreg_lock; + /* remembers which page was last selected */ + int page; + /* our advertised capabilities */ + struct ptp_clock_info caps; + /* protects the three fields below from concurrent access */ + struct mutex clock_lock; + /* the one phyter from which we shall read */ + struct dp83640_private *chosen; + /* list of the other attached phyters, not chosen */ + struct list_head phylist; + /* reference to our PTP hardware clock */ + struct ptp_clock *ptp_clock; +}; + +/* globals */ + +static int chosen_phy = -1; +static ushort cal_gpio = 4; + +module_param(chosen_phy, int, 0444); +module_param(cal_gpio, ushort, 0444); + +MODULE_PARM_DESC(chosen_phy, \ + "The address of the PHY to use for the ancillary clock features"); +MODULE_PARM_DESC(cal_gpio, \ + "Which GPIO line to use for synchronizing multiple PHYs"); + +/* a list of clocks and a mutex to protect it */ +static LIST_HEAD(phyter_clocks); +static DEFINE_MUTEX(phyter_clocks_lock); + +static void rx_timestamp_work(struct work_struct *work); + +/* extended register access functions */ + +#define BROADCAST_ADDR 31 + +static inline int broadcast_write(struct mii_bus *bus, u32 regnum, u16 val) +{ + return mdiobus_write(bus, BROADCAST_ADDR, regnum, val); +} + +/* Caller must hold extreg_lock. */ +static int ext_read(struct phy_device *phydev, int page, u32 regnum) +{ + struct dp83640_private *dp83640 = phydev->priv; + int val; + + if (dp83640->clock->page != page) { + broadcast_write(phydev->bus, PAGESEL, page); + dp83640->clock->page = page; + } + val = phy_read(phydev, regnum); + + return val; +} + +/* Caller must hold extreg_lock. */ +static void ext_write(int broadcast, struct phy_device *phydev, + int page, u32 regnum, u16 val) +{ + struct dp83640_private *dp83640 = phydev->priv; + + if (dp83640->clock->page != page) { + broadcast_write(phydev->bus, PAGESEL, page); + dp83640->clock->page = page; + } + if (broadcast) + broadcast_write(phydev->bus, regnum, val); + else + phy_write(phydev, regnum, val); +} + +/* Caller must hold extreg_lock. */ +static int tdr_write(int bc, struct phy_device *dev, + const struct timespec *ts, u16 cmd) +{ + ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_nsec & 0xffff);/* ns[15:0] */ + ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_nsec >> 16); /* ns[31:16] */ + ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_sec & 0xffff); /* sec[15:0] */ + ext_write(bc, dev, PAGE4, PTP_TDR, ts->tv_sec >> 16); /* sec[31:16]*/ + + ext_write(bc, dev, PAGE4, PTP_CTL, cmd); + + return 0; +} + +/* convert phy timestamps into driver timestamps */ + +static void phy2rxts(struct phy_rxts *p, struct rxts *rxts) +{ + u32 sec; + + sec = p->sec_lo; + sec |= p->sec_hi << 16; + + rxts->ns = p->ns_lo; + rxts->ns |= (p->ns_hi & 0x3fff) << 16; + rxts->ns += ((u64)sec) * 1000000000ULL; + rxts->seqid = p->seqid; + rxts->msgtype = (p->msgtype >> 12) & 0xf; + rxts->hash = p->msgtype & 0x0fff; + rxts->tmo = jiffies + HZ; +} + +static u64 phy2txts(struct phy_txts *p) +{ + u64 ns; + u32 sec; + + sec = p->sec_lo; + sec |= p->sec_hi << 16; + + ns = p->ns_lo; + ns |= (p->ns_hi & 0x3fff) << 16; + ns += ((u64)sec) * 1000000000ULL; + + return ns; +} + +/* ptp clock methods */ + +static int ptp_dp83640_adjfreq(struct ptp_clock_info *ptp, s32 ppb) +{ + struct dp83640_clock *clock = + container_of(ptp, struct dp83640_clock, caps); + struct phy_device *phydev = clock->chosen->phydev; + u64 rate; + int neg_adj = 0; + u16 hi, lo; + + if (ppb < 0) { + neg_adj = 1; + ppb = -ppb; + } + rate = ppb; + rate <<= 26; + rate = div_u64(rate, 1953125); + + hi = (rate >> 16) & PTP_RATE_HI_MASK; + if (neg_adj) + hi |= PTP_RATE_DIR; + + lo = rate & 0xffff; + + mutex_lock(&clock->extreg_lock); + + ext_write(1, phydev, PAGE4, PTP_RATEH, hi); + ext_write(1, phydev, PAGE4, PTP_RATEL, lo); + + mutex_unlock(&clock->extreg_lock); + + return 0; +} + +static int ptp_dp83640_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct dp83640_clock *clock = + container_of(ptp, struct dp83640_clock, caps); + struct phy_device *phydev = clock->chosen->phydev; + struct timespec ts; + int err; + + delta += ADJTIME_FIX; + + ts = ns_to_timespec(delta); + + mutex_lock(&clock->extreg_lock); + + err = tdr_write(1, phydev, &ts, PTP_STEP_CLK); + + mutex_unlock(&clock->extreg_lock); + + return err; +} + +static int ptp_dp83640_gettime(struct ptp_clock_info *ptp, struct timespec *ts) +{ + struct dp83640_clock *clock = + container_of(ptp, struct dp83640_clock, caps); + struct phy_device *phydev = clock->chosen->phydev; + unsigned int val[4]; + + mutex_lock(&clock->extreg_lock); + + ext_write(0, phydev, PAGE4, PTP_CTL, PTP_RD_CLK); + + val[0] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[15:0] */ + val[1] = ext_read(phydev, PAGE4, PTP_TDR); /* ns[31:16] */ + val[2] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[15:0] */ + val[3] = ext_read(phydev, PAGE4, PTP_TDR); /* sec[31:16] */ + + mutex_unlock(&clock->extreg_lock); + + ts->tv_nsec = val[0] | (val[1] << 16); + ts->tv_sec = val[2] | (val[3] << 16); + + return 0; +} + +static int ptp_dp83640_settime(struct ptp_clock_info *ptp, + const struct timespec *ts) +{ + struct dp83640_clock *clock = + container_of(ptp, struct dp83640_clock, caps); + struct phy_device *phydev = clock->chosen->phydev; + int err; + + mutex_lock(&clock->extreg_lock); + + err = tdr_write(1, phydev, ts, PTP_LOAD_CLK); + + mutex_unlock(&clock->extreg_lock); + + return err; +} + +static int ptp_dp83640_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct dp83640_clock *clock = + container_of(ptp, struct dp83640_clock, caps); + struct phy_device *phydev = clock->chosen->phydev; + u16 evnt; + + switch (rq->type) { + case PTP_CLK_REQ_EXTTS: + if (rq->extts.index != 0) + return -EINVAL; + evnt = EVNT_WR | (EXT_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT; + if (on) { + evnt |= (EXT_GPIO & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT; + evnt |= EVNT_RISE; + } + ext_write(0, phydev, PAGE5, PTP_EVNT, evnt); + return 0; + default: + break; + } + + return -EOPNOTSUPP; +} + +static u8 status_frame_dst[6] = { 0x01, 0x1B, 0x19, 0x00, 0x00, 0x00 }; +static u8 status_frame_src[6] = { 0x08, 0x00, 0x17, 0x0B, 0x6B, 0x0F }; + +static void enable_status_frames(struct phy_device *phydev, bool on) +{ + u16 cfg0 = 0, ver; + + if (on) + cfg0 = PSF_EVNT_EN | PSF_RXTS_EN | PSF_TXTS_EN | ENDIAN_FLAG; + + ver = (PSF_PTPVER & VERSIONPTP_MASK) << VERSIONPTP_SHIFT; + + ext_write(0, phydev, PAGE5, PSF_CFG0, cfg0); + ext_write(0, phydev, PAGE6, PSF_CFG1, ver); + + if (!phydev->attached_dev) { + pr_warning("dp83640: expected to find an attached netdevice\n"); + return; + } + + if (on) { + if (dev_mc_add(phydev->attached_dev, status_frame_dst)) + pr_warning("dp83640: failed to add mc address\n"); + } else { + if (dev_mc_del(phydev->attached_dev, status_frame_dst)) + pr_warning("dp83640: failed to delete mc address\n"); + } +} + +static bool is_status_frame(struct sk_buff *skb, int type) +{ + struct ethhdr *h = eth_hdr(skb); + + if (PTP_CLASS_V2_L2 == type && + !memcmp(h->h_source, status_frame_src, sizeof(status_frame_src))) + return true; + else + return false; +} + +static int expired(struct rxts *rxts) +{ + return time_after(jiffies, rxts->tmo); +} + +/* Caller must hold rx_lock. */ +static void prune_rx_ts(struct dp83640_private *dp83640) +{ + struct list_head *this, *next; + struct rxts *rxts; + + list_for_each_safe(this, next, &dp83640->rxts) { + rxts = list_entry(this, struct rxts, list); + if (expired(rxts)) { + list_del_init(&rxts->list); + list_add(&rxts->list, &dp83640->rxpool); + } + } +} + +/* synchronize the phyters so they act as one clock */ + +static void enable_broadcast(struct phy_device *phydev, int init_page, int on) +{ + int val; + phy_write(phydev, PAGESEL, 0); + val = phy_read(phydev, PHYCR2); + if (on) + val |= BC_WRITE; + else + val &= ~BC_WRITE; + phy_write(phydev, PHYCR2, val); + phy_write(phydev, PAGESEL, init_page); +} + +static void recalibrate(struct dp83640_clock *clock) +{ + s64 now, diff; + struct phy_txts event_ts; + struct timespec ts; + struct list_head *this; + struct dp83640_private *tmp; + struct phy_device *master = clock->chosen->phydev; + u16 cfg0, evnt, ptp_trig, trigger, val; + + trigger = CAL_TRIGGER; + + mutex_lock(&clock->extreg_lock); + + /* + * enable broadcast, disable status frames, enable ptp clock + */ + list_for_each(this, &clock->phylist) { + tmp = list_entry(this, struct dp83640_private, list); + enable_broadcast(tmp->phydev, clock->page, 1); + tmp->cfg0 = ext_read(tmp->phydev, PAGE5, PSF_CFG0); + ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, 0); + ext_write(0, tmp->phydev, PAGE4, PTP_CTL, PTP_ENABLE); + } + enable_broadcast(master, clock->page, 1); + cfg0 = ext_read(master, PAGE5, PSF_CFG0); + ext_write(0, master, PAGE5, PSF_CFG0, 0); + ext_write(0, master, PAGE4, PTP_CTL, PTP_ENABLE); + + /* + * enable an event timestamp + */ + evnt = EVNT_WR | EVNT_RISE | EVNT_SINGLE; + evnt |= (CAL_EVENT & EVNT_SEL_MASK) << EVNT_SEL_SHIFT; + evnt |= (cal_gpio & EVNT_GPIO_MASK) << EVNT_GPIO_SHIFT; + + list_for_each(this, &clock->phylist) { + tmp = list_entry(this, struct dp83640_private, list); + ext_write(0, tmp->phydev, PAGE5, PTP_EVNT, evnt); + } + ext_write(0, master, PAGE5, PTP_EVNT, evnt); + + /* + * configure a trigger + */ + ptp_trig = TRIG_WR | TRIG_IF_LATE | TRIG_PULSE; + ptp_trig |= (trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT; + ptp_trig |= (cal_gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT; + ext_write(0, master, PAGE5, PTP_TRIG, ptp_trig); + + /* load trigger */ + val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT; + val |= TRIG_LOAD; + ext_write(0, master, PAGE4, PTP_CTL, val); + + /* enable trigger */ + val &= ~TRIG_LOAD; + val |= TRIG_EN; + ext_write(0, master, PAGE4, PTP_CTL, val); + + /* disable trigger */ + val = (trigger & TRIG_SEL_MASK) << TRIG_SEL_SHIFT; + val |= TRIG_DIS; + ext_write(0, master, PAGE4, PTP_CTL, val); + + /* + * read out and correct offsets + */ + val = ext_read(master, PAGE4, PTP_STS); + pr_info("master PTP_STS 0x%04hx", val); + val = ext_read(master, PAGE4, PTP_ESTS); + pr_info("master PTP_ESTS 0x%04hx", val); + event_ts.ns_lo = ext_read(master, PAGE4, PTP_EDATA); + event_ts.ns_hi = ext_read(master, PAGE4, PTP_EDATA); + event_ts.sec_lo = ext_read(master, PAGE4, PTP_EDATA); + event_ts.sec_hi = ext_read(master, PAGE4, PTP_EDATA); + now = phy2txts(&event_ts); + + list_for_each(this, &clock->phylist) { + tmp = list_entry(this, struct dp83640_private, list); + val = ext_read(tmp->phydev, PAGE4, PTP_STS); + pr_info("slave PTP_STS 0x%04hx", val); + val = ext_read(tmp->phydev, PAGE4, PTP_ESTS); + pr_info("slave PTP_ESTS 0x%04hx", val); + event_ts.ns_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA); + event_ts.ns_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA); + event_ts.sec_lo = ext_read(tmp->phydev, PAGE4, PTP_EDATA); + event_ts.sec_hi = ext_read(tmp->phydev, PAGE4, PTP_EDATA); + diff = now - (s64) phy2txts(&event_ts); + pr_info("slave offset %lld nanoseconds\n", diff); + diff += ADJTIME_FIX; + ts = ns_to_timespec(diff); + tdr_write(0, tmp->phydev, &ts, PTP_STEP_CLK); + } + + /* + * restore status frames + */ + list_for_each(this, &clock->phylist) { + tmp = list_entry(this, struct dp83640_private, list); + ext_write(0, tmp->phydev, PAGE5, PSF_CFG0, tmp->cfg0); + } + ext_write(0, master, PAGE5, PSF_CFG0, cfg0); + + mutex_unlock(&clock->extreg_lock); +} + +/* time stamping methods */ + +static void decode_evnt(struct dp83640_private *dp83640, + struct phy_txts *phy_txts, u16 ests) +{ + struct ptp_clock_event event; + int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK; + + switch (words) { /* fall through in every case */ + case 3: + dp83640->edata.sec_hi = phy_txts->sec_hi; + case 2: + dp83640->edata.sec_lo = phy_txts->sec_lo; + case 1: + dp83640->edata.ns_hi = phy_txts->ns_hi; + case 0: + dp83640->edata.ns_lo = phy_txts->ns_lo; + } + + event.type = PTP_CLOCK_EXTTS; + event.index = 0; + event.timestamp = phy2txts(&dp83640->edata); + + ptp_clock_event(dp83640->clock->ptp_clock, &event); +} + +static void decode_rxts(struct dp83640_private *dp83640, + struct phy_rxts *phy_rxts) +{ + struct rxts *rxts; + unsigned long flags; + + spin_lock_irqsave(&dp83640->rx_lock, flags); + + prune_rx_ts(dp83640); + + if (list_empty(&dp83640->rxpool)) { + pr_warning("dp83640: rx timestamp pool is empty\n"); + goto out; + } + rxts = list_first_entry(&dp83640->rxpool, struct rxts, list); + list_del_init(&rxts->list); + phy2rxts(phy_rxts, rxts); + list_add_tail(&rxts->list, &dp83640->rxts); +out: + spin_unlock_irqrestore(&dp83640->rx_lock, flags); +} + +static void decode_txts(struct dp83640_private *dp83640, + struct phy_txts *phy_txts) +{ + struct skb_shared_hwtstamps shhwtstamps; + struct sk_buff *skb; + u64 ns; + + /* We must already have the skb that triggered this. */ + + skb = skb_dequeue(&dp83640->tx_queue); + + if (!skb) { + pr_warning("dp83640: have timestamp but tx_queue empty\n"); + return; + } + ns = phy2txts(phy_txts); + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); + shhwtstamps.hwtstamp = ns_to_ktime(ns); + skb_complete_tx_timestamp(skb, &shhwtstamps); +} + +static void decode_status_frame(struct dp83640_private *dp83640, + struct sk_buff *skb) +{ + struct phy_rxts *phy_rxts; + struct phy_txts *phy_txts; + u8 *ptr; + int len, size; + u16 ests, type; + + ptr = skb->data + 2; + + for (len = skb_headlen(skb) - 2; len > sizeof(type); len -= size) { + + type = *(u16 *)ptr; + ests = type & 0x0fff; + type = type & 0xf000; + len -= sizeof(type); + ptr += sizeof(type); + + if (PSF_RX == type && len >= sizeof(*phy_rxts)) { + + phy_rxts = (struct phy_rxts *) ptr; + decode_rxts(dp83640, phy_rxts); + size = sizeof(*phy_rxts); + + } else if (PSF_TX == type && len >= sizeof(*phy_txts)) { + + phy_txts = (struct phy_txts *) ptr; + decode_txts(dp83640, phy_txts); + size = sizeof(*phy_txts); + + } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) { + + phy_txts = (struct phy_txts *) ptr; + decode_evnt(dp83640, phy_txts, ests); + size = sizeof(*phy_txts); + + } else { + size = 0; + break; + } + ptr += size; + } +} + +static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) +{ + u16 *seqid; + unsigned int offset; + u8 *msgtype, *data = skb_mac_header(skb); + + /* check sequenceID, messageType, 12 bit hash of offset 20-29 */ + + switch (type) { + case PTP_CLASS_V1_IPV4: + case PTP_CLASS_V2_IPV4: + offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN; + break; + case PTP_CLASS_V1_IPV6: + case PTP_CLASS_V2_IPV6: + offset = OFF_PTP6; + break; + case PTP_CLASS_V2_L2: + offset = ETH_HLEN; + break; + case PTP_CLASS_V2_VLAN: + offset = ETH_HLEN + VLAN_HLEN; + break; + default: + return 0; + } + + if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid)) + return 0; + + if (unlikely(type & PTP_CLASS_V1)) + msgtype = data + offset + OFF_PTP_CONTROL; + else + msgtype = data + offset; + + seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID); + + return (rxts->msgtype == (*msgtype & 0xf) && + rxts->seqid == ntohs(*seqid)); +} + +static void dp83640_free_clocks(void) +{ + struct dp83640_clock *clock; + struct list_head *this, *next; + + mutex_lock(&phyter_clocks_lock); + + list_for_each_safe(this, next, &phyter_clocks) { + clock = list_entry(this, struct dp83640_clock, list); + if (!list_empty(&clock->phylist)) { + pr_warning("phy list non-empty while unloading"); + BUG(); + } + list_del(&clock->list); + mutex_destroy(&clock->extreg_lock); + mutex_destroy(&clock->clock_lock); + put_device(&clock->bus->dev); + kfree(clock); + } + + mutex_unlock(&phyter_clocks_lock); +} + +static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus) +{ + INIT_LIST_HEAD(&clock->list); + clock->bus = bus; + mutex_init(&clock->extreg_lock); + mutex_init(&clock->clock_lock); + INIT_LIST_HEAD(&clock->phylist); + clock->caps.owner = THIS_MODULE; + sprintf(clock->caps.name, "dp83640 timer"); + clock->caps.max_adj = 1953124; + clock->caps.n_alarm = 0; + clock->caps.n_ext_ts = N_EXT_TS; + clock->caps.n_per_out = 0; + clock->caps.pps = 0; + clock->caps.adjfreq = ptp_dp83640_adjfreq; + clock->caps.adjtime = ptp_dp83640_adjtime; + clock->caps.gettime = ptp_dp83640_gettime; + clock->caps.settime = ptp_dp83640_settime; + clock->caps.enable = ptp_dp83640_enable; + /* + * Get a reference to this bus instance. + */ + get_device(&bus->dev); +} + +static int choose_this_phy(struct dp83640_clock *clock, + struct phy_device *phydev) +{ + if (chosen_phy == -1 && !clock->chosen) + return 1; + + if (chosen_phy == phydev->addr) + return 1; + + return 0; +} + +static struct dp83640_clock *dp83640_clock_get(struct dp83640_clock *clock) +{ + if (clock) + mutex_lock(&clock->clock_lock); + return clock; +} + +/* + * Look up and lock a clock by bus instance. + * If there is no clock for this bus, then create it first. + */ +static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus) +{ + struct dp83640_clock *clock = NULL, *tmp; + struct list_head *this; + + mutex_lock(&phyter_clocks_lock); + + list_for_each(this, &phyter_clocks) { + tmp = list_entry(this, struct dp83640_clock, list); + if (tmp->bus == bus) { + clock = tmp; + break; + } + } + if (clock) + goto out; + + clock = kzalloc(sizeof(struct dp83640_clock), GFP_KERNEL); + if (!clock) + goto out; + + dp83640_clock_init(clock, bus); + list_add_tail(&phyter_clocks, &clock->list); +out: + mutex_unlock(&phyter_clocks_lock); + + return dp83640_clock_get(clock); +} + +static void dp83640_clock_put(struct dp83640_clock *clock) +{ + mutex_unlock(&clock->clock_lock); +} + +static int dp83640_probe(struct phy_device *phydev) +{ + struct dp83640_clock *clock; + struct dp83640_private *dp83640; + int err = -ENOMEM, i; + + if (phydev->addr == BROADCAST_ADDR) + return 0; + + clock = dp83640_clock_get_bus(phydev->bus); + if (!clock) + goto no_clock; + + dp83640 = kzalloc(sizeof(struct dp83640_private), GFP_KERNEL); + if (!dp83640) + goto no_memory; + + dp83640->phydev = phydev; + INIT_WORK(&dp83640->ts_work, rx_timestamp_work); + + INIT_LIST_HEAD(&dp83640->rxts); + INIT_LIST_HEAD(&dp83640->rxpool); + for (i = 0; i < MAX_RXTS; i++) + list_add(&dp83640->rx_pool_data[i].list, &dp83640->rxpool); + + phydev->priv = dp83640; + + spin_lock_init(&dp83640->rx_lock); + skb_queue_head_init(&dp83640->rx_queue); + skb_queue_head_init(&dp83640->tx_queue); + + dp83640->clock = clock; + + if (choose_this_phy(clock, phydev)) { + clock->chosen = dp83640; + clock->ptp_clock = ptp_clock_register(&clock->caps); + if (IS_ERR(clock->ptp_clock)) { + err = PTR_ERR(clock->ptp_clock); + goto no_register; + } + } else + list_add_tail(&dp83640->list, &clock->phylist); + + if (clock->chosen && !list_empty(&clock->phylist)) + recalibrate(clock); + else + enable_broadcast(dp83640->phydev, clock->page, 1); + + dp83640_clock_put(clock); + return 0; + +no_register: + clock->chosen = NULL; + kfree(dp83640); +no_memory: + dp83640_clock_put(clock); +no_clock: + return err; +} + +static void dp83640_remove(struct phy_device *phydev) +{ + struct dp83640_clock *clock; + struct list_head *this, *next; + struct dp83640_private *tmp, *dp83640 = phydev->priv; + + if (phydev->addr == BROADCAST_ADDR) + return; + + enable_status_frames(phydev, false); + cancel_work_sync(&dp83640->ts_work); + + clock = dp83640_clock_get(dp83640->clock); + + if (dp83640 == clock->chosen) { + ptp_clock_unregister(clock->ptp_clock); + clock->chosen = NULL; + } else { + list_for_each_safe(this, next, &clock->phylist) { + tmp = list_entry(this, struct dp83640_private, list); + if (tmp == dp83640) { + list_del_init(&tmp->list); + break; + } + } + } + + dp83640_clock_put(clock); + kfree(dp83640); +} + +static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) +{ + struct dp83640_private *dp83640 = phydev->priv; + struct hwtstamp_config cfg; + u16 txcfg0, rxcfg0; + + if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) + return -EFAULT; + + if (cfg.flags) /* reserved for future extensions */ + return -EINVAL; + + switch (cfg.tx_type) { + case HWTSTAMP_TX_OFF: + dp83640->hwts_tx_en = 0; + break; + case HWTSTAMP_TX_ON: + dp83640->hwts_tx_en = 1; + break; + default: + return -ERANGE; + } + + switch (cfg.rx_filter) { + case HWTSTAMP_FILTER_NONE: + dp83640->hwts_rx_en = 0; + dp83640->layer = 0; + dp83640->version = 0; + break; + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + dp83640->hwts_rx_en = 1; + dp83640->layer = LAYER4; + dp83640->version = 1; + break; + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + dp83640->hwts_rx_en = 1; + dp83640->layer = LAYER4; + dp83640->version = 2; + break; + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + dp83640->hwts_rx_en = 1; + dp83640->layer = LAYER2; + dp83640->version = 2; + break; + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + dp83640->hwts_rx_en = 1; + dp83640->layer = LAYER4|LAYER2; + dp83640->version = 2; + break; + default: + return -ERANGE; + } + + txcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT; + rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT; + + if (dp83640->layer & LAYER2) { + txcfg0 |= TX_L2_EN; + rxcfg0 |= RX_L2_EN; + } + if (dp83640->layer & LAYER4) { + txcfg0 |= TX_IPV6_EN | TX_IPV4_EN; + rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN; + } + + if (dp83640->hwts_tx_en) + txcfg0 |= TX_TS_EN; + + if (dp83640->hwts_rx_en) + rxcfg0 |= RX_TS_EN; + + mutex_lock(&dp83640->clock->extreg_lock); + + if (dp83640->hwts_tx_en || dp83640->hwts_rx_en) { + enable_status_frames(phydev, true); + ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); + } + + ext_write(0, phydev, PAGE5, PTP_TXCFG0, txcfg0); + ext_write(0, phydev, PAGE5, PTP_RXCFG0, rxcfg0); + + mutex_unlock(&dp83640->clock->extreg_lock); + + return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; +} + +static void rx_timestamp_work(struct work_struct *work) +{ + struct dp83640_private *dp83640 = + container_of(work, struct dp83640_private, ts_work); + struct list_head *this, *next; + struct rxts *rxts; + struct skb_shared_hwtstamps *shhwtstamps; + struct sk_buff *skb; + unsigned int type; + unsigned long flags; + + /* Deliver each deferred packet, with or without a time stamp. */ + + while ((skb = skb_dequeue(&dp83640->rx_queue)) != NULL) { + type = SKB_PTP_TYPE(skb); + spin_lock_irqsave(&dp83640->rx_lock, flags); + list_for_each_safe(this, next, &dp83640->rxts) { + rxts = list_entry(this, struct rxts, list); + if (match(skb, type, rxts)) { + shhwtstamps = skb_hwtstamps(skb); + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); + shhwtstamps->hwtstamp = ns_to_ktime(rxts->ns); + list_del_init(&rxts->list); + list_add(&rxts->list, &dp83640->rxpool); + break; + } + } + spin_unlock_irqrestore(&dp83640->rx_lock, flags); + netif_rx(skb); + } + + /* Clear out expired time stamps. */ + + spin_lock_irqsave(&dp83640->rx_lock, flags); + prune_rx_ts(dp83640); + spin_unlock_irqrestore(&dp83640->rx_lock, flags); +} + +static bool dp83640_rxtstamp(struct phy_device *phydev, + struct sk_buff *skb, int type) +{ + struct dp83640_private *dp83640 = phydev->priv; + + if (!dp83640->hwts_rx_en) + return false; + + if (is_status_frame(skb, type)) { + decode_status_frame(dp83640, skb); + /* Let the stack drop this frame. */ + return false; + } + + SKB_PTP_TYPE(skb) = type; + skb_queue_tail(&dp83640->rx_queue, skb); + schedule_work(&dp83640->ts_work); + + return true; +} + +static void dp83640_txtstamp(struct phy_device *phydev, + struct sk_buff *skb, int type) +{ + struct dp83640_private *dp83640 = phydev->priv; + + if (!dp83640->hwts_tx_en) { + kfree_skb(skb); + return; + } + skb_queue_tail(&dp83640->tx_queue, skb); + schedule_work(&dp83640->ts_work); +} + +static struct phy_driver dp83640_driver = { + .phy_id = DP83640_PHY_ID, + .phy_id_mask = 0xfffffff0, + .name = "NatSemi DP83640", + .features = PHY_BASIC_FEATURES, + .flags = 0, + .probe = dp83640_probe, + .remove = dp83640_remove, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .hwtstamp = dp83640_hwtstamp, + .rxtstamp = dp83640_rxtstamp, + .txtstamp = dp83640_txtstamp, + .driver = {.owner = THIS_MODULE,} +}; + +static int __init dp83640_init(void) +{ + return phy_driver_register(&dp83640_driver); +} + +static void __exit dp83640_exit(void) +{ + dp83640_free_clocks(); + phy_driver_unregister(&dp83640_driver); +} + +MODULE_DESCRIPTION("National Semiconductor DP83640 PHY driver"); +MODULE_AUTHOR("Richard Cochran <richard.cochran@omicron.at>"); +MODULE_LICENSE("GPL"); + +module_init(dp83640_init); +module_exit(dp83640_exit); + +static struct mdio_device_id __maybe_unused dp83640_tbl[] = { + { DP83640_PHY_ID, 0xfffffff0 }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, dp83640_tbl); diff --git a/drivers/net/phy/dp83640_reg.h b/drivers/net/phy/dp83640_reg.h new file mode 100644 index 0000000..e7fe411 --- /dev/null +++ b/drivers/net/phy/dp83640_reg.h @@ -0,0 +1,267 @@ +/* dp83640_reg.h + * Generated by regen.tcl on Thu Feb 17 10:02:48 AM CET 2011 + */ +#ifndef HAVE_DP83640_REGISTERS +#define HAVE_DP83640_REGISTERS + +#define PAGE0 0x0000 +#define PHYCR2 0x001c /* PHY Control Register 2 */ + +#define PAGE4 0x0004 +#define PTP_CTL 0x0014 /* PTP Control Register */ +#define PTP_TDR 0x0015 /* PTP Time Data Register */ +#define PTP_STS 0x0016 /* PTP Status Register */ +#define PTP_TSTS 0x0017 /* PTP Trigger Status Register */ +#define PTP_RATEL 0x0018 /* PTP Rate Low Register */ +#define PTP_RATEH 0x0019 /* PTP Rate High Register */ +#define PTP_RDCKSUM 0x001a /* PTP Read Checksum */ +#define PTP_WRCKSUM 0x001b /* PTP Write Checksum */ +#define PTP_TXTS 0x001c /* PTP Transmit Timestamp Register, in four 16-bit reads */ +#define PTP_RXTS 0x001d /* PTP Receive Timestamp Register, in six? 16-bit reads */ +#define PTP_ESTS 0x001e /* PTP Event Status Register */ +#define PTP_EDATA 0x001f /* PTP Event Data Register */ + +#define PAGE5 0x0005 +#define PTP_TRIG 0x0014 /* PTP Trigger Configuration Register */ +#define PTP_EVNT 0x0015 /* PTP Event Configuration Register */ +#define PTP_TXCFG0 0x0016 /* PTP Transmit Configuration Register 0 */ +#define PTP_TXCFG1 0x0017 /* PTP Transmit Configuration Register 1 */ +#define PSF_CFG0 0x0018 /* PHY Status Frame Configuration Register 0 */ +#define PTP_RXCFG0 0x0019 /* PTP Receive Configuration Register 0 */ +#define PTP_RXCFG1 0x001a /* PTP Receive Configuration Register 1 */ +#define PTP_RXCFG2 0x001b /* PTP Receive Configuration Register 2 */ +#define PTP_RXCFG3 0x001c /* PTP Receive Configuration Register 3 */ +#define PTP_RXCFG4 0x001d /* PTP Receive Configuration Register 4 */ +#define PTP_TRDL 0x001e /* PTP Temporary Rate Duration Low Register */ +#define PTP_TRDH 0x001f /* PTP Temporary Rate Duration High Register */ + +#define PAGE6 0x0006 +#define PTP_COC 0x0014 /* PTP Clock Output Control Register */ +#define PSF_CFG1 0x0015 /* PHY Status Frame Configuration Register 1 */ +#define PSF_CFG2 0x0016 /* PHY Status Frame Configuration Register 2 */ +#define PSF_CFG3 0x0017 /* PHY Status Frame Configuration Register 3 */ +#define PSF_CFG4 0x0018 /* PHY Status Frame Configuration Register 4 */ +#define PTP_SFDCFG 0x0019 /* PTP SFD Configuration Register */ +#define PTP_INTCTL 0x001a /* PTP Interrupt Control Register */ +#define PTP_CLKSRC 0x001b /* PTP Clock Source Register */ +#define PTP_ETR 0x001c /* PTP Ethernet Type Register */ +#define PTP_OFF 0x001d /* PTP Offset Register */ +#define PTP_GPIOMON 0x001e /* PTP GPIO Monitor Register */ +#define PTP_RXHASH 0x001f /* PTP Receive Hash Register */ + +/* Bit definitions for the PHYCR2 register */ +#define BC_WRITE (1<<11) /* Broadcast Write Enable */ + +/* Bit definitions for the PTP_CTL register */ +#define TRIG_SEL_SHIFT (10) /* PTP Trigger Select */ +#define TRIG_SEL_MASK (0x7) +#define TRIG_DIS (1<<9) /* Disable PTP Trigger */ +#define TRIG_EN (1<<8) /* Enable PTP Trigger */ +#define TRIG_READ (1<<7) /* Read PTP Trigger */ +#define TRIG_LOAD (1<<6) /* Load PTP Trigger */ +#define PTP_RD_CLK (1<<5) /* Read PTP Clock */ +#define PTP_LOAD_CLK (1<<4) /* Load PTP Clock */ +#define PTP_STEP_CLK (1<<3) /* Step PTP Clock */ +#define PTP_ENABLE (1<<2) /* Enable PTP Clock */ +#define PTP_DISABLE (1<<1) /* Disable PTP Clock */ +#define PTP_RESET (1<<0) /* Reset PTP Clock */ + +/* Bit definitions for the PTP_STS register */ +#define TXTS_RDY (1<<11) /* Transmit Timestamp Ready */ +#define RXTS_RDY (1<<10) /* Receive Timestamp Ready */ +#define TRIG_DONE (1<<9) /* PTP Trigger Done */ +#define EVENT_RDY (1<<8) /* PTP Event Timestamp Ready */ +#define TXTS_IE (1<<3) /* Transmit Timestamp Interrupt Enable */ +#define RXTS_IE (1<<2) /* Receive Timestamp Interrupt Enable */ +#define TRIG_IE (1<<1) /* Trigger Interrupt Enable */ +#define EVENT_IE (1<<0) /* Event Interrupt Enable */ + +/* Bit definitions for the PTP_TSTS register */ +#define TRIG7_ERROR (1<<15) /* Trigger 7 Error */ +#define TRIG7_ACTIVE (1<<14) /* Trigger 7 Active */ +#define TRIG6_ERROR (1<<13) /* Trigger 6 Error */ +#define TRIG6_ACTIVE (1<<12) /* Trigger 6 Active */ +#define TRIG5_ERROR (1<<11) /* Trigger 5 Error */ +#define TRIG5_ACTIVE (1<<10) /* Trigger 5 Active */ +#define TRIG4_ERROR (1<<9) /* Trigger 4 Error */ +#define TRIG4_ACTIVE (1<<8) /* Trigger 4 Active */ +#define TRIG3_ERROR (1<<7) /* Trigger 3 Error */ +#define TRIG3_ACTIVE (1<<6) /* Trigger 3 Active */ +#define TRIG2_ERROR (1<<5) /* Trigger 2 Error */ +#define TRIG2_ACTIVE (1<<4) /* Trigger 2 Active */ +#define TRIG1_ERROR (1<<3) /* Trigger 1 Error */ +#define TRIG1_ACTIVE (1<<2) /* Trigger 1 Active */ +#define TRIG0_ERROR (1<<1) /* Trigger 0 Error */ +#define TRIG0_ACTIVE (1<<0) /* Trigger 0 Active */ + +/* Bit definitions for the PTP_RATEH register */ +#define PTP_RATE_DIR (1<<15) /* PTP Rate Direction */ +#define PTP_TMP_RATE (1<<14) /* PTP Temporary Rate */ +#define PTP_RATE_HI_SHIFT (0) /* PTP Rate High 10-bits */ +#define PTP_RATE_HI_MASK (0x3ff) + +/* Bit definitions for the PTP_ESTS register */ +#define EVNTS_MISSED_SHIFT (8) /* Indicates number of events missed */ +#define EVNTS_MISSED_MASK (0x7) +#define EVNT_TS_LEN_SHIFT (6) /* Indicates length of the Timestamp field in 16-bit words minus 1 */ +#define EVNT_TS_LEN_MASK (0x3) +#define EVNT_RF (1<<5) /* Indicates whether the event is a rise or falling event */ +#define EVNT_NUM_SHIFT (2) /* Indicates Event Timestamp Unit which detected an event */ +#define EVNT_NUM_MASK (0x7) +#define MULT_EVNT (1<<1) /* Indicates multiple events were detected at the same time */ +#define EVENT_DET (1<<0) /* PTP Event Detected */ + +/* Bit definitions for the PTP_EDATA register */ +#define E7_RISE (1<<15) /* Indicates direction of Event 7 */ +#define E7_DET (1<<14) /* Indicates Event 7 detected */ +#define E6_RISE (1<<13) /* Indicates direction of Event 6 */ +#define E6_DET (1<<12) /* Indicates Event 6 detected */ +#define E5_RISE (1<<11) /* Indicates direction of Event 5 */ +#define E5_DET (1<<10) /* Indicates Event 5 detected */ +#define E4_RISE (1<<9) /* Indicates direction of Event 4 */ +#define E4_DET (1<<8) /* Indicates Event 4 detected */ +#define E3_RISE (1<<7) /* Indicates direction of Event 3 */ +#define E3_DET (1<<6) /* Indicates Event 3 detected */ +#define E2_RISE (1<<5) /* Indicates direction of Event 2 */ +#define E2_DET (1<<4) /* Indicates Event 2 detected */ +#define E1_RISE (1<<3) /* Indicates direction of Event 1 */ +#define E1_DET (1<<2) /* Indicates Event 1 detected */ +#define E0_RISE (1<<1) /* Indicates direction of Event 0 */ +#define E0_DET (1<<0) /* Indicates Event 0 detected */ + +/* Bit definitions for the PTP_TRIG register */ +#define TRIG_PULSE (1<<15) /* generate a Pulse rather than a single edge */ +#define TRIG_PER (1<<14) /* generate a periodic signal */ +#define TRIG_IF_LATE (1<<13) /* trigger immediately if already past */ +#define TRIG_NOTIFY (1<<12) /* Trigger Notification Enable */ +#define TRIG_GPIO_SHIFT (8) /* Trigger GPIO Connection, value 1-12 */ +#define TRIG_GPIO_MASK (0xf) +#define TRIG_TOGGLE (1<<7) /* Trigger Toggle Mode Enable */ +#define TRIG_CSEL_SHIFT (1) /* Trigger Configuration Select */ +#define TRIG_CSEL_MASK (0x7) +#define TRIG_WR (1<<0) /* Trigger Configuration Write */ + +/* Bit definitions for the PTP_EVNT register */ +#define EVNT_RISE (1<<14) /* Event Rise Detect Enable */ +#define EVNT_FALL (1<<13) /* Event Fall Detect Enable */ +#define EVNT_SINGLE (1<<12) /* enable single event capture operation */ +#define EVNT_GPIO_SHIFT (8) /* Event GPIO Connection, value 1-12 */ +#define EVNT_GPIO_MASK (0xf) +#define EVNT_SEL_SHIFT (1) /* Event Select */ +#define EVNT_SEL_MASK (0x7) +#define EVNT_WR (1<<0) /* Event Configuration Write */ + +/* Bit definitions for the PTP_TXCFG0 register */ +#define SYNC_1STEP (1<<15) /* insert timestamp into transmit Sync Messages */ +#define DR_INSERT (1<<13) /* Insert Delay_Req Timestamp in Delay_Resp (dangerous) */ +#define NTP_TS_EN (1<<12) /* Enable Timestamping of NTP Packets */ +#define IGNORE_2STEP (1<<11) /* Ignore Two_Step flag for One-Step operation */ +#define CRC_1STEP (1<<10) /* Disable checking of CRC for One-Step operation */ +#define CHK_1STEP (1<<9) /* Enable UDP Checksum correction for One-Step Operation */ +#define IP1588_EN (1<<8) /* Enable IEEE 1588 defined IP address filter */ +#define TX_L2_EN (1<<7) /* Layer2 Timestamp Enable */ +#define TX_IPV6_EN (1<<6) /* IPv6 Timestamp Enable */ +#define TX_IPV4_EN (1<<5) /* IPv4 Timestamp Enable */ +#define TX_PTP_VER_SHIFT (1) /* Enable Timestamp capture for IEEE 1588 version X */ +#define TX_PTP_VER_MASK (0xf) +#define TX_TS_EN (1<<0) /* Transmit Timestamp Enable */ + +/* Bit definitions for the PTP_TXCFG1 register */ +#define BYTE0_MASK_SHIFT (8) /* Bit mask to be used for matching Byte0 of the PTP Message */ +#define BYTE0_MASK_MASK (0xff) +#define BYTE0_DATA_SHIFT (0) /* Data to be used for matching Byte0 of the PTP Message */ +#define BYTE0_DATA_MASK (0xff) + +/* Bit definitions for the PSF_CFG0 register */ +#define MAC_SRC_ADD_SHIFT (11) /* Status Frame Mac Source Address */ +#define MAC_SRC_ADD_MASK (0x3) +#define MIN_PRE_SHIFT (8) /* Status Frame Minimum Preamble */ +#define MIN_PRE_MASK (0x7) +#define PSF_ENDIAN (1<<7) /* Status Frame Endian Control */ +#define PSF_IPV4 (1<<6) /* Status Frame IPv4 Enable */ +#define PSF_PCF_RD (1<<5) /* Control Frame Read PHY Status Frame Enable */ +#define PSF_ERR_EN (1<<4) /* Error PHY Status Frame Enable */ +#define PSF_TXTS_EN (1<<3) /* Transmit Timestamp PHY Status Frame Enable */ +#define PSF_RXTS_EN (1<<2) /* Receive Timestamp PHY Status Frame Enable */ +#define PSF_TRIG_EN (1<<1) /* Trigger PHY Status Frame Enable */ +#define PSF_EVNT_EN (1<<0) /* Event PHY Status Frame Enable */ + +/* Bit definitions for the PTP_RXCFG0 register */ +#define DOMAIN_EN (1<<15) /* Domain Match Enable */ +#define ALT_MAST_DIS (1<<14) /* Alternate Master Timestamp Disable */ +#define USER_IP_SEL (1<<13) /* Selects portion of IP address accessible thru PTP_RXCFG2 */ +#define USER_IP_EN (1<<12) /* Enable User-programmed IP address filter */ +#define RX_SLAVE (1<<11) /* Receive Slave Only */ +#define IP1588_EN_SHIFT (8) /* Enable IEEE 1588 defined IP address filters */ +#define IP1588_EN_MASK (0xf) +#define RX_L2_EN (1<<7) /* Layer2 Timestamp Enable */ +#define RX_IPV6_EN (1<<6) /* IPv6 Timestamp Enable */ +#define RX_IPV4_EN (1<<5) /* IPv4 Timestamp Enable */ +#define RX_PTP_VER_SHIFT (1) /* Enable Timestamp capture for IEEE 1588 version X */ +#define RX_PTP_VER_MASK (0xf) +#define RX_TS_EN (1<<0) /* Receive Timestamp Enable */ + +/* Bit definitions for the PTP_RXCFG1 register */ +#define BYTE0_MASK_SHIFT (8) /* Bit mask to be used for matching Byte0 of the PTP Message */ +#define BYTE0_MASK_MASK (0xff) +#define BYTE0_DATA_SHIFT (0) /* Data to be used for matching Byte0 of the PTP Message */ +#define BYTE0_DATA_MASK (0xff) + +/* Bit definitions for the PTP_RXCFG3 register */ +#define TS_MIN_IFG_SHIFT (12) /* Minimum Inter-frame Gap */ +#define TS_MIN_IFG_MASK (0xf) +#define ACC_UDP (1<<11) /* Record Timestamp if UDP Checksum Error */ +#define ACC_CRC (1<<10) /* Record Timestamp if CRC Error */ +#define TS_APPEND (1<<9) /* Append Timestamp for L2 */ +#define TS_INSERT (1<<8) /* Enable Timestamp Insertion */ +#define PTP_DOMAIN_SHIFT (0) /* PTP Message domainNumber field */ +#define PTP_DOMAIN_MASK (0xff) + +/* Bit definitions for the PTP_RXCFG4 register */ +#define IPV4_UDP_MOD (1<<15) /* Enable IPV4 UDP Modification */ +#define TS_SEC_EN (1<<14) /* Enable Timestamp Seconds */ +#define TS_SEC_LEN_SHIFT (12) /* Inserted Timestamp Seconds Length */ +#define TS_SEC_LEN_MASK (0x3) +#define RXTS_NS_OFF_SHIFT (6) /* Receive Timestamp Nanoseconds offset */ +#define RXTS_NS_OFF_MASK (0x3f) +#define RXTS_SEC_OFF_SHIFT (0) /* Receive Timestamp Seconds offset */ +#define RXTS_SEC_OFF_MASK (0x3f) + +/* Bit definitions for the PTP_COC register */ +#define PTP_CLKOUT_EN (1<<15) /* PTP Clock Output Enable */ +#define PTP_CLKOUT_SEL (1<<14) /* PTP Clock Output Source Select */ +#define PTP_CLKOUT_SPEEDSEL (1<<13) /* PTP Clock Output I/O Speed Select */ +#define PTP_CLKDIV_SHIFT (0) /* PTP Clock Divide-by Value */ +#define PTP_CLKDIV_MASK (0xff) + +/* Bit definitions for the PSF_CFG1 register */ +#define PTPRESERVED_SHIFT (12) /* PTP v2 reserved field */ +#define PTPRESERVED_MASK (0xf) +#define VERSIONPTP_SHIFT (8) /* PTP v2 versionPTP field */ +#define VERSIONPTP_MASK (0xf) +#define TRANSPORT_SPECIFIC_SHIFT (4) /* PTP v2 Header transportSpecific field */ +#define TRANSPORT_SPECIFIC_MASK (0xf) +#define MESSAGETYPE_SHIFT (0) /* PTP v2 messageType field */ +#define MESSAGETYPE_MASK (0xf) + +/* Bit definitions for the PTP_SFDCFG register */ +#define TX_SFD_GPIO_SHIFT (4) /* TX SFD GPIO Select, value 1-12 */ +#define TX_SFD_GPIO_MASK (0xf) +#define RX_SFD_GPIO_SHIFT (0) /* RX SFD GPIO Select, value 1-12 */ +#define RX_SFD_GPIO_MASK (0xf) + +/* Bit definitions for the PTP_INTCTL register */ +#define PTP_INT_GPIO_SHIFT (0) /* PTP Interrupt GPIO Select */ +#define PTP_INT_GPIO_MASK (0xf) + +/* Bit definitions for the PTP_CLKSRC register */ +#define CLK_SRC_SHIFT (14) /* PTP Clock Source Select */ +#define CLK_SRC_MASK (0x3) +#define CLK_SRC_PER_SHIFT (0) /* PTP Clock Source Period */ +#define CLK_SRC_PER_MASK (0x7f) + +/* Bit definitions for the PTP_OFF register */ +#define PTP_OFFSET_SHIFT (0) /* PTP Message offset from preceding header */ +#define PTP_OFFSET_MASK (0xff) + +#endif diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index db19332..f4b01c6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -292,6 +292,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)}, {PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)}, + {PCI_DEVICE(0x10cf, 0x11a2)}, /* Fujitsu 1000base-SX with BCM5703SKHB */ {} }; diff --git a/drivers/net/tile/tilepro.c b/drivers/net/tile/tilepro.c index 1e980fd..1e2af96 100644 --- a/drivers/net/tile/tilepro.c +++ b/drivers/net/tile/tilepro.c @@ -1658,11 +1658,9 @@ static int tile_net_stop(struct net_device *dev) while (tile_net_lepp_free_comps(dev, true)) /* loop */; - /* Wipe the EPP queue. */ + /* Wipe the EPP queue, and wait till the stores hit the EPP. */ memset(priv->eq, 0, sizeof(lepp_queue_t)); - - /* Evict the EPP queue. */ - finv_buffer(priv->eq, EQ_SIZE); + mb(); return 0; } @@ -2398,7 +2396,7 @@ static void tile_net_cleanup(void) struct net_device *dev = tile_net_devs[i]; struct tile_net_priv *priv = netdev_priv(dev); unregister_netdev(dev); - finv_buffer(priv->eq, EQ_SIZE); + finv_buffer_remote(priv->eq, EQ_SIZE, 0); __free_pages(priv->eq_pages, EQ_ORDER); free_netdev(dev); } diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4ab557d..cdd3ae4 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -54,7 +54,7 @@ #include <linux/usb/usbnet.h> #include <linux/usb/cdc.h> -#define DRIVER_VERSION "06-May-2011" +#define DRIVER_VERSION "24-May-2011" /* CDC NCM subclass 3.2.1 */ #define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10 @@ -134,8 +134,6 @@ struct cdc_ncm_ctx { u16 tx_ndp_modulus; u16 tx_seq; u16 connected; - u8 data_claimed; - u8 control_claimed; }; static void cdc_ncm_tx_timeout(unsigned long arg); @@ -460,17 +458,6 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx) del_timer_sync(&ctx->tx_timer); - if (ctx->data_claimed) { - usb_set_intfdata(ctx->data, NULL); - usb_driver_release_interface(driver_of(ctx->intf), ctx->data); - } - - if (ctx->control_claimed) { - usb_set_intfdata(ctx->control, NULL); - usb_driver_release_interface(driver_of(ctx->intf), - ctx->control); - } - if (ctx->tx_rem_skb != NULL) { dev_kfree_skb_any(ctx->tx_rem_skb); ctx->tx_rem_skb = NULL; @@ -495,7 +482,7 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (ctx == NULL) - goto error; + return -ENODEV; memset(ctx, 0, sizeof(*ctx)); @@ -568,46 +555,36 @@ advance: /* check if we got everything */ if ((ctx->control == NULL) || (ctx->data == NULL) || - (ctx->ether_desc == NULL)) + (ctx->ether_desc == NULL) || (ctx->control != intf)) goto error; /* claim interfaces, if any */ - if (ctx->data != intf) { - temp = usb_driver_claim_interface(driver, ctx->data, dev); - if (temp) - goto error; - ctx->data_claimed = 1; - } - - if (ctx->control != intf) { - temp = usb_driver_claim_interface(driver, ctx->control, dev); - if (temp) - goto error; - ctx->control_claimed = 1; - } + temp = usb_driver_claim_interface(driver, ctx->data, dev); + if (temp) + goto error; iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; /* reset data interface */ temp = usb_set_interface(dev->udev, iface_no, 0); if (temp) - goto error; + goto error2; /* initialize data interface */ if (cdc_ncm_setup(ctx)) - goto error; + goto error2; /* configure data interface */ temp = usb_set_interface(dev->udev, iface_no, 1); if (temp) - goto error; + goto error2; cdc_ncm_find_endpoints(ctx, ctx->data); cdc_ncm_find_endpoints(ctx, ctx->control); if ((ctx->in_ep == NULL) || (ctx->out_ep == NULL) || (ctx->status_ep == NULL)) - goto error; + goto error2; dev->net->ethtool_ops = &cdc_ncm_ethtool_ops; @@ -617,7 +594,7 @@ advance: temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress); if (temp) - goto error; + goto error2; dev_info(&dev->udev->dev, "MAC-Address: " "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", @@ -642,38 +619,38 @@ advance: ctx->tx_speed = ctx->rx_speed = 0; return 0; +error2: + usb_set_intfdata(ctx->control, NULL); + usb_set_intfdata(ctx->data, NULL); + usb_driver_release_interface(driver, ctx->data); error: cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]); dev->data[0] = 0; - dev_info(&dev->udev->dev, "Descriptor failure\n"); + dev_info(&dev->udev->dev, "bind() failure\n"); return -ENODEV; } static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf) { struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; - struct usb_driver *driver; + struct usb_driver *driver = driver_of(intf); if (ctx == NULL) return; /* no setup */ - driver = driver_of(intf); - - usb_set_intfdata(ctx->data, NULL); - usb_set_intfdata(ctx->control, NULL); - usb_set_intfdata(ctx->intf, NULL); - - /* release interfaces, if any */ - if (ctx->data_claimed) { + /* disconnect master --> disconnect slave */ + if (intf == ctx->control && ctx->data) { + usb_set_intfdata(ctx->data, NULL); usb_driver_release_interface(driver, ctx->data); - ctx->data_claimed = 0; - } + ctx->data = NULL; - if (ctx->control_claimed) { + } else if (intf == ctx->data && ctx->control) { + usb_set_intfdata(ctx->control, NULL); usb_driver_release_interface(driver, ctx->control); - ctx->control_claimed = 0; + ctx->control = NULL; } + usb_set_intfdata(ctx->intf, NULL); cdc_ncm_free(ctx); } diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h index d722753..0f1f05f 100644 --- a/drivers/net/via-velocity.h +++ b/drivers/net/via-velocity.h @@ -1096,7 +1096,7 @@ struct mac_regs { volatile __le16 PatternCRC[8]; /* 0xB0 */ volatile __le32 ByteMask[4][4]; /* 0xC0 */ -} __packed; +}; enum hw_mib { diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index a70c512..55cf71f 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -4501,17 +4501,15 @@ static int setup_proc_entry( struct net_device *dev, struct proc_dir_entry *entry; /* First setup the device directory */ strcpy(apriv->proc_name,dev->name); - apriv->proc_entry = create_proc_entry(apriv->proc_name, - S_IFDIR|airo_perm, - airo_entry); + apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm, + airo_entry); if (!apriv->proc_entry) goto fail; apriv->proc_entry->uid = proc_uid; apriv->proc_entry->gid = proc_gid; /* Setup the StatsDelta */ - entry = proc_create_data("StatsDelta", - S_IFREG | (S_IRUGO&proc_perm), + entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm, apriv->proc_entry, &proc_statsdelta_ops, dev); if (!entry) goto fail_stats_delta; @@ -4519,8 +4517,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the Stats */ - entry = proc_create_data("Stats", - S_IFREG | (S_IRUGO&proc_perm), + entry = proc_create_data("Stats", S_IRUGO & proc_perm, apriv->proc_entry, &proc_stats_ops, dev); if (!entry) goto fail_stats; @@ -4528,8 +4525,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the Status */ - entry = proc_create_data("Status", - S_IFREG | (S_IRUGO&proc_perm), + entry = proc_create_data("Status", S_IRUGO & proc_perm, apriv->proc_entry, &proc_status_ops, dev); if (!entry) goto fail_status; @@ -4537,8 +4533,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the Config */ - entry = proc_create_data("Config", - S_IFREG | proc_perm, + entry = proc_create_data("Config", proc_perm, apriv->proc_entry, &proc_config_ops, dev); if (!entry) goto fail_config; @@ -4546,8 +4541,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the SSID */ - entry = proc_create_data("SSID", - S_IFREG | proc_perm, + entry = proc_create_data("SSID", proc_perm, apriv->proc_entry, &proc_SSID_ops, dev); if (!entry) goto fail_ssid; @@ -4555,8 +4549,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the APList */ - entry = proc_create_data("APList", - S_IFREG | proc_perm, + entry = proc_create_data("APList", proc_perm, apriv->proc_entry, &proc_APList_ops, dev); if (!entry) goto fail_aplist; @@ -4564,8 +4557,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the BSSList */ - entry = proc_create_data("BSSList", - S_IFREG | proc_perm, + entry = proc_create_data("BSSList", proc_perm, apriv->proc_entry, &proc_BSSList_ops, dev); if (!entry) goto fail_bsslist; @@ -4573,8 +4565,7 @@ static int setup_proc_entry( struct net_device *dev, entry->gid = proc_gid; /* Setup the WepKey */ - entry = proc_create_data("WepKey", - S_IFREG | proc_perm, + entry = proc_create_data("WepKey", proc_perm, apriv->proc_entry, &proc_wepkey_ops, dev); if (!entry) goto fail_wepkey; @@ -5706,9 +5697,7 @@ static int __init airo_init_module( void ) { int i; - airo_entry = create_proc_entry("driver/aironet", - S_IFDIR | airo_perm, - NULL); + airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL); if (airo_entry) { airo_entry->uid = proc_uid; diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index df2484d..c983c10 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -164,7 +164,7 @@ static int airo_resume(struct pcmcia_device *link) return 0; } -static struct pcmcia_device_id airo_ids[] = { +static const struct pcmcia_device_id airo_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a), PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005), PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007), diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 6195639..5b49cd0 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> * diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 5a1f4f5..bfb6481 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 0cd6783..dbab5b9 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h index 36f7d06..234617c 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 4bf9dab..441bb33 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h index 69a94c7..6d2e2f3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index cb611b2..015d974 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index f44c84a..f344cc2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index 6203eed..7573257 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 7a332f1..077e8a6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index a57e963..2fe0a34 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 47780ef..453af6d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index f915a3d..e8ac70d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index f276cb9..f48051c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index d985841..0ca7635 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index afb0b5e..ab21a49 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #ifndef AR9003_EEPROM_H #define AR9003_EEPROM_H diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index a55eddb..392bf0f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index be6adec..10d71f7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 45cc7e8..c504493 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 356d2fd7..e4d6a87 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 25f3c2f..eee23ec 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index c7505b4..443090d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2010 Atheros Communications, Inc. + * Copyright (c) 2010-2011 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index fbdde29..611ea6c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 03b37d7..f75068b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -397,6 +397,9 @@ struct ath_beacon { struct ath_descdma bdma; struct ath_txq *cabq; struct list_head bbuf; + + bool tx_processed; + bool tx_last; }; void ath_beacon_tasklet(unsigned long data); diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 637dbc5..d4d8cec 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,6 +18,12 @@ #define FUDGE 2 +static void ath9k_reset_beacon_status(struct ath_softc *sc) +{ + sc->beacon.tx_processed = false; + sc->beacon.tx_last = false; +} + /* * This function will modify certain transmit queue properties depending on * the operating mode of the station (AP or AdHoc). Parameters are AIFS @@ -72,6 +78,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ieee80211_supported_band *sband; u8 rate = 0; + ath9k_reset_beacon_status(sc); + ds = bf->bf_desc; flags = ATH9K_TXDESC_NOACK; @@ -134,6 +142,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, struct ieee80211_tx_info *info; int cabq_depth; + ath9k_reset_beacon_status(sc); + avp = (void *)vif->drv_priv; cabq = sc->beacon.cabq; @@ -351,9 +361,7 @@ void ath_beacon_tasklet(unsigned long data) struct ath_buf *bf = NULL; struct ieee80211_vif *vif; int slot; - u32 bfaddr, bc = 0, tsftu; - u64 tsf; - u16 intval; + u32 bfaddr, bc = 0; /* * Check if the previous beacon has gone out. If @@ -388,17 +396,27 @@ void ath_beacon_tasklet(unsigned long data) * on the tsf to safeguard against missing an swba. */ - intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; - tsf = ath9k_hw_gettsf64(ah); - tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); - tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); - slot = (tsftu % (intval * ATH_BCBUF)) / intval; - vif = sc->beacon.bslot[slot]; + if (ah->opmode == NL80211_IFTYPE_AP) { + u16 intval; + u32 tsftu; + u64 tsf; + + intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; + tsf = ath9k_hw_gettsf64(ah); + tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); + tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); + slot = (tsftu % (intval * ATH_BCBUF)) / intval; + vif = sc->beacon.bslot[slot]; + + ath_dbg(common, ATH_DBG_BEACON, + "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", + slot, tsf, tsftu / ATH_BCBUF, intval, vif); + } else { + slot = 0; + vif = sc->beacon.bslot[slot]; + } - ath_dbg(common, ATH_DBG_BEACON, - "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", - slot, tsf, tsftu / ATH_BCBUF, intval, vif); bfaddr = 0; if (vif) { @@ -636,6 +654,8 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, struct ath_common *common = ath9k_hw_common(ah); u32 tsf, delta, intval, nexttbtt; + ath9k_reset_beacon_status(sc); + tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE); intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); @@ -646,7 +666,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, delta = (tsf - sc->beacon.bc_tstamp); else delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp)); - nexttbtt = tsf + roundup(delta, intval); + nexttbtt = tsf + intval - (delta % intval); } ath_dbg(common, ATH_DBG_BEACON, diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 23f15a7..41ce0b1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2009-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index a9efca8..234f776 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2009-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 558b228..a1250c5 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 4420780..1bef41d 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 74535e6..fa6bd2d 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2009-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 5124f14..77ec288 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Atheros Communications Inc. + * Copyright (c) 2009-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index bad1a87..d55ffd7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -435,6 +435,7 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, conf->channel_type, channel_type_str(conf->channel_type)); + ath9k_ps_wakeup(sc); put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); len += snprintf(buf + len, sizeof(buf) - len, @@ -444,6 +445,7 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, len += snprintf(buf + len, sizeof(buf) - len, "addrmask: %pM\n", addr); tmp = ath9k_hw_getrxfilter(sc->sc_ah); + ath9k_ps_restore(sc); len += snprintf(buf + len, sizeof(buf) - len, "rfilt: 0x%x", tmp); if (tmp & ATH9K_RX_FILTER_UCAST) @@ -725,6 +727,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, break; } + ath9k_ps_wakeup(sc); len += snprintf(buf + len, size - len, "curbssid: %pM\n" "OP-Mode: %s(%i)\n" @@ -734,6 +737,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, REG_READ(ah, AR_BEACON_PERIOD)); reg = REG_READ(ah, AR_TIMER_MODE); + ath9k_ps_restore(sc); len += snprintf(buf + len, size - len, "Timer-Mode-Register: 0x%x (", reg); if (reg & AR_TBTT_TIMER_EN) @@ -1050,7 +1054,9 @@ static ssize_t read_file_regval(struct file *file, char __user *user_buf, unsigned int len; u32 regval; + ath9k_ps_wakeup(sc); regval = REG_READ_D(ah, sc->debug.regidx); + ath9k_ps_restore(sc); len = sprintf(buf, "0x%08x\n", regval); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1072,7 +1078,9 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf, if (strict_strtoul(buf, 0, ®val)) return -EINVAL; + ath9k_ps_wakeup(sc); REG_WRITE_D(ah, sc->debug.regidx, regval); + ath9k_ps_restore(sc); return count; } diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 5488a32..8ce6ad8 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 8c18bed..e61404d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 3e31613..de99c0d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 6f714dd..5b1e894 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index b87db47..7856f0d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index c031854..17f0a68 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 0349b3a..bc713fc 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 2e3a33a..260f1f3 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 2bdcdbc..794f630 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,7 +18,7 @@ #define HTC_USB_H #define MAJOR_VERSION_REQ 1 -#define MINOR_VERSION_REQ 2 +#define MINOR_VERSION_REQ 3 #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index dfc7a98..5bc0220 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -46,15 +46,8 @@ extern struct ieee80211_ops ath9k_htc_ops; extern int htc_modparam_nohwcrypt; enum htc_phymode { - HTC_MODE_AUTO = 0, - HTC_MODE_11A = 1, - HTC_MODE_11B = 2, - HTC_MODE_11G = 3, - HTC_MODE_FH = 4, - HTC_MODE_TURBO_A = 5, - HTC_MODE_TURBO_G = 6, - HTC_MODE_11NA = 7, - HTC_MODE_11NG = 8 + HTC_MODE_11NA = 0, + HTC_MODE_11NG = 1 }; enum htc_opmode { @@ -123,18 +116,13 @@ struct ath9k_htc_target_vif { u8 pad; } __packed; -#define ATH_HTC_STA_AUTH 0x0001 -#define ATH_HTC_STA_QOS 0x0002 -#define ATH_HTC_STA_ERP 0x0004 -#define ATH_HTC_STA_HT 0x0008 - struct ath9k_htc_target_sta { u8 macaddr[ETH_ALEN]; u8 bssid[ETH_ALEN]; u8 sta_index; u8 vif_index; u8 is_vif_sta; - __be16 flags; /* ATH_HTC_STA_* */ + __be16 flags; __be16 htcap; __be16 maxampdu; u8 pad; @@ -285,9 +273,9 @@ struct ath9k_htc_rx { }; #define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ -#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 2500 /* ms */ +#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 3000 /* ms */ #define ATH9K_HTC_TX_RESERVE 10 -#define ATH9K_HTC_TX_TIMEOUT_COUNT 20 +#define ATH9K_HTC_TX_TIMEOUT_COUNT 40 #define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) #define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) @@ -450,6 +438,7 @@ struct ath9k_htc_priv { u8 vif_sta_pos[ATH9K_HTC_MAX_VIF]; u8 num_ibss_vif; u8 num_sta_vif; + u8 num_sta_assoc_vif; u8 num_ap_vif; u16 op_flags; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 0ded2c6..aa6a731 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index af57fe5..db2352e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index bfdc8a8..61e6d39 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -258,7 +258,7 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, */ if (IS_AR7010_DEVICE(drv_info)) - priv->htc->credits = 48; + priv->htc->credits = 45; else priv->htc->credits = 33; @@ -769,11 +769,6 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, hw->channel_change_time = 5000; hw->max_listen_interval = 10; - if (AR_SREV_9271(priv->ah)) - hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_9271; - else - hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_7010; - hw->vif_data_size = sizeof(struct ath9k_htc_vif); hw->sta_data_size = sizeof(struct ath9k_htc_sta); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 5aa104f..7b77968 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,7 +26,7 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, { enum htc_phymode mode; - mode = HTC_MODE_AUTO; + mode = -EINVAL; switch (ichan->chanmode) { case CHANNEL_G: @@ -45,6 +45,8 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, break; } + WARN_ON(mode < 0); + return mode; } @@ -500,9 +502,6 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, tsta.maxampdu = cpu_to_be16(maxampdu); } - if (sta && sta->ht_cap.ht_supported) - tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); - WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); if (ret) { if (sta) @@ -582,7 +581,7 @@ int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); tcap.ampdu_limit = cpu_to_be32(0xffff); - tcap.ampdu_subframes = priv->hw->max_tx_aggregation_subframes; + tcap.ampdu_subframes = 0xff; tcap.enable_coex = enable_coex; tcap.tx_chainmask = priv->ah->caps.tx_chainmask; @@ -1165,6 +1164,8 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, ath9k_htc_set_opmode(priv); + ath9k_htc_set_bssid_mask(priv, vif); + /* * Stop ANI only if there are no associated station interfaces. */ @@ -1435,6 +1436,37 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, return ret; } +static void ath9k_htc_set_bssid(struct ath9k_htc_priv *priv) +{ + struct ath_common *common = ath9k_hw_common(priv->ah); + + ath9k_hw_write_associd(priv->ah); + ath_dbg(common, ATH_DBG_CONFIG, + "BSSID: %pM aid: 0x%x\n", + common->curbssid, common->curaid); +} + +static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; + struct ath_common *common = ath9k_hw_common(priv->ah); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + + if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) { + common->curaid = bss_conf->aid; + memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); + } +} + +static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv) +{ + if (priv->num_sta_assoc_vif == 1) { + ieee80211_iterate_active_interfaces_atomic(priv->hw, + ath9k_htc_bss_iter, priv); + ath9k_htc_set_bssid(priv); + } +} + static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -1443,43 +1475,32 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); - bool set_assoc; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); - /* - * Set the HW AID/BSSID only for the first station interface - * or in IBSS mode. - */ - set_assoc = !!((priv->ah->opmode == NL80211_IFTYPE_ADHOC) || - ((priv->ah->opmode == NL80211_IFTYPE_STATION) && - (priv->num_sta_vif == 1))); - - if (changed & BSS_CHANGED_ASSOC) { - if (set_assoc) { - ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", - bss_conf->assoc); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + bss_conf->assoc); - common->curaid = bss_conf->assoc ? - bss_conf->aid : 0; + bss_conf->assoc ? + priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; - if (bss_conf->assoc) + if (priv->ah->opmode == NL80211_IFTYPE_STATION) { + if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) ath9k_htc_start_ani(priv); - else + else if (priv->num_sta_assoc_vif == 0) ath9k_htc_stop_ani(priv); } } if (changed & BSS_CHANGED_BSSID) { - if (set_assoc) { + if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { + common->curaid = bss_conf->aid; memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); - ath9k_hw_write_associd(ah); - - ath_dbg(common, ATH_DBG_CONFIG, - "BSSID: %pM aid: 0x%x\n", - common->curbssid, common->curaid); + ath9k_htc_set_bssid(priv); + } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) { + ath9k_htc_choose_set_bssid(priv); } } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index a898dac..2d81c70 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -875,6 +875,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) rfilt |= ATH9K_RX_FILTER_CONTROL; if ((ah->opmode == NL80211_IFTYPE_STATION) && + (priv->nvifs <= 1) && !(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC)) rfilt |= ATH9K_RX_FILTER_MYBEACON; else @@ -888,6 +889,9 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) if (priv->rxfilter & FIF_PSPOLL) rfilt |= ATH9K_RX_FILTER_PSPOLL; + if (priv->nvifs > 1) + rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; + return rfilt; #undef RX_FILTER_PRESERVE diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index cee970f..1b90ed8 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 91a5305..e1ffbb6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 8b8f044..2f3e072 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b75b5dc..72543ce 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7af2773..57435ce 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index b172d15..45c585a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index bd6d2b9..c2091f1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index b60c130..8e848c4 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 17ebdf1..a198ee3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -2332,6 +2332,45 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) return false; } +int ath9k_tx_last_beacon(struct ieee80211_hw *hw) +{ + struct ath_softc *sc = hw->priv; + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_vif *vif; + struct ath_vif *avp; + struct ath_buf *bf; + struct ath_tx_status ts; + int status; + + vif = sc->beacon.bslot[0]; + if (!vif) + return 0; + + avp = (void *)vif->drv_priv; + if (!avp->is_bslot_active) + return 0; + + if (!sc->beacon.tx_processed) { + tasklet_disable(&sc->bcon_tasklet); + + bf = avp->av_bcbuf; + if (!bf || !bf->bf_mpdu) + goto skip; + + status = ath9k_hw_txprocdesc(ah, bf->bf_desc, &ts); + if (status == -EINPROGRESS) + goto skip; + + sc->beacon.tx_processed = true; + sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); + +skip: + tasklet_enable(&sc->bcon_tasklet); + } + + return sc->beacon.tx_last; +} + struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2356,4 +2395,5 @@ struct ieee80211_ops ath9k_ops = { .set_coverage_class = ath9k_set_coverage_class, .flush = ath9k_flush, .tx_frames_pending = ath9k_tx_frames_pending, + .tx_last_beacon = ath9k_tx_last_beacon, }; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 9c65459..b8cbfc7 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 9441bf8..8b38030 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 4ccbf2d..1754221 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2004-2009 Atheros Communications, Inc. + * Copyright (c) 2004-2011 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 5d984b8..c3d8502 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2004 Sam Leffler, Errno Consulting * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 4f52e04..07e35e5 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 456f3ec..c18ee99 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index f9b1eb4..35422fc 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 6095eeb..fde6da6 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Atheros Communications Inc. + * Copyright (c) 2010-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 97dd1fa..3779b89 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index bb57869..4da01a9 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -286,6 +286,10 @@ struct ar9170 { unsigned int tx_seq_table; } fw; + /* interface configuration combinations */ + struct ieee80211_iface_limit if_comb_limits[1]; + struct ieee80211_iface_combination if_combs[1]; + /* reset / stuck frames/queue detection */ struct work_struct restart_work; struct work_struct ping_work; diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 9517ede..221957c 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c @@ -151,6 +151,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) const struct carl9170fw_chk_desc *chk_desc; const struct carl9170fw_last_desc *last_desc; const struct carl9170fw_txsq_desc *txsq_desc; + u16 if_comb_types; last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC, sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER); @@ -268,6 +269,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) if (SUPP(CARL9170FW_WOL)) device_set_wakeup_enable(&ar->udev->dev, true); + if_comb_types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_P2P_CLIENT); + ar->fw.vif_num = otus_desc->vif_num; ar->fw.cmd_bufs = otus_desc->cmd_bufs; ar->fw.address = le32_to_cpu(otus_desc->fw_address); @@ -294,12 +298,25 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); if (SUPP(CARL9170FW_WLANTX_CAB)) { - ar->hw->wiphy->interface_modes |= + if_comb_types |= BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO); } } + ar->if_comb_limits[0].max = ar->fw.vif_num; + ar->if_comb_limits[0].types = if_comb_types; + + ar->if_combs[0].num_different_channels = 1; + ar->if_combs[0].max_interfaces = ar->fw.vif_num; + ar->if_combs[0].limits = ar->if_comb_limits; + ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits); + + ar->hw->wiphy->iface_combinations = ar->if_combs; + ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs); + + ar->hw->wiphy->interface_modes |= if_comb_types; + txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC, sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 7d5c65e..54d093c 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1570,14 +1570,8 @@ void *carl9170_alloc(size_t priv_size) INIT_LIST_HEAD(&ar->vif_list); init_completion(&ar->tx_flush); - /* - * Note: - * IBSS/ADHOC and AP mode are only enabled, if the firmware - * supports these modes. The code which will add the - * additional interface_modes is in fw.c. - */ - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_P2P_CLIENT); + /* firmware decides which modes we support */ + hw->wiphy->interface_modes = 0; hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_REPORTS_TX_ACK_STATUS | diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index cc11d66..3f508e5 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c @@ -43,7 +43,7 @@ * set of ~ ( MAC XOR BSSID ) for all bssids we handle. * * When you do this you are essentially computing the common bits of all your - * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with + * BSSes. Later it is assumed the hardware will "and" (&) the BSSID mask with * the MAC address to obtain the relevant bits and compare the result with * (frame's BSSID & mask) to see if they match. * @@ -71,8 +71,8 @@ * On loop iteration for BSSID-02: * bssid_mask &= ~(0001 ^ 1001) * bssid_mask = (1010) & ~(0001 ^ 1001) - * bssid_mask = (1010) & ~(1001) - * bssid_mask = (1010) & (0110) + * bssid_mask = (1010) & ~(1000) + * bssid_mask = (1010) & (0111) * bssid_mask = 0010 * * A bssid_mask of 0010 means "only pay attention to the second least @@ -102,11 +102,9 @@ * * IFRAME-02: 0001 (we should allow) * - * allow = (0001 & 1010) == 1010 - * * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; - * --> allow = (0010) == (0010) + * --> allow = (0000) == (0000) * --> allow = 1 * * Other examples: diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 0526351..ec295c4 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -122,7 +122,7 @@ static int atmel_config(struct pcmcia_device *link) { local_info_t *dev; int ret; - struct pcmcia_device_id *did; + const struct pcmcia_device_id *did; dev = link->priv; did = dev_get_drvdata(&link->dev); @@ -211,7 +211,7 @@ static int atmel_resume(struct pcmcia_device *link) .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ .driver_info = (kernel_ulong_t)(info), } -static struct pcmcia_device_id atmel_ids[] = { +static const struct pcmcia_device_id atmel_ids[] = { PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0620, ATMEL_FW_TYPE_502_3COM), PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0696, ATMEL_FW_TYPE_502_3COM), PCMCIA_DEVICE_MANF_CARD_INFO(0x01bf, 0x3302, ATMEL_FW_TYPE_502E), diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index ebc93c1..25a78cf 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -567,6 +567,8 @@ struct b43_dma { struct b43_dmaring *tx_ring_mcast; /* Multicast */ struct b43_dmaring *rx_ring; + + u32 translation; /* Routing bits */ }; struct b43_pio_txqueue; @@ -705,7 +707,7 @@ enum { /* Data structure for one wireless device (802.11 core) */ struct b43_wldev { - struct ssb_device *dev; + struct ssb_device *sdev; struct b43_wl *wl; /* The device initialization status. @@ -879,22 +881,34 @@ static inline enum ieee80211_band b43_current_band(struct b43_wl *wl) static inline u16 b43_read16(struct b43_wldev *dev, u16 offset) { - return ssb_read16(dev->dev, offset); + return ssb_read16(dev->sdev, offset); } static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value) { - ssb_write16(dev->dev, offset, value); + ssb_write16(dev->sdev, offset, value); } static inline u32 b43_read32(struct b43_wldev *dev, u16 offset) { - return ssb_read32(dev->dev, offset); + return ssb_read32(dev->sdev, offset); } static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) { - ssb_write32(dev->dev, offset, value); + ssb_write32(dev->sdev, offset, value); +} + +static inline void b43_block_read(struct b43_wldev *dev, void *buffer, + size_t count, u16 offset, u8 reg_width) +{ + ssb_block_read(dev->sdev, buffer, count, offset, reg_width); +} + +static inline void b43_block_write(struct b43_wldev *dev, const void *buffer, + size_t count, u16 offset, u8 reg_width) +{ + ssb_block_write(dev->sdev, buffer, count, offset, reg_width); } static inline bool b43_using_pio_transfers(struct b43_wldev *dev) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index ff0f5ba..47d44bc 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -80,7 +80,7 @@ static void op32_fill_descriptor(struct b43_dmaring *ring, addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK); addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addr |= ssb_dma_translation(ring->dev->dev); + addr |= ring->dev->dma.translation; ctl = bufsize & B43_DMA32_DCTL_BYTECNT; if (slot == ring->nr_slots - 1) ctl |= B43_DMA32_DCTL_DTABLEEND; @@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring, addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= (ssb_dma_translation(ring->dev->dev) << 1); + addrhi |= (ring->dev->dma.translation << 1); if (slot == ring->nr_slots - 1) ctl0 |= B43_DMA64_DCTL0_DTABLEEND; if (start) @@ -333,10 +333,10 @@ static inline dma_addr_t dmaaddr; if (tx) { - dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + dmaaddr = dma_map_single(ring->dev->sdev->dma_dev, buf, len, DMA_TO_DEVICE); } else { - dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + dmaaddr = dma_map_single(ring->dev->sdev->dma_dev, buf, len, DMA_FROM_DEVICE); } @@ -348,10 +348,10 @@ static inline dma_addr_t addr, size_t len, int tx) { if (tx) { - dma_unmap_single(ring->dev->dev->dma_dev, + dma_unmap_single(ring->dev->sdev->dma_dev, addr, len, DMA_TO_DEVICE); } else { - dma_unmap_single(ring->dev->dev->dma_dev, + dma_unmap_single(ring->dev->sdev->dma_dev, addr, len, DMA_FROM_DEVICE); } } @@ -361,7 +361,7 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - dma_sync_single_for_cpu(ring->dev->dev->dma_dev, + dma_sync_single_for_cpu(ring->dev->sdev->dma_dev, addr, len, DMA_FROM_DEVICE); } @@ -370,7 +370,7 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - dma_sync_single_for_device(ring->dev->dev->dma_dev, + dma_sync_single_for_device(ring->dev->sdev->dma_dev, addr, len, DMA_FROM_DEVICE); } @@ -401,7 +401,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring) */ if (ring->type == B43_DMA_64BIT) flags |= GFP_DMA; - ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, + ring->descbase = dma_alloc_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE, &(ring->dmabase), flags); if (!ring->descbase) { @@ -415,7 +415,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring) static void free_ringmemory(struct b43_dmaring *ring) { - dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, + dma_free_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE, ring->descbase, ring->dmabase); } @@ -523,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, dma_addr_t addr, size_t buffersize, bool dma_to_device) { - if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr))) + if (unlikely(dma_mapping_error(ring->dev->sdev->dma_dev, addr))) return 1; switch (ring->type) { @@ -658,7 +658,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) int err = 0; u32 value; u32 addrext; - u32 trans = ssb_dma_translation(ring->dev->dev); + u32 trans = ring->dev->dma.translation; if (ring->tx) { if (ring->type == B43_DMA_64BIT) { @@ -869,7 +869,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = dma_map_single(dev->dev->dma_dev, + dma_test = dma_map_single(dev->sdev->dma_dev, ring->txhdr_cache, b43_txhdr_size(dev), DMA_TO_DEVICE); @@ -884,7 +884,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, if (!ring->txhdr_cache) goto err_kfree_meta; - dma_test = dma_map_single(dev->dev->dma_dev, + dma_test = dma_map_single(dev->sdev->dma_dev, ring->txhdr_cache, b43_txhdr_size(dev), DMA_TO_DEVICE); @@ -898,7 +898,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, } } - dma_unmap_single(dev->dev->dma_dev, + dma_unmap_single(dev->sdev->dma_dev, dma_test, b43_txhdr_size(dev), DMA_TO_DEVICE); } @@ -1013,9 +1013,9 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) /* Try to set the DMA mask. If it fails, try falling back to a * lower mask, as we can always also support a lower one. */ while (1) { - err = dma_set_mask(dev->dev->dma_dev, mask); + err = dma_set_mask(dev->sdev->dma_dev, mask); if (!err) { - err = dma_set_coherent_mask(dev->dev->dma_dev, mask); + err = dma_set_coherent_mask(dev->sdev->dma_dev, mask); if (!err) break; } @@ -1055,6 +1055,7 @@ int b43_dma_init(struct b43_wldev *dev) err = b43_dma_set_mask(dev, dmamask); if (err) return err; + dma->translation = ssb_dma_translation(dev->sdev); err = -ENOMEM; /* setup TX DMA channels. */ @@ -1084,7 +1085,7 @@ int b43_dma_init(struct b43_wldev *dev) goto err_destroy_mcast; /* No support for the TX status DMA ring. */ - B43_WARN_ON(dev->dev->id.revision < 5); + B43_WARN_ON(dev->sdev->id.revision < 5); b43dbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type); diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index c587115..0cafafe 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -138,7 +138,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, led->led_dev.default_trigger = default_trigger; led->led_dev.brightness_set = b43_led_brightness_set; - err = led_classdev_register(dev->dev->dev, &led->led_dev); + err = led_classdev_register(dev->sdev->dev, &led->led_dev); if (err) { b43warn(dev->wl, "LEDs: Failed to register %s\n", name); led->wl = NULL; @@ -215,7 +215,7 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev, enum b43_led_behaviour *behaviour, bool *activelow) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u8 sprom[4]; sprom[0] = bus->sprom.gpio0; diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index 94e4f13..2ef7d4b 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c @@ -98,7 +98,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev, rfover |= pga; rfover |= lna; rfover |= trsw_rx; - if ((dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) + if ((dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && phy->rev > 6) rfover |= B43_PHY_RFOVERVAL_EXTLNA; @@ -387,7 +387,7 @@ struct lo_g_saved_values { static void lo_measure_setup(struct b43_wldev *dev, struct lo_g_saved_values *sav) { - struct ssb_sprom *sprom = &dev->dev->bus->sprom; + struct ssb_sprom *sprom = &dev->sdev->bus->sprom; struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; struct b43_txpower_lo_control *lo = gphy->lo_control; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5a43984..eb41596 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -548,7 +548,7 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf) { u32 low, high; - B43_WARN_ON(dev->dev->id.revision < 3); + B43_WARN_ON(dev->sdev->id.revision < 3); /* The hardware guarantees us an atomic read, if we * read the low register first. */ @@ -586,7 +586,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf) { u32 low, high; - B43_WARN_ON(dev->dev->id.revision < 3); + B43_WARN_ON(dev->sdev->id.revision < 3); low = tsf; high = (tsf >> 32); @@ -714,7 +714,7 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on) b43_ram_write(dev, i * 4, buffer[i]); b43_write16(dev, 0x0568, 0x0000); - if (dev->dev->id.revision < 11) + if (dev->sdev->id.revision < 11) b43_write16(dev, 0x07C0, 0x0000); else b43_write16(dev, 0x07C0, 0x0100); @@ -1132,7 +1132,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) b43_write32(dev, B43_MMIO_MACCTL, macctl); /* Commit write */ b43_read32(dev, B43_MMIO_MACCTL); - if (awake && dev->dev->id.revision >= 5) { + if (awake && dev->sdev->id.revision >= 5) { /* Wait for the microcode to wake up. */ for (i = 0; i < 100; i++) { ucstat = b43_shm_read16(dev, B43_SHM_SHARED, @@ -1144,29 +1144,35 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) } } -void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) +static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, u32 flags) { u32 tmslow; - u32 macctl; flags |= B43_TMSLOW_PHYCLKEN; flags |= B43_TMSLOW_PHYRESET; if (dev->phy.type == B43_PHYTYPE_N) flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */ - ssb_device_enable(dev->dev, flags); + ssb_device_enable(dev->sdev, flags); msleep(2); /* Wait for the PLL to turn on. */ /* Now take the PHY out of Reset again */ - tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); tmslow |= SSB_TMSLOW_FGC; tmslow &= ~B43_TMSLOW_PHYRESET; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); - ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ + ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); + ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */ msleep(1); tmslow &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); - ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ + ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); + ssb_read32(dev->sdev, SSB_TMSLOW); /* flush */ msleep(1); +} + +void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) +{ + u32 macctl; + + b43_ssb_wireless_core_reset(dev, flags); /* Turn Analog ON, but only if we already know the PHY-type. * This protects against very early setup where we don't know the @@ -1215,7 +1221,7 @@ static void drain_txstatus_queue(struct b43_wldev *dev) { u32 dummy; - if (dev->dev->id.revision < 5) + if (dev->sdev->id.revision < 5) return; /* Read all entries from the microcode TXstatus FIFO * and throw them away. @@ -1421,9 +1427,9 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev, /* Get the mask of available antennas. */ if (dev->phy.gmode) - antenna_mask = dev->dev->bus->sprom.ant_available_bg; + antenna_mask = dev->sdev->bus->sprom.ant_available_bg; else - antenna_mask = dev->dev->bus->sprom.ant_available_a; + antenna_mask = dev->sdev->bus->sprom.ant_available_a; if (!(antenna_mask & (1 << (antenna_nr - 1)))) { /* This antenna is not available. Fall back to default. */ @@ -1638,7 +1644,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) mutex_lock(&wl->mutex); dev = wl->current_dev; if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { /* wl->mutex is enough. */ b43_do_beacon_update_trigger_work(dev); mmiowb(); @@ -1683,7 +1689,7 @@ static void b43_update_templates(struct b43_wl *wl) static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) { b43_time_lock(dev); - if (dev->dev->id.revision >= 3) { + if (dev->sdev->id.revision >= 3) { b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16)); b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10)); } else { @@ -2057,7 +2063,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, B43_WARN_ON(1); return -ENOSYS; } - err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); + err = request_firmware(&blob, ctx->fwname, ctx->dev->sdev->dev); if (err == -ENOENT) { snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), @@ -2107,13 +2113,12 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) { struct b43_wldev *dev = ctx->dev; struct b43_firmware *fw = &ctx->dev->fw; - const u8 rev = ctx->dev->dev->id.revision; + const u8 rev = ctx->dev->sdev->id.revision; const char *filename; u32 tmshigh; int err; /* Get microcode */ - tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); if ((rev >= 5) && (rev <= 10)) filename = "ucode5"; else if ((rev >= 11) && (rev <= 12)) @@ -2152,6 +2157,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) switch (dev->phy.type) { case B43_PHYTYPE_A: if ((rev >= 5) && (rev <= 10)) { + tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) filename = "a0g1initvals5"; else @@ -2196,6 +2202,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) switch (dev->phy.type) { case B43_PHYTYPE_A: if ((rev >= 5) && (rev <= 10)) { + tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) filename = "a0g1bsinitvals5"; else @@ -2441,7 +2448,7 @@ static int b43_upload_microcode(struct b43_wldev *dev) snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u", dev->fw.rev, dev->fw.patch); - wiphy->hw_version = dev->dev->id.coreid; + wiphy->hw_version = dev->sdev->id.coreid; if (b43_is_old_txhdr_format(dev)) { /* We're over the deadline, but we keep support for old fw @@ -2557,10 +2564,20 @@ out: /* Initialize the GPIOs * http://bcm-specs.sipsolutions.net/GPIO */ +static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev) +{ + struct ssb_bus *bus = dev->sdev->bus; + +#ifdef CONFIG_SSB_DRIVER_PCICORE + return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev); +#else + return bus->chipco.dev; +#endif +} + static int b43_gpio_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; - struct ssb_device *gpiodev, *pcidev = NULL; + struct ssb_device *gpiodev; u32 mask, set; b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) @@ -2571,7 +2588,7 @@ static int b43_gpio_init(struct b43_wldev *dev) mask = 0x0000001F; set = 0x0000000F; - if (dev->dev->bus->chip_id == 0x4301) { + if (dev->sdev->bus->chip_id == 0x4301) { mask |= 0x0060; set |= 0x0060; } @@ -2582,25 +2599,21 @@ static int b43_gpio_init(struct b43_wldev *dev) mask |= 0x0180; set |= 0x0180; } - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) { + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) { b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) | 0x0200); mask |= 0x0200; set |= 0x0200; } - if (dev->dev->id.revision >= 2) + if (dev->sdev->id.revision >= 2) mask |= 0x0010; /* FIXME: This is redundant. */ -#ifdef CONFIG_SSB_DRIVER_PCICORE - pcidev = bus->pcicore.dev; -#endif - gpiodev = bus->chipco.dev ? : pcidev; - if (!gpiodev) - return 0; - ssb_write32(gpiodev, B43_GPIO_CONTROL, - (ssb_read32(gpiodev, B43_GPIO_CONTROL) - & mask) | set); + gpiodev = b43_ssb_gpio_dev(dev); + if (gpiodev) + ssb_write32(gpiodev, B43_GPIO_CONTROL, + (ssb_read32(gpiodev, B43_GPIO_CONTROL) + & mask) | set); return 0; } @@ -2608,16 +2621,11 @@ static int b43_gpio_init(struct b43_wldev *dev) /* Turn off all GPIO stuff. Call this on module unload, for example. */ static void b43_gpio_cleanup(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; - struct ssb_device *gpiodev, *pcidev = NULL; + struct ssb_device *gpiodev; -#ifdef CONFIG_SSB_DRIVER_PCICORE - pcidev = bus->pcicore.dev; -#endif - gpiodev = bus->chipco.dev ? : pcidev; - if (!gpiodev) - return; - ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); + gpiodev = b43_ssb_gpio_dev(dev); + if (gpiodev) + ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); } /* http://bcm-specs.sipsolutions.net/EnableMac */ @@ -2689,12 +2697,12 @@ out: /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) { - u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); if (on) tmslow |= B43_TMSLOW_MACPHYCLKEN; else tmslow &= ~B43_TMSLOW_MACPHYCLKEN; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); + ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); } static void b43_adjust_opmode(struct b43_wldev *dev) @@ -2733,15 +2741,15 @@ static void b43_adjust_opmode(struct b43_wldev *dev) /* Workaround: On old hardware the HW-MAC-address-filter * doesn't work properly, so always run promisc in filter * it in software. */ - if (dev->dev->id.revision <= 4) + if (dev->sdev->id.revision <= 4) ctl |= B43_MACCTL_PROMISC; b43_write32(dev, B43_MMIO_MACCTL, ctl); cfp_pretbtt = 2; if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) { - if (dev->dev->bus->chip_id == 0x4306 && - dev->dev->bus->chip_rev == 3) + if (dev->sdev->bus->chip_id == 0x4306 && + dev->sdev->bus->chip_rev == 3) cfp_pretbtt = 100; else cfp_pretbtt = 50; @@ -2899,7 +2907,7 @@ static int b43_chip_init(struct b43_wldev *dev) b43_write16(dev, 0x005E, value16); } b43_write32(dev, 0x0100, 0x01000000); - if (dev->dev->id.revision < 5) + if (dev->sdev->id.revision < 5) b43_write32(dev, 0x010C, 0x01000000); b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) @@ -2914,7 +2922,7 @@ static int b43_chip_init(struct b43_wldev *dev) /* Initially set the wireless operation mode. */ b43_adjust_opmode(dev); - if (dev->dev->id.revision < 3) { + if (dev->sdev->id.revision < 3) { b43_write16(dev, 0x060E, 0x0000); b43_write16(dev, 0x0610, 0x8000); b43_write16(dev, 0x0604, 0x0000); @@ -2934,7 +2942,7 @@ static int b43_chip_init(struct b43_wldev *dev) b43_mac_phy_clock_set(dev, true); b43_write16(dev, B43_MMIO_POWERUP_DELAY, - dev->dev->bus->chipco.fast_pwrup_delay); + dev->sdev->bus->chipco.fast_pwrup_delay); err = 0; b43dbg(dev->wl, "Chip initialized\n"); @@ -3097,7 +3105,7 @@ static int b43_validate_chipaccess(struct b43_wldev *dev) b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0); b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4); - if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) { + if ((dev->sdev->id.revision >= 3) && (dev->sdev->id.revision <= 10)) { /* The 32bit register shadows the two 16bit registers * with update sideeffects. Validate this. */ b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA); @@ -3450,7 +3458,7 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) static void b43_put_phy_into_reset(struct b43_wldev *dev) { - struct ssb_device *sdev = dev->dev; + struct ssb_device *sdev = dev->sdev; u32 tmslow; tmslow = ssb_read32(sdev, SSB_TMSLOW); @@ -3946,7 +3954,7 @@ redo: /* Disable interrupts on the device. */ b43_set_status(dev, B43_STAT_INITIALIZED); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { /* wl->mutex is locked. That is enough. */ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ @@ -3959,11 +3967,11 @@ redo: /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */ orig_dev = dev; mutex_unlock(&wl->mutex); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { b43_sdio_free_irq(dev); } else { - synchronize_irq(dev->dev->irq); - free_irq(dev->dev->irq, dev); + synchronize_irq(dev->sdev->irq); + free_irq(dev->sdev->irq, dev); } mutex_lock(&wl->mutex); dev = wl->current_dev; @@ -3996,18 +4004,19 @@ static int b43_wireless_core_start(struct b43_wldev *dev) B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); drain_txstatus_queue(dev); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { + if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler); if (err) { b43err(dev->wl, "Cannot request SDIO IRQ\n"); goto out; } } else { - err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, + err = request_threaded_irq(dev->sdev->irq, b43_interrupt_handler, b43_interrupt_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { - b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); + b43err(dev->wl, "Cannot request IRQ-%d\n", + dev->sdev->irq); goto out; } } @@ -4087,10 +4096,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) analog_type, phy_type, phy_rev); /* Get RADIO versioning */ - if (dev->dev->bus->chip_id == 0x4317) { - if (dev->dev->bus->chip_rev == 0) + if (dev->sdev->bus->chip_id == 0x4317) { + if (dev->sdev->bus->chip_rev == 0) tmp = 0x3205017F; - else if (dev->dev->bus->chip_rev == 1) + else if (dev->sdev->bus->chip_rev == 1) tmp = 0x4205017F; else tmp = 0x5205017F; @@ -4195,7 +4204,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev) static void b43_bluetooth_coext_enable(struct b43_wldev *dev) { - struct ssb_sprom *sprom = &dev->dev->bus->sprom; + struct ssb_sprom *sprom = &dev->sdev->bus->sprom; u64 hf; if (!modparam_btcoex) @@ -4222,16 +4231,16 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev) static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u32 tmp; if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) || (bus->chip_id == 0x4312)) { - tmp = ssb_read32(dev->dev, SSB_IMCFGLO); + tmp = ssb_read32(dev->sdev, SSB_IMCFGLO); tmp &= ~SSB_IMCFGLO_REQTO; tmp &= ~SSB_IMCFGLO_SERTO; tmp |= 0x3; - ssb_write32(dev->dev, SSB_IMCFGLO, tmp); + ssb_write32(dev->sdev, SSB_IMCFGLO, tmp); ssb_commit_settings(bus); } } @@ -4301,14 +4310,14 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) dev->wl->current_beacon = NULL; } - ssb_device_disable(dev->dev, 0); - ssb_bus_may_powerdown(dev->dev->bus); + ssb_device_disable(dev->sdev, 0); + ssb_bus_may_powerdown(dev->sdev->bus); } /* Initialize a wireless core */ static int b43_wireless_core_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct ssb_sprom *sprom = &bus->sprom; struct b43_phy *phy = &dev->phy; int err; @@ -4320,7 +4329,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) err = ssb_bus_powerup(bus, 0); if (err) goto out; - if (!ssb_device_is_enabled(dev->dev)) { + if (!ssb_device_is_enabled(dev->sdev)) { tmp = phy->gmode ? B43_TMSLOW_GMODE : 0; b43_wireless_core_reset(dev, tmp); } @@ -4330,7 +4339,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) phy->ops->prepare_structs(dev); /* Enable IRQ routing to this device. */ - ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); + ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev); b43_imcfglo_timeouts_workaround(dev); b43_bluetooth_coext_disable(dev); @@ -4343,7 +4352,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) if (err) goto err_busdown; b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_WLCOREREV, dev->dev->id.revision); + B43_SHM_SH_WLCOREREV, dev->sdev->id.revision); hf = b43_hf_read(dev); if (phy->type == B43_PHYTYPE_G) { hf |= B43_HF_SYMW; @@ -4390,8 +4399,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev) /* Maximum Contention Window */ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); - if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || - (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || + if ((dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA) || + (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) || dev->use_pio) { dev->__using_pio_transfers = 1; err = b43_pio_init(dev); @@ -4728,7 +4737,7 @@ static void b43_wireless_core_detach(struct b43_wldev *dev) static int b43_wireless_core_attach(struct b43_wldev *dev) { struct b43_wl *wl = dev->wl; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL; int err; bool have_2ghz_phy = 0, have_5ghz_phy = 0; @@ -4747,10 +4756,10 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) goto out; } /* Get the PHY type. */ - if (dev->dev->id.revision >= 5) { + if (dev->sdev->id.revision >= 5) { u32 tmshigh; - tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); + tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY); have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY); } else @@ -4823,7 +4832,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) INIT_WORK(&dev->restart_work, b43_chip_reset); dev->phy.ops->switch_analog(dev, 0); - ssb_device_disable(dev->dev, 0); + ssb_device_disable(dev->sdev, 0); ssb_bus_may_powerdown(bus); out: @@ -4864,7 +4873,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) goto out; wldev->use_pio = b43_modparam_pio; - wldev->dev = dev; + wldev->sdev = dev; wldev->wl = wl; b43_set_status(wldev, B43_STAT_UNINIT); wldev->bad_frames_preempt = modparam_bad_frames_preempt; @@ -4925,19 +4934,16 @@ static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl) ieee80211_free_hw(hw); } -static int b43_wireless_init(struct ssb_device *dev) +static struct b43_wl *b43_wireless_init(struct ssb_device *dev) { struct ssb_sprom *sprom = &dev->bus->sprom; struct ieee80211_hw *hw; struct b43_wl *wl; - int err = -ENOMEM; - - b43_sprom_fixup(dev->bus); hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops); if (!hw) { b43err(NULL, "Could not allocate ieee80211 device\n"); - goto out; + return ERR_PTR(-ENOMEM); } wl = hw_to_b43_wl(hw); @@ -4971,12 +4977,9 @@ static int b43_wireless_init(struct ssb_device *dev) INIT_WORK(&wl->tx_work, b43_tx_work); skb_queue_head_init(&wl->tx_queue); - ssb_set_devtypedata(dev, wl); b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", dev->bus->chip_id, dev->id.revision); - err = 0; -out: - return err; + return wl; } static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id) @@ -4989,11 +4992,14 @@ static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id) if (!wl) { /* Probing the first core. Must setup common struct b43_wl */ first = 1; - err = b43_wireless_init(dev); - if (err) + b43_sprom_fixup(dev->bus); + wl = b43_wireless_init(dev); + if (IS_ERR(wl)) { + err = PTR_ERR(wl); goto out; - wl = ssb_get_devtypedata(dev); - B43_WARN_ON(!wl); + } + ssb_set_devtypedata(dev, wl); + B43_WARN_ON(ssb_get_devtypedata(dev) != wl); } err = b43_one_core_attach(dev, wl); if (err) diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 7dcba5f..2c8461d 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -32,7 +32,7 @@ #include <pcmcia/cisreg.h> -static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { +static const struct pcmcia_device_id b43_pcmcia_tbl[] = { PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), PCMCIA_DEVICE_NULL, diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c index b6428ec..b01c8ce 100644 --- a/drivers/net/wireless/b43/phy_a.c +++ b/drivers/net/wireless/b43/phy_a.c @@ -265,7 +265,7 @@ static void hardware_pctl_init_aphy(struct b43_wldev *dev) void b43_phy_inita(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; /* This lowlevel A-PHY init is also called from G-PHY init. @@ -311,7 +311,7 @@ void b43_phy_inita(struct b43_wldev *dev) } if ((phy->type == B43_PHYTYPE_G) && - (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { + (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF); } } @@ -323,17 +323,17 @@ static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev) struct b43_phy_a *aphy = phy->a; s16 pab0, pab1, pab2; - pab0 = (s16) (dev->dev->bus->sprom.pa1b0); - pab1 = (s16) (dev->dev->bus->sprom.pa1b1); - pab2 = (s16) (dev->dev->bus->sprom.pa1b2); + pab0 = (s16) (dev->sdev->bus->sprom.pa1b0); + pab1 = (s16) (dev->sdev->bus->sprom.pa1b1); + pab2 = (s16) (dev->sdev->bus->sprom.pa1b2); if (pab0 != 0 && pab1 != 0 && pab2 != 0 && pab0 != -1 && pab1 != -1 && pab2 != -1) { /* The pabX values are set in SPROM. Use them. */ - if ((s8) dev->dev->bus->sprom.itssi_a != 0 && - (s8) dev->dev->bus->sprom.itssi_a != -1) + if ((s8) dev->sdev->bus->sprom.itssi_a != 0 && + (s8) dev->sdev->bus->sprom.itssi_a != -1) aphy->tgt_idle_tssi = - (s8) (dev->dev->bus->sprom.itssi_a); + (s8) (dev->sdev->bus->sprom.itssi_a); else aphy->tgt_idle_tssi = 62; aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index b5c5ce9..e46b2f4 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -168,7 +168,7 @@ void b43_phy_lock(struct b43_wldev *dev) B43_WARN_ON(dev->phy.phy_locked); dev->phy.phy_locked = 1; #endif - B43_WARN_ON(dev->dev->id.revision < 3); + B43_WARN_ON(dev->sdev->id.revision < 3); if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); @@ -180,7 +180,7 @@ void b43_phy_unlock(struct b43_wldev *dev) B43_WARN_ON(!dev->phy.phy_locked); dev->phy.phy_locked = 0; #endif - B43_WARN_ON(dev->dev->id.revision < 3); + B43_WARN_ON(dev->sdev->id.revision < 3); if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) b43_power_saving_ctl_bits(dev, 0); @@ -368,8 +368,8 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) /* The next check will be needed in two seconds, or later. */ phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2)); - if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && - (dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306)) + if ((dev->sdev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && + (dev->sdev->bus->boardinfo.type == SSB_BOARD_BU4306)) return; /* No software txpower adjustment needed */ result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI)); diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index be48281..1758a28 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -718,7 +718,7 @@ static void b43_calc_nrssi_threshold(struct b43_wldev *dev) B43_WARN_ON(phy->type != B43_PHYTYPE_G); if (!phy->gmode || - !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { + !(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { tmp16 = b43_nrssi_hw_read(dev, 0x20); if (tmp16 >= 0x20) tmp16 -= 0x40; @@ -1114,7 +1114,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev, { struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); if (!phy->gmode) return 0; @@ -1491,7 +1491,7 @@ static u16 b43_radio_init2050(struct b43_wldev *dev) static void b43_phy_initb5(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; u16 offset, value; @@ -1620,7 +1620,7 @@ static void b43_phy_initb6(struct b43_wldev *dev) b43_radio_write16(dev, 0x5A, 0x88); b43_radio_write16(dev, 0x5B, 0x6B); b43_radio_write16(dev, 0x5C, 0x0F); - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) { + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) { b43_radio_write16(dev, 0x5D, 0xFA); b43_radio_write16(dev, 0x5E, 0xD8); } else { @@ -1787,7 +1787,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev) b43_phy_set(dev, B43_PHY_RFOVER, 0x0100); b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF); - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) { + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) { if (phy->rev >= 7) { b43_phy_set(dev, B43_PHY_RFOVER, 0x0800); b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000); @@ -1922,7 +1922,7 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev) /* Initialize B/G PHY power control */ static void b43_phy_init_pctl(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; struct b43_phy_g *gphy = phy->g; struct b43_rfatt old_rfatt; @@ -2053,7 +2053,7 @@ static void b43_phy_initg(struct b43_wldev *dev) if (phy->rev >= 6) { b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12)); } - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); else b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); @@ -2066,7 +2066,7 @@ static void b43_phy_initg(struct b43_wldev *dev) b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); } - if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { + if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { /* The specs state to update the NRSSI LT with * the value 0x7FFFFFFF here. I think that is some weird * compiler optimization in the original driver. @@ -2088,8 +2088,8 @@ static void b43_phy_initg(struct b43_wldev *dev) /* FIXME: The spec says in the following if, the 0 should be replaced 'if OFDM may not be used in the current locale' but OFDM is legal everywhere */ - if ((dev->dev->bus->chip_id == 0x4306 - && dev->dev->bus->chip_package == 2) || 0) { + if ((dev->sdev->bus->chip_id == 0x4306 + && dev->sdev->bus->chip_package == 2) || 0) { b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF); b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF); } @@ -2105,7 +2105,7 @@ void b43_gphy_channel_switch(struct b43_wldev *dev, b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel)); if (channel == 14) { - if (dev->dev->bus->sprom.country_code == + if (dev->sdev->bus->sprom.country_code == SSB_SPROM1CCODE_JAPAN) b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ACPR); @@ -2136,7 +2136,7 @@ static void default_baseband_attenuation(struct b43_wldev *dev, static void default_radio_attenuation(struct b43_wldev *dev, struct b43_rfatt *rf) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; rf->with_padmix = 0; @@ -2384,11 +2384,11 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev) struct b43_phy_g *gphy = phy->g; s16 pab0, pab1, pab2; - pab0 = (s16) (dev->dev->bus->sprom.pa0b0); - pab1 = (s16) (dev->dev->bus->sprom.pa0b1); - pab2 = (s16) (dev->dev->bus->sprom.pa0b2); + pab0 = (s16) (dev->sdev->bus->sprom.pa0b0); + pab1 = (s16) (dev->sdev->bus->sprom.pa0b1); + pab2 = (s16) (dev->sdev->bus->sprom.pa0b2); - B43_WARN_ON((dev->dev->bus->chip_id == 0x4301) && + B43_WARN_ON((dev->sdev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)); /* Not supported anymore */ gphy->dyn_tssi_tbl = 0; @@ -2396,10 +2396,10 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev) if (pab0 != 0 && pab1 != 0 && pab2 != 0 && pab0 != -1 && pab1 != -1 && pab2 != -1) { /* The pabX values are set in SPROM. Use them. */ - if ((s8) dev->dev->bus->sprom.itssi_bg != 0 && - (s8) dev->dev->bus->sprom.itssi_bg != -1) { + if ((s8) dev->sdev->bus->sprom.itssi_bg != 0 && + (s8) dev->sdev->bus->sprom.itssi_bg != -1) { gphy->tgt_idle_tssi = - (s8) (dev->dev->bus->sprom.itssi_bg); + (s8) (dev->sdev->bus->sprom.itssi_bg); } else gphy->tgt_idle_tssi = 62; gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, @@ -2840,7 +2840,7 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) B43_TXCTL_TXMIX; rfatt += 2; bbatt += 2; - } else if (dev->dev->bus->sprom. + } else if (dev->sdev->bus->sprom. boardflags_lo & B43_BFL_PACTRL) { bbatt += 4 * (rfatt - 2); @@ -2914,14 +2914,14 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi); B43_WARN_ON(phy->type != B43_PHYTYPE_G); - max_pwr = dev->dev->bus->sprom.maxpwr_bg; - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) + max_pwr = dev->sdev->bus->sprom.maxpwr_bg; + if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) max_pwr -= 3; /* minus 0.75 */ if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) { b43warn(dev->wl, "Invalid max-TX-power value in SPROM.\n"); max_pwr = INT_TO_Q52(20); /* fake it */ - dev->dev->bus->sprom.maxpwr_bg = max_pwr; + dev->sdev->bus->sprom.maxpwr_bg = max_pwr; } /* Get desired power (in Q5.2) */ @@ -3014,7 +3014,7 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; - if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) + if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) return; b43_mac_suspend(dev); diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index fd50eb1..012c8da 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -86,7 +86,7 @@ static void b43_lpphy_op_free(struct b43_wldev *dev) static void lpphy_read_band_sprom(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u16 cckpo, maxpwr; u32 ofdmpo; int i; @@ -214,7 +214,7 @@ static void lpphy_table_init(struct b43_wldev *dev) static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy_lp *lpphy = dev->phy.lp; u16 tmp, tmp2; @@ -412,7 +412,7 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy_lp *lpphy = dev->phy.lp; b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50); @@ -519,7 +519,7 @@ struct b2062_freqdata { static void lpphy_2062_init(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u32 crystalfreq, tmp, ref; unsigned int i; const struct b2062_freqdata *fd = NULL; @@ -697,7 +697,7 @@ static void lpphy_radio_init(struct b43_wldev *dev) lpphy_sync_stx(dev); b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80); b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0); - if (dev->dev->bus->chip_id == 0x4325) { + if (dev->sdev->bus->chip_id == 0x4325) { // TODO SSB PMU recalibration } } @@ -1289,7 +1289,7 @@ finish: static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF; int i; @@ -1840,7 +1840,7 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains, static void lpphy_papd_cal_txpwr(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct lpphy_tx_gains gains, oldgains; int old_txpctl, old_afe_ovr, old_rf, old_bbmult; @@ -1870,7 +1870,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx, bool rx, bool pa, struct lpphy_tx_gains *gains) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; const struct lpphy_rx_iq_comp *iqcomp = NULL; struct lpphy_tx_gains nogains, oldgains; u16 tmp; @@ -2408,7 +2408,7 @@ static const struct b206x_channel b2063_chantbl[] = { static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF); udelay(20); @@ -2432,7 +2432,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev, unsigned int channel) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; const struct b206x_channel *chandata = NULL; u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; @@ -2522,7 +2522,7 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev) static int lpphy_b2063_tune(struct b43_wldev *dev, unsigned int channel) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; static const struct b206x_channel *chandata = NULL; u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index b075a3f..9ed6515 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -299,7 +299,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) static void b43_nphy_tx_power_fix(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); u8 txpi[2], bbmult, i; u16 tmp, radio_gain, dac_gain; @@ -423,8 +423,8 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev) static void b43_radio_init2055_post(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); - struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); + struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); + struct ssb_boardinfo *binfo = &(dev->sdev->bus->boardinfo); int i; u16 val; bool workaround = false; @@ -609,12 +609,12 @@ static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) if (dev->phy.type != B43_PHYTYPE_N) return; - tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); if (force) tmslow |= SSB_TMSLOW_FGC; else tmslow &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); + ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ @@ -959,7 +959,7 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0); b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0); - ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00, + ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00, 0xFC00); b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) & @@ -983,7 +983,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) { u16 tmp; - if (dev->dev->id.revision == 16) + if (dev->sdev->id.revision == 16) b43_mac_suspend(dev); tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL); @@ -993,7 +993,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) tmp |= (val & mask); b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp); - if (dev->dev->id.revision == 16) + if (dev->sdev->id.revision == 16) b43_mac_enable(dev); return tmp; @@ -1168,7 +1168,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); + struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); /* PHY rev 0, 1, 2 */ u8 i, j; @@ -1373,7 +1373,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ static void b43_nphy_workarounds(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = phy->n; @@ -3586,7 +3586,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) */ int b43_phy_initn(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = phy->n; u8 tx_pwr_state; @@ -3601,7 +3601,7 @@ int b43_phy_initn(struct b43_wldev *dev) if ((dev->phy.rev >= 3) && (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) { - chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); + chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); } nphy->deaf_count = 0; b43_nphy_tables_init(dev); diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index aa12273..72ab94d 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -111,7 +111,7 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev, B43_MMIO_PIO11_BASE5, }; - if (dev->dev->id.revision >= 11) { + if (dev->sdev->id.revision >= 11) { B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11)); return bases_rev11[index]; } @@ -121,14 +121,14 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev, static u16 pio_txqueue_offset(struct b43_wldev *dev) { - if (dev->dev->id.revision >= 11) + if (dev->sdev->id.revision >= 11) return 0x18; return 0; } static u16 pio_rxqueue_offset(struct b43_wldev *dev) { - if (dev->dev->id.revision >= 11) + if (dev->sdev->id.revision >= 11) return 0x38; return 8; } @@ -144,7 +144,7 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev, if (!q) return NULL; q->dev = dev; - q->rev = dev->dev->id.revision; + q->rev = dev->sdev->id.revision; q->mmio_base = index_to_pioqueue_base(dev, index) + pio_txqueue_offset(dev); q->index = index; @@ -178,7 +178,7 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev, if (!q) return NULL; q->dev = dev; - q->rev = dev->dev->id.revision; + q->rev = dev->sdev->id.revision; q->mmio_base = index_to_pioqueue_base(dev, index) + pio_rxqueue_offset(dev); @@ -339,7 +339,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; b43_piotx_write16(q, B43_PIO_TXCTL, ctl); - ssb_block_write(dev->dev, data, (data_len & ~1), + b43_block_write(dev, data, (data_len & ~1), q->mmio_base + B43_PIO_TXDATA, sizeof(u16)); if (data_len & 1) { @@ -351,7 +351,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, b43_piotx_write16(q, B43_PIO_TXCTL, ctl); tail[0] = data[data_len - 1]; tail[1] = 0; - ssb_block_write(dev->dev, tail, 2, + b43_block_write(dev, tail, 2, q->mmio_base + B43_PIO_TXDATA, sizeof(u16)); } @@ -393,7 +393,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - ssb_block_write(dev->dev, data, (data_len & ~3), + b43_block_write(dev, data, (data_len & ~3), q->mmio_base + B43_PIO8_TXDATA, sizeof(u32)); if (data_len & 3) { @@ -421,7 +421,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, break; } b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - ssb_block_write(dev->dev, tail, 4, + b43_block_write(dev, tail, 4, q->mmio_base + B43_PIO8_TXDATA, sizeof(u32)); } @@ -657,11 +657,11 @@ data_ready: /* Get the preamble (RX header) */ if (q->rev >= 8) { - ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr), + b43_block_read(dev, rxhdr, sizeof(*rxhdr), q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); } else { - ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr), + b43_block_read(dev, rxhdr, sizeof(*rxhdr), q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); } @@ -697,7 +697,7 @@ data_ready: skb_reserve(skb, 2); skb_put(skb, len + padding); if (q->rev >= 8) { - ssb_block_read(dev->dev, skb->data + padding, (len & ~3), + b43_block_read(dev, skb->data + padding, (len & ~3), q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); if (len & 3) { @@ -705,7 +705,7 @@ data_ready: BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); /* Read the last few bytes. */ - ssb_block_read(dev->dev, tail, 4, + b43_block_read(dev, tail, 4, q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); switch (len & 3) { @@ -724,7 +724,7 @@ data_ready: } } } else { - ssb_block_read(dev->dev, skb->data + padding, (len & ~1), + b43_block_read(dev, skb->data + padding, (len & ~1), q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); if (len & 1) { @@ -732,7 +732,7 @@ data_ready: BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); /* Read the last byte. */ - ssb_block_read(dev->dev, tail, 2, + b43_block_read(dev, tail, 2, q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); skb->data[len + padding - 1] = tail[0]; diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 86bc0a0..a617efe 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -37,7 +37,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; bool enabled; bool brought_up = false; @@ -47,7 +47,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw) mutex_unlock(&wl->mutex); return; } - ssb_device_enable(dev->dev, 0); + ssb_device_enable(dev->sdev, 0); brought_up = true; } @@ -63,7 +63,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw) } if (brought_up) { - ssb_device_disable(dev->dev, 0); + ssb_device_disable(dev->sdev, 0); ssb_bus_may_powerdown(bus); } diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c index 09e2dfd..808e25b 100644 --- a/drivers/net/wireless/b43/sdio.c +++ b/drivers/net/wireless/b43/sdio.c @@ -66,7 +66,7 @@ static void b43_sdio_interrupt_dispatcher(struct sdio_func *func) int b43_sdio_request_irq(struct b43_wldev *dev, void (*handler)(struct b43_wldev *dev)) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct sdio_func *func = bus->host_sdio; struct b43_sdio *sdio = sdio_get_drvdata(func); int err; @@ -82,7 +82,7 @@ int b43_sdio_request_irq(struct b43_wldev *dev, void b43_sdio_free_irq(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct sdio_func *func = bus->host_sdio; struct b43_sdio *sdio = sdio_get_drvdata(func); diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c index f1ae4e0..57af619 100644 --- a/drivers/net/wireless/b43/sysfs.c +++ b/drivers/net/wireless/b43/sysfs.c @@ -140,7 +140,7 @@ static DEVICE_ATTR(interference, 0644, int b43_sysfs_register(struct b43_wldev *wldev) { - struct device *dev = wldev->dev->dev; + struct device *dev = wldev->sdev->dev; B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); @@ -149,7 +149,7 @@ int b43_sysfs_register(struct b43_wldev *wldev) void b43_sysfs_unregister(struct b43_wldev *wldev) { - struct device *dev = wldev->dev->dev; + struct device *dev = wldev->sdev->dev; device_remove_file(dev, &dev_attr_interference); } diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c index 61027ee..59df3c6 100644 --- a/drivers/net/wireless/b43/tables_lpphy.c +++ b/drivers/net/wireless/b43/tables_lpphy.c @@ -2304,7 +2304,7 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev) void lpphy_rev2plus_table_init(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; int i; B43_WARN_ON(dev->phy.rev < 2); @@ -2416,7 +2416,7 @@ void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count, void lpphy_init_tx_gain_table(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; switch (dev->phy.rev) { case 0: diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index 9a335da..8f4db44 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c @@ -458,7 +458,7 @@ static void b43_wa_rssi_adc(struct b43_wldev *dev) static void b43_wa_boards_a(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && bus->boardinfo.type == SSB_BOARD_BU4306 && @@ -486,7 +486,7 @@ static void b43_wa_boards_a(struct b43_wldev *dev) static void b43_wa_boards_g(struct b43_wldev *dev) { - struct ssb_bus *bus = dev->dev->bus; + struct ssb_bus *bus = dev->sdev->bus; struct b43_phy *phy = &dev->phy; if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM || diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index e5be381..c8f99ae 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -547,7 +547,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev, else tmp -= 3; } else { - if (dev->dev->bus->sprom. + if (dev->sdev->bus->sprom. boardflags_lo & B43_BFL_RSSI) { if (in_rssi > 63) in_rssi = 63; diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 2176ede..c052a0d 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -620,7 +620,7 @@ static int hostap_cs_resume(struct pcmcia_device *link) return 0; } -static struct pcmcia_device_id hostap_cs_ids[] = { +static const struct pcmcia_device_id hostap_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index b4c8193..61d4a11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -171,10 +171,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) static struct iwl_lib_ops iwl1000_lib = { .set_hw_params = iwl1000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 89b8da7..86feec8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -195,9 +195,9 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = sizeof(cmd), + .len = { sizeof(cmd), }, .flags = CMD_SYNC, - .data = &cmd, + .data = { &cmd, }, }; cmd.band = priv->band == IEEE80211_BAND_2GHZ; @@ -252,10 +252,6 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl2000_lib = { .set_hw_params = iwl2000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 98f81df..a70b8cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -282,9 +282,9 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = sizeof(cmd), + .len = { sizeof(cmd), }, .flags = CMD_SYNC, - .data = &cmd, + .data = { &cmd, }, }; cmd.band = priv->band == IEEE80211_BAND_2GHZ; @@ -339,10 +339,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl5000_lib = { .set_hw_params = iwl5000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, @@ -374,10 +370,6 @@ static struct iwl_lib_ops iwl5000_lib = { static struct iwl_lib_ops iwl5150_lib = { .set_hw_params = iwl5150_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a7921f9a..f8c710d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -221,9 +221,9 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = sizeof(cmd), + .len = { sizeof(cmd), }, .flags = CMD_SYNC, - .data = &cmd, + .data = { &cmd, }, }; cmd.band = priv->band == IEEE80211_BAND_2GHZ; @@ -278,10 +278,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, static struct iwl_lib_ops iwl6000_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_rx_handler_setup, .setup_deferred_work = iwlagn_setup_deferred_work, .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, @@ -314,10 +310,6 @@ static struct iwl_lib_ops iwl6000_lib = { static struct iwl_lib_ops iwl6030_lib = { .set_hw_params = iwl6000_hw_set_hw_params, - .txq_set_sched = iwlagn_txq_set_sched, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, .rx_handler_setup = iwlagn_bt_rx_handler_setup, .setup_deferred_work = iwlagn_bt_setup_deferred_work, .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 39d1e47..c9255de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -87,14 +87,14 @@ int iwl_send_calib_results(struct iwl_priv *priv) struct iwl_host_cmd hcmd = { .id = REPLY_PHY_CALIBRATION_CMD, - .flags = CMD_SIZE_HUGE, }; for (i = 0; i < IWL_CALIB_MAX; i++) { if ((BIT(i) & priv->hw_params.calib_init_cfg) && priv->calib_results[i].buf) { - hcmd.len = priv->calib_results[i].buf_len; - hcmd.data = priv->calib_results[i].buf; + hcmd.len[0] = priv->calib_results[i].buf_len; + hcmd.data[0] = priv->calib_results[i].buf; + hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; ret = iwl_send_cmd_sync(priv, &hcmd); if (ret) { IWL_ERR(priv, "Error %d iteration %d\n", @@ -456,9 +456,9 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) struct iwl_sensitivity_data *data = NULL; struct iwl_host_cmd cmd_out = { .id = SENSITIVITY_CMD, - .len = sizeof(struct iwl_sensitivity_cmd), + .len = { sizeof(struct iwl_sensitivity_cmd), }, .flags = CMD_ASYNC, - .data = &cmd, + .data = { &cmd, }, }; data = &(priv->sensitivity_data); @@ -491,9 +491,9 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) struct iwl_sensitivity_data *data = NULL; struct iwl_host_cmd cmd_out = { .id = SENSITIVITY_CMD, - .len = sizeof(struct iwl_enhance_sensitivity_cmd), + .len = { sizeof(struct iwl_enhance_sensitivity_cmd), }, .flags = CMD_ASYNC, - .data = &cmd, + .data = { &cmd, }, }; data = &(priv->sensitivity_data); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 8e79653..f803fb6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1140,8 +1140,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) { struct iwl_host_cmd cmd = { .id = REPLY_SCAN_CMD, - .len = sizeof(struct iwl_scan_cmd), - .flags = CMD_SIZE_HUGE, + .len = { sizeof(struct iwl_scan_cmd), }, }; struct iwl_scan_cmd *scan; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; @@ -1425,10 +1424,11 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) return -EIO; } - cmd.len += le16_to_cpu(scan->tx_cmd.len) + + cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl_scan_channel); - cmd.data = scan; - scan->len = cpu_to_le16(cmd.len); + cmd.data[0] = scan; + cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; + scan->len = cpu_to_le16(cmd.len[0]); /* set scan bit here for PAN params */ set_bit(STATUS_SCAN_HW, &priv->status); @@ -1520,9 +1520,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) struct iwl_txfifo_flush_cmd flush_cmd; struct iwl_host_cmd cmd = { .id = REPLY_TXFIFO_FLUSH, - .len = sizeof(struct iwl_txfifo_flush_cmd), + .len = { sizeof(struct iwl_txfifo_flush_cmd), }, .flags = CMD_SYNC, - .data = &flush_cmd, + .data = { &flush_cmd, }, }; might_sleep(); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 91f2655..592b0cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -335,6 +335,32 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, return tid; } +#ifdef CONFIG_MAC80211_DEBUGFS +static void rs_program_fix_rate(struct iwl_priv *priv, + struct iwl_lq_sta *lq_sta) +{ + struct iwl_station_priv *sta_priv = + container_of(lq_sta, struct iwl_station_priv, lq_sta); + struct iwl_rxon_context *ctx = sta_priv->common.ctx; + + lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ + lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ + lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ + lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ + + lq_sta->dbg_fixed_rate = priv->dbg_fixed_rate; + + IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", + lq_sta->lq.sta_id, priv->dbg_fixed_rate); + + if (priv->dbg_fixed_rate) { + rs_fill_link_cmd(NULL, lq_sta, priv->dbg_fixed_rate); + iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, + false); + } +} +#endif + /* get the traffic load value for tid */ @@ -1046,7 +1072,10 @@ done: /* See if there's a better rate or modulation mode to try. */ if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); - +#ifdef CONFIG_MAC80211_DEBUGFS + if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate) + rs_program_fix_rate(priv, lq_sta); +#endif if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) rs_bt_update_lq(priv, ctx, lq_sta); } @@ -2170,11 +2199,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) * setup rate table in uCode * return rate_n_flags as used in the table */ -static u32 rs_update_rate_tbl(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl, - int index, u8 is_green) +static void rs_update_rate_tbl(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + int index, u8 is_green) { u32 rate; @@ -2182,8 +2211,6 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); rs_fill_link_cmd(priv, lq_sta, rate); iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false); - - return rate; } /* @@ -2212,7 +2239,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, u8 update_lq = 0; struct iwl_scale_tbl_info *tbl, *tbl1; u16 rate_scale_index_msk = 0; - u32 rate; u8 is_green = 0; u8 active_tbl = 0; u8 done_search = 0; @@ -2299,8 +2325,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); /* get "active" rate info */ index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - rate = rs_update_rate_tbl(priv, ctx, lq_sta, - tbl, index, is_green); + rs_update_rate_tbl(priv, ctx, lq_sta, tbl, + index, is_green); } return; } @@ -2541,8 +2567,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, lq_update: /* Replace uCode's rate table for the destination station. */ if (update_lq) - rate = rs_update_rate_tbl(priv, ctx, lq_sta, - tbl, index, is_green); + rs_update_rate_tbl(priv, ctx, lq_sta, tbl, index, is_green); if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { /* Should we stay with this modulation mode, @@ -2871,6 +2896,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; + priv->dbg_fixed_rate = 0; #ifdef CONFIG_MAC80211_DEBUGFS lq_sta->dbg_fixed_rate = 0; #endif @@ -3045,7 +3071,6 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, IWL_DEBUG_RATE(priv, "leave\n"); } - #ifdef CONFIG_MAC80211_DEBUGFS static int open_file_generic(struct inode *inode, struct file *file) { @@ -3070,6 +3095,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); } else { lq_sta->dbg_fixed_rate = 0; + priv->dbg_fixed_rate = 0; IWL_ERR(priv, "Invalid antenna selection 0x%X, Valid is 0x%X\n", ant_sel_tx, valid_tx_ant); @@ -3088,9 +3114,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, char buf[64]; size_t buf_size; u32 parsed_rate; - struct iwl_station_priv *sta_priv = - container_of(lq_sta, struct iwl_station_priv, lq_sta); - struct iwl_rxon_context *ctx = sta_priv->common.ctx; + priv = lq_sta->drv; memset(buf, 0, sizeof(buf)); @@ -3099,23 +3123,11 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, return -EFAULT; if (sscanf(buf, "%x", &parsed_rate) == 1) - lq_sta->dbg_fixed_rate = parsed_rate; + priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = parsed_rate; else - lq_sta->dbg_fixed_rate = 0; + priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = 0; - lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ - lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - - IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", - lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); - - if (lq_sta->dbg_fixed_rate) { - rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); - iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, - false); - } + rs_program_fix_rate(priv, lq_sta); return count; } @@ -3143,7 +3155,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, lq_sta->total_failed, lq_sta->total_success, lq_sta->active_legacy_rate); desc += sprintf(buff+desc, "fixed rate 0x%X\n", - lq_sta->dbg_fixed_rate); + priv->dbg_fixed_rate); desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", @@ -3254,14 +3266,10 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = { static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - char buff[120]; - int desc = 0; - struct iwl_lq_sta *lq_sta = file->private_data; - struct iwl_priv *priv; struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; - - priv = lq_sta->drv; + char buff[120]; + int desc = 0; if (is_Ht(tbl->lq_type)) desc += sprintf(buff+desc, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 0238743..a95ad84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -289,7 +289,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) /* cast away the const for active_rxon in this function */ struct iwl_rxon_cmd *active = (void *)&ctx->active; bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK); - bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK); int ret; lockdep_assert_held(&priv->mutex); @@ -389,11 +388,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) * AP station must be done after the BSSID is set to correctly * set up filters in the device. */ - if ((old_assoc && new_assoc) || !new_assoc) { - ret = iwlagn_rxon_disconn(priv, ctx); - if (ret) - return ret; - } + ret = iwlagn_rxon_disconn(priv, ctx); + if (ret) + return ret; if (new_assoc) return iwlagn_rxon_connect(priv, ctx); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 079275f..0bd722c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -144,7 +144,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, size_t cmd_size = sizeof(struct iwl_wep_cmd); struct iwl_host_cmd cmd = { .id = ctx->wep_key_cmd, - .data = wep_cmd, + .data = { wep_cmd, }, .flags = CMD_SYNC, }; @@ -172,7 +172,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX; - cmd.len = cmd_size; + cmd.len[0] = cmd_size; if (not_empty || send_if_empty) return iwl_send_cmd(priv, &cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 342de78..4974cd7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -755,12 +755,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) spin_unlock(&priv->sta_lock); /* Attach buffers to TFD */ - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - txcmd_phys, firstlen, 1, 0); + iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1); if (secondlen > 0) - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, secondlen, - 0, 0); + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, + secondlen, 0); scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl_tx_cmd, scratch); @@ -916,7 +914,7 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); /* Turn off all Tx DMA fifos */ - priv->cfg->ops->lib->txq_set_sched(priv, 0); + iwlagn_txq_set_sched(priv, 0); /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); @@ -954,7 +952,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); /* Turn off all Tx DMA fifos */ - priv->cfg->ops->lib->txq_set_sched(priv, 0); + iwlagn_txq_set_sched(priv, 0); /* Tell NIC where to find the "keep warm" buffer */ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); @@ -980,7 +978,7 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) /* Turn off all Tx DMA fifos */ spin_lock_irqsave(&priv->lock, flags); - priv->cfg->ops->lib->txq_set_sched(priv, 0); + iwlagn_txq_set_sched(priv, 0); /* Stop each Tx DMA channel, and wait for it to be idle */ for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { @@ -1263,7 +1261,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) iwlagn_txq_inval_byte_cnt_tbl(priv, txq); - priv->cfg->ops->lib->txq_free_tfd(priv, txq); + iwlagn_txq_free_tfd(priv, txq); } return nfreed; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 8bda0e8..97de5d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -217,8 +217,8 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv) struct iwl_calib_cfg_cmd calib_cfg_cmd; struct iwl_host_cmd cmd = { .id = CALIBRATION_CFG_CMD, - .len = sizeof(struct iwl_calib_cfg_cmd), - .data = &calib_cfg_cmd, + .len = { sizeof(struct iwl_calib_cfg_cmd), }, + .data = { &calib_cfg_cmd, }, }; memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); @@ -440,7 +440,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) IWL_MASK(0, priv->hw_params.max_txq_num)); /* Activate all Tx DMA/FIFO channels */ - priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); + iwlagn_txq_set_sched(priv, IWL_MASK(0, 7)); /* map queues to FIFOs */ if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 08e3cae..11c6c11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -134,12 +134,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) struct iwl_tx_beacon_cmd *tx_beacon_cmd; struct iwl_host_cmd cmd = { .id = REPLY_TX_BEACON, - .flags = CMD_SIZE_HUGE, }; u32 frame_size; u32 rate_flags; u32 rate; - int err; /* * We have to set up the TX command, the TX Beacon command, and the @@ -156,17 +154,15 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) if (WARN_ON(!priv->beacon_skb)) return -EINVAL; - /* Allocate beacon memory */ - tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len, - GFP_KERNEL); + /* Allocate beacon command */ + if (!priv->beacon_cmd) + priv->beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd), GFP_KERNEL); + tx_beacon_cmd = priv->beacon_cmd; if (!tx_beacon_cmd) return -ENOMEM; frame_size = priv->beacon_skb->len; - /* Set up TX beacon contents */ - memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size); - /* Set up TX command fields */ tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; @@ -175,7 +171,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; /* Set up TX beacon command fields */ - iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, + iwl_set_beacon_tim(priv, tx_beacon_cmd, priv->beacon_skb->data, frame_size); /* Set up packet rate and flags */ @@ -189,164 +185,14 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) rate_flags); /* Submit command */ - cmd.len = sizeof(*tx_beacon_cmd) + frame_size; - cmd.data = tx_beacon_cmd; - - err = iwl_send_cmd_sync(priv, &cmd); - - /* Free temporary storage */ - kfree(tx_beacon_cmd); - - return err; -} - -static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + cmd.len[0] = sizeof(*tx_beacon_cmd); + cmd.data[0] = tx_beacon_cmd; + cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; + cmd.len[1] = frame_size; + cmd.data[1] = priv->beacon_skb->data; + cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; - dma_addr_t addr = get_unaligned_le32(&tb->lo); - if (sizeof(dma_addr_t) > sizeof(u32)) - addr |= - ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; - - return addr; -} - -static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - - return le16_to_cpu(tb->hi_n_len) >> 4; -} - -static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, - dma_addr_t addr, u16 len) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - u16 hi_n_len = len << 4; - - put_unaligned_le32(addr, &tb->lo); - if (sizeof(dma_addr_t) > sizeof(u32)) - hi_n_len |= ((addr >> 16) >> 16) & 0xF; - - tb->hi_n_len = cpu_to_le16(hi_n_len); - - tfd->num_tbs = idx + 1; -} - -static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) -{ - return tfd->num_tbs & 0x1f; -} - -/** - * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * @priv - driver private data - * @txq - tx queue - * - * Does NOT advance any TFD circular buffer read/write indexes - * Does NOT free the TFD itself (which is within circular buffer) - */ -void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ - struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; - struct iwl_tfd *tfd; - struct pci_dev *dev = priv->pci_dev; - int index = txq->q.read_ptr; - int i; - int num_tbs; - - tfd = &tfd_tmp[index]; - - /* Sanity check on number of chunks */ - num_tbs = iwl_tfd_get_num_tbs(tfd); - - if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); - /* @todo issue fatal error, it is quite serious situation */ - return; - } - - /* Unmap tx_cmd */ - if (num_tbs) - pci_unmap_single(dev, - dma_unmap_addr(&txq->meta[index], mapping), - dma_unmap_len(&txq->meta[index], len), - PCI_DMA_BIDIRECTIONAL); - - /* Unmap chunks, if any. */ - for (i = 1; i < num_tbs; i++) - pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), - iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); - - /* free SKB */ - if (txq->txb) { - struct sk_buff *skb; - - skb = txq->txb[txq->q.read_ptr].skb; - - /* can be called from irqs-disabled context */ - if (skb) { - dev_kfree_skb_any(skb); - txq->txb[txq->q.read_ptr].skb = NULL; - } - } -} - -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, - u8 reset, u8 pad) -{ - struct iwl_queue *q; - struct iwl_tfd *tfd, *tfd_tmp; - u32 num_tbs; - - q = &txq->q; - tfd_tmp = (struct iwl_tfd *)txq->tfds; - tfd = &tfd_tmp[q->write_ptr]; - - if (reset) - memset(tfd, 0, sizeof(*tfd)); - - num_tbs = iwl_tfd_get_num_tbs(tfd); - - /* Each TFD can point to a maximum 20 Tx buffers */ - if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Error can not send more than %d chunks\n", - IWL_NUM_OF_TBS); - return -EINVAL; - } - - if (WARN_ON(addr & ~DMA_BIT_MASK(36))) - return -EINVAL; - - if (unlikely(addr & ~IWL_TX_DMA_MASK)) - IWL_ERR(priv, "Unaligned address = %llx\n", - (unsigned long long)addr); - - iwl_tfd_set_tb(tfd, num_tbs, addr, len); - - return 0; -} - -/* - * Tell nic where to find circular buffer of Tx Frame Descriptors for - * given Tx queue, and enable the DMA channel used for that queue. - * - * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA - * channels supported in hardware. - */ -int iwl_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - int txq_id = txq->q.id; - - /* Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), - txq->q.dma_addr >> 8); - - return 0; + return iwl_send_cmd_sync(priv, &cmd); } static void iwl_bg_beacon_update(struct work_struct *work) @@ -1776,10 +1622,7 @@ static const char *desc_lookup(u32 num) void iwl_dump_nic_error_log(struct iwl_priv *priv) { - u32 data2, line; - u32 desc, time, count, base, data1; - u32 blink1, blink2, ilink1, ilink2; - u32 pc, hcmd; + u32 base; struct iwl_error_event_table table; base = priv->device_pointers.error_event_table; @@ -1802,37 +1645,40 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) iwl_read_targ_mem_words(priv, base, &table, sizeof(table)); - count = table.valid; - - if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { + if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { IWL_ERR(priv, "Start IWL Error Log Dump:\n"); IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", - priv->status, count); - } - - desc = table.error_id; - priv->isr_stats.err_code = desc; - pc = table.pc; - blink1 = table.blink1; - blink2 = table.blink2; - ilink1 = table.ilink1; - ilink2 = table.ilink2; - data1 = table.data1; - data2 = table.data2; - line = table.line; - time = table.tsf_low; - hcmd = table.hcmd; - - trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, - blink1, blink2, ilink1, ilink2); - - IWL_ERR(priv, "Desc Time " - "data1 data2 line\n"); - IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n", - desc_lookup(desc), desc, time, data1, data2, line); - IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); - IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", - pc, blink1, blink2, ilink1, ilink2, hcmd); + priv->status, table.valid); + } + + priv->isr_stats.err_code = table.error_id; + + trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low, + table.data1, table.data2, table.line, + table.blink1, table.blink2, table.ilink1, + table.ilink2, table.bcon_time, table.gp1, + table.gp2, table.gp3, table.ucode_ver, + table.hw_ver, table.brd_ver); + IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, + desc_lookup(table.error_id)); + IWL_ERR(priv, "0x%08X | uPc\n", table.pc); + IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1); + IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2); + IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1); + IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2); + IWL_ERR(priv, "0x%08X | data1\n", table.data1); + IWL_ERR(priv, "0x%08X | data2\n", table.data2); + IWL_ERR(priv, "0x%08X | line\n", table.line); + IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time); + IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low); + IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi); + IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1); + IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2); + IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3); + IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver); + IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver); + IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver); + IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd); } #define EVENT_START_OFFSET (4 * sizeof(u32)) @@ -2114,8 +1960,8 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) struct iwl_calib_cfg_cmd calib_cfg_cmd; struct iwl_host_cmd cmd = { .id = CALIBRATION_CFG_CMD, - .len = sizeof(struct iwl_calib_cfg_cmd), - .data = &calib_cfg_cmd, + .len = { sizeof(struct iwl_calib_cfg_cmd), }, + .data = { &calib_cfg_cmd, }, }; memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); @@ -3395,6 +3241,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv) iwlcore_free_geos(priv); iwl_free_channel_map(priv); kfree(priv->scan_cmd); + kfree(priv->beacon_cmd); } struct ieee80211_ops iwlagn_hw_ops = { @@ -3812,6 +3659,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) */ set_bit(STATUS_EXIT_PENDING, &priv->status); + iwl_testmode_cleanup(priv); iwl_leds_exit(priv); if (priv->mac80211_registered) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index fe33fe8..2495fe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -191,12 +191,10 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); void iwl_setup_rx_handlers(struct iwl_priv *priv); /* tx */ -void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, u8 reset, u8 pad); -int iwl_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq); + dma_addr_t addr, u16 len, u8 reset); void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); @@ -345,6 +343,7 @@ extern int iwl_alive_start(struct iwl_priv *priv); #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); extern void iwl_testmode_init(struct iwl_priv *priv); +extern void iwl_testmode_cleanup(struct iwl_priv *priv); #else static inline int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) @@ -355,6 +354,10 @@ static inline void iwl_testmode_init(struct iwl_priv *priv) { } +static inline +void iwl_testmode_cleanup(struct iwl_priv *priv) +{ +} #endif #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 5fdad65..6ee5f1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -205,7 +205,6 @@ enum { #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) #define SEQ_TO_INDEX(s) ((s) & 0xff) #define INDEX_TO_SEQ(i) ((i) & 0xff) -#define SEQ_HUGE_FRAME cpu_to_le16(0x4000) #define SEQ_RX_FRAME cpu_to_le16(0x8000) /** @@ -234,9 +233,7 @@ struct iwl_cmd_header { * * 0:7 tfd index - position within TX queue * 8:12 TX queue id - * 13 reserved - * 14 huge - driver sets this to indicate command is in the - * 'huge' storage at the end of the command buffers + * 13:14 reserved * 15 unsolicited RX or uCode-originated notification */ __le16 sequence; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5b5b0cce..3bb76f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -127,16 +127,6 @@ struct iwl_temp_ops { struct iwl_lib_ops { /* set hw dependent parameters */ int (*set_hw_params)(struct iwl_priv *priv); - /* Handling TX */ - void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); - int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, - u16 len, u8 reset, u8 pad); - void (*txq_free_tfd)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); - int (*txq_init)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); /* setup Rx handler */ void (*rx_handler_setup)(struct iwl_priv *priv); /* setup deferred work */ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 214e465..22a6e3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -48,8 +48,6 @@ #include "iwl-agn-rs.h" #include "iwl-agn-tt.h" -#define U32_PAD(n) ((4-(n))&0x3) - struct iwl_tx_queue; /* CT-KILL constants */ @@ -83,7 +81,7 @@ struct iwl_tx_queue; #define MAX_RTS_THRESHOLD 2347U #define MAX_MSDU_SIZE 2304U #define MAX_MPDU_SIZE 2346U -#define DEFAULT_BEACON_INTERVAL 100U +#define DEFAULT_BEACON_INTERVAL 200U #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U @@ -112,8 +110,6 @@ struct iwl_cmd_meta { struct iwl_device_cmd *cmd, struct iwl_rx_packet *pkt); - /* The CMD_SIZE_HUGE flag bit indicates that the command - * structure is stored at the end of the shared queue memory. */ u32 flags; DEFINE_DMA_UNMAP_ADDR(mapping); @@ -123,7 +119,23 @@ struct iwl_cmd_meta { /* * Generic queue structure * - * Contains common data for Rx and Tx queues + * Contains common data for Rx and Tx queues. + * + * Note the difference between n_bd and n_window: the hardware + * always assumes 256 descriptors, so n_bd is always 256 (unless + * there might be HW changes in the future). For the normal TX + * queues, n_window, which is the size of the software queue data + * is also 256; however, for the command queue, n_window is only + * 32 since we don't need so many commands pending. Since the HW + * still uses 256 BDs for DMA though, n_bd stays 256. As a result, + * the software buffers (in the variables @meta, @txb in struct + * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds + * in the same struct) have 256. + * This means that we end up with the following: + * HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 | + * SW entries: | 0 | ... | 31 | + * where N is a number between 0 and 7. This means that the SW + * data is a window overlayed over the HW queue. */ struct iwl_queue { int n_bd; /* number of BDs in this queue */ @@ -165,7 +177,7 @@ struct iwl_tx_info { struct iwl_tx_queue { struct iwl_queue q; - void *tfds; + struct iwl_tfd *tfds; struct iwl_device_cmd **cmd; struct iwl_cmd_meta *meta; struct iwl_tx_info *txb; @@ -247,7 +259,6 @@ enum { CMD_SYNC = 0, CMD_SIZE_NORMAL = 0, CMD_NO_SKB = 0, - CMD_SIZE_HUGE = (1 << 0), CMD_ASYNC = (1 << 1), CMD_WANT_SKB = (1 << 2), CMD_MAPPED = (1 << 3), @@ -259,8 +270,8 @@ enum { * struct iwl_device_cmd * * For allocation of the command and tx queues, this establishes the overall - * size of the largest command we send to uCode, except for a scan command - * (which is relatively huge; space is allocated separately). + * size of the largest command we send to uCode, except for commands that + * aren't fully copied and use other TFD space. */ struct iwl_device_cmd { struct iwl_cmd_header hdr; /* uCode API */ @@ -277,15 +288,21 @@ struct iwl_device_cmd { #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) +#define IWL_MAX_CMD_TFDS 2 + +enum iwl_hcmd_dataflag { + IWL_HCMD_DFL_NOCOPY = BIT(0), +}; struct iwl_host_cmd { - const void *data; + const void *data[IWL_MAX_CMD_TFDS]; unsigned long reply_page; void (*callback)(struct iwl_priv *priv, struct iwl_device_cmd *cmd, struct iwl_rx_packet *pkt); u32 flags; - u16 len; + u16 len[IWL_MAX_CMD_TFDS]; + u8 dataflags[IWL_MAX_CMD_TFDS]; u8 id; }; @@ -688,17 +705,8 @@ static inline int iwl_queue_used(const struct iwl_queue *q, int i) } -static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) +static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) { - /* - * This is for init calibration result and scan command which - * required buffer > TFD_MAX_PAYLOAD_SIZE, - * the big buffer at end of command array - */ - if (is_huge) - return q->n_window; /* must be power of 2 */ - - /* Otherwise, use normal size buffers */ return index & (q->n_window - 1); } @@ -1171,6 +1179,14 @@ enum iwl_scan_type { IWL_SCAN_OFFCH_TX, }; +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL +struct iwl_testmode_trace { + u8 *cpu_addr; + u8 *trace_addr; + dma_addr_t dma_addr; + bool trace_enabled; +}; +#endif struct iwl_priv { /* ieee device used by generic ieee processing code */ @@ -1452,6 +1468,7 @@ struct iwl_priv { struct work_struct beacon_update; struct iwl_rxon_context *beacon_ctx; struct sk_buff *beacon_skb; + void *beacon_cmd; struct work_struct tt_work; struct work_struct ct_enter; @@ -1501,6 +1518,11 @@ struct iwl_priv { struct led_classdev led; unsigned long blink_on, blink_off; bool led_registered; +#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL + struct iwl_testmode_trace testmode_trace; +#endif + u32 dbg_fixed_rate; + }; /*iwl_priv */ static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index f00172c..2c84ba95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -137,20 +137,27 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, #define TRACE_SYSTEM iwlwifi TRACE_EVENT(iwlwifi_dev_hcmd, - TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags), - TP_ARGS(priv, hcmd, len, flags), + TP_PROTO(struct iwl_priv *priv, u32 flags, + const void *hcmd0, size_t len0, + const void *hcmd1, size_t len1, + const void *hcmd2, size_t len2), + TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2), TP_STRUCT__entry( PRIV_ENTRY - __dynamic_array(u8, hcmd, len) + __dynamic_array(u8, hcmd0, len0) + __dynamic_array(u8, hcmd1, len1) + __dynamic_array(u8, hcmd2, len2) __field(u32, flags) ), TP_fast_assign( PRIV_ASSIGN; - memcpy(__get_dynamic_array(hcmd), hcmd, len); + memcpy(__get_dynamic_array(hcmd0), hcmd0, len0); + memcpy(__get_dynamic_array(hcmd1), hcmd1, len1); + memcpy(__get_dynamic_array(hcmd2), hcmd2, len2); __entry->flags = flags; ), TP_printk("[%p] hcmd %#.2x (%ssync)", - __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0], + __entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0], __entry->flags & CMD_ASYNC ? "a" : "") ); @@ -202,15 +209,18 @@ TRACE_EVENT(iwlwifi_dev_tx, ); TRACE_EVENT(iwlwifi_dev_ucode_error, - TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time, + TP_PROTO(struct iwl_priv *priv, u32 desc, u32 tsf_low, u32 data1, u32 data2, u32 line, u32 blink1, - u32 blink2, u32 ilink1, u32 ilink2), - TP_ARGS(priv, desc, time, data1, data2, line, - blink1, blink2, ilink1, ilink2), + u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time, + u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver, + u32 brd_ver), + TP_ARGS(priv, desc, tsf_low, data1, data2, line, + blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2, + gp3, ucode_ver, hw_ver, brd_ver), TP_STRUCT__entry( PRIV_ENTRY __field(u32, desc) - __field(u32, time) + __field(u32, tsf_low) __field(u32, data1) __field(u32, data2) __field(u32, line) @@ -218,11 +228,18 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, __field(u32, blink2) __field(u32, ilink1) __field(u32, ilink2) + __field(u32, bcon_time) + __field(u32, gp1) + __field(u32, gp2) + __field(u32, gp3) + __field(u32, ucode_ver) + __field(u32, hw_ver) + __field(u32, brd_ver) ), TP_fast_assign( PRIV_ASSIGN; __entry->desc = desc; - __entry->time = time; + __entry->tsf_low = tsf_low; __entry->data1 = data1; __entry->data2 = data2; __entry->line = line; @@ -230,12 +247,25 @@ TRACE_EVENT(iwlwifi_dev_ucode_error, __entry->blink2 = blink2; __entry->ilink1 = ilink1; __entry->ilink2 = ilink2; + __entry->bcon_time = bcon_time; + __entry->gp1 = gp1; + __entry->gp2 = gp2; + __entry->gp3 = gp3; + __entry->ucode_ver = ucode_ver; + __entry->hw_ver = hw_ver; + __entry->brd_ver = brd_ver; ), TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, " - "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X", - __entry->priv, __entry->desc, __entry->time, __entry->data1, + "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X " + "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X " + "hw 0x%08X brd 0x%08X", + __entry->priv, __entry->desc, __entry->tsf_low, + __entry->data1, __entry->data2, __entry->line, __entry->blink1, - __entry->blink2, __entry->ilink1, __entry->ilink2) + __entry->blink2, __entry->ilink1, __entry->ilink2, + __entry->bcon_time, __entry->gp1, __entry->gp2, + __entry->gp3, __entry->ucode_ver, __entry->hw_ver, + __entry->brd_ver) ); TRACE_EVENT(iwlwifi_dev_ucode_event, diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index c839796..47a56bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -216,15 +216,14 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv) static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) { - u32 otpgp; + iwl_read32(priv, CSR_OTP_GP_REG); - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (mode == IWL_OTP_ACCESS_ABSOLUTE) iwl_clear_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_OTP_ACCESS_MODE); + CSR_OTP_GP_REG_OTP_ACCESS_MODE); else iwl_set_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_OTP_ACCESS_MODE); + CSR_OTP_GP_REG_OTP_ACCESS_MODE); } static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8f0beb9..76f9966 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -188,6 +188,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) cmd_idx = iwl_enqueue_hcmd(priv, cmd); if (cmd_idx < 0) { ret = cmd_idx; + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", get_cmd_string(cmd->id), ret); return ret; @@ -264,8 +265,8 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) { struct iwl_host_cmd cmd = { .id = id, - .len = len, - .data = data, + .len = { len, }, + .data = { data, }, }; return iwl_send_cmd_sync(priv, &cmd); @@ -279,8 +280,8 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, { struct iwl_host_cmd cmd = { .id = id, - .len = len, - .data = data, + .len = { len, }, + .data = { data, }, }; cmd.flags |= CMD_ASYNC; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 439187f..7c23beb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -107,8 +107,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) { struct iwl_host_cmd cmd = { .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl_led_cmd), - .data = led_cmd, + .len = { sizeof(struct iwl_led_cmd), }, + .data = { led_cmd, }, .flags = CMD_ASYNC, .callback = NULL, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 3c8cebd..7df2814 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -141,7 +141,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_host_cmd cmd = { .id = REPLY_ADD_STA, .flags = flags, - .data = data, + .data = { data, }, }; u8 sta_id __maybe_unused = sta->sta.sta_id; @@ -155,7 +155,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, might_sleep(); } - cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); + cmd.len[0] = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); ret = iwl_send_cmd(priv, &cmd); if (ret || (flags & CMD_ASYNC)) @@ -401,9 +401,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, struct iwl_host_cmd cmd = { .id = REPLY_REMOVE_STA, - .len = sizeof(struct iwl_rem_sta_cmd), + .len = { sizeof(struct iwl_rem_sta_cmd), }, .flags = CMD_SYNC, - .data = &rm_sta_cmd, + .data = { &rm_sta_cmd, }, }; memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); @@ -760,9 +760,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_host_cmd cmd = { .id = REPLY_TX_LINK_QUALITY_CMD, - .len = sizeof(struct iwl_link_quality_cmd), + .len = { sizeof(struct iwl_link_quality_cmd), }, .flags = flags, - .data = lq, + .data = { lq, }, }; if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 89b6696..69b7e6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -97,6 +97,13 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, + + [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, + + [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, + [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, }, + + [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, }; /* @@ -167,6 +174,31 @@ nla_put_failure: void iwl_testmode_init(struct iwl_priv *priv) { priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; + priv->testmode_trace.trace_enabled = false; +} + +static void iwl_trace_cleanup(struct iwl_priv *priv) +{ + struct device *dev = &priv->pci_dev->dev; + + if (priv->testmode_trace.trace_enabled) { + if (priv->testmode_trace.cpu_addr && + priv->testmode_trace.dma_addr) + dma_free_coherent(dev, + TRACE_TOTAL_SIZE, + priv->testmode_trace.cpu_addr, + priv->testmode_trace.dma_addr); + priv->testmode_trace.trace_enabled = false; + priv->testmode_trace.cpu_addr = NULL; + priv->testmode_trace.trace_addr = NULL; + priv->testmode_trace.dma_addr = 0; + } +} + + +void iwl_testmode_cleanup(struct iwl_priv *priv) +{ + iwl_trace_cleanup(priv); } /* @@ -198,10 +230,11 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) } cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); - cmd.data = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); - cmd.len = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); + cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," - " len %d\n", cmd.id, cmd.flags, cmd.len); + " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ return iwl_send_cmd(priv, &cmd); } @@ -388,6 +421,38 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) "Error starting the device: %d\n", status); break; + case IWL_TM_CMD_APP2DEV_GET_EEPROM: + if (priv->eeprom) { + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + priv->cfg->base_params->eeprom_size + 20); + if (!skb) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, + IWL_TM_CMD_DEV2APP_EEPROM_RSP); + NLA_PUT(skb, IWL_TM_ATTR_EEPROM, + priv->cfg->base_params->eeprom_size, + priv->eeprom); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", + status); + } else + return -EFAULT; + break; + + case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: + if (!tb[IWL_TM_ATTR_FIXRATE]) { + IWL_DEBUG_INFO(priv, + "Error finding fixrate setting\n"); + return -ENOMSG; + } + priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); + break; + default: IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); return -ENOSYS; @@ -399,6 +464,102 @@ nla_put_failure: return -EMSGSIZE; } + +/* + * This function handles the user application commands for uCode trace + * + * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the + * handlers respectively. + * + * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned + * value of the actual command execution is replied to the user application. + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct iwl_priv *priv = hw->priv; + struct sk_buff *skb; + int status = 0; + struct device *dev = &priv->pci_dev->dev; + + switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { + case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: + if (priv->testmode_trace.trace_enabled) + return -EBUSY; + + priv->testmode_trace.cpu_addr = + dma_alloc_coherent(dev, + TRACE_TOTAL_SIZE, + &priv->testmode_trace.dma_addr, + GFP_KERNEL); + if (!priv->testmode_trace.cpu_addr) + return -ENOMEM; + priv->testmode_trace.trace_enabled = true; + priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN( + priv->testmode_trace.cpu_addr, 0x100); + memset(priv->testmode_trace.trace_addr, 0x03B, + TRACE_BUFF_SIZE); + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + sizeof(priv->testmode_trace.dma_addr) + 20); + if (!skb) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + iwl_trace_cleanup(priv); + return -ENOMEM; + } + NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR, + sizeof(priv->testmode_trace.dma_addr), + (u64 *)&priv->testmode_trace.dma_addr); + status = cfg80211_testmode_reply(skb); + if (status < 0) { + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", + status); + } + break; + + case IWL_TM_CMD_APP2DEV_END_TRACE: + iwl_trace_cleanup(priv); + break; + + case IWL_TM_CMD_APP2DEV_READ_TRACE: + if (priv->testmode_trace.trace_enabled && + priv->testmode_trace.trace_addr) { + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, + 20 + TRACE_BUFF_SIZE); + if (skb == NULL) { + IWL_DEBUG_INFO(priv, + "Error allocating memory\n"); + return -ENOMEM; + } + NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA, + TRACE_BUFF_SIZE, + priv->testmode_trace.trace_addr); + status = cfg80211_testmode_reply(skb); + if (status < 0) { + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", status); + } + } else + return -EFAULT; + break; + + default: + IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n"); + return -ENOSYS; + } + return status; + +nla_put_failure: + kfree_skb(skb); + if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) == + IWL_TM_CMD_APP2DEV_BEGIN_TRACE) + iwl_trace_cleanup(priv); + return -EMSGSIZE; +} + /* The testmode gnl message handler that takes the gnl message from the * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then * invoke the corresponding handlers. @@ -455,9 +616,19 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: + case IWL_TM_CMD_APP2DEV_GET_EEPROM: + case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); result = iwl_testmode_driver(hw, tb); break; + + case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: + case IWL_TM_CMD_APP2DEV_END_TRACE: + case IWL_TM_CMD_APP2DEV_READ_TRACE: + IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n"); + result = iwl_testmode_trace(hw, tb); + break; + default: IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); result = -ENOSYS; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 31f8949..a88085e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -88,9 +88,15 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_LOAD_INIT_FW, IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB, IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW, + IWL_TM_CMD_APP2DEV_GET_EEPROM, + IWL_TM_CMD_APP2DEV_FIXRATE_REQ, /* if there is other new command for the driver layer operation, * append them here */ + /* commands fom user space for uCode trace operations */ + IWL_TM_CMD_APP2DEV_BEGIN_TRACE, + IWL_TM_CMD_APP2DEV_END_TRACE, + IWL_TM_CMD_APP2DEV_READ_TRACE, /* commands from kernel space to carry the synchronous response * to user application */ @@ -99,6 +105,11 @@ enum iwl_tm_cmd_t { /* commands from kernel space to multicast the spontaneous messages * to user application */ IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, + + /* commands from kernel space to carry the eeprom response + * to user application */ + IWL_TM_CMD_DEV2APP_EEPROM_RSP, + IWL_TM_CMD_MAX, }; @@ -144,8 +155,31 @@ enum iwl_tm_attr_t { * application */ IWL_TM_ATTR_UCODE_RX_PKT, + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM, + * The mandatory fields are: + * IWL_TM_ATTR_EEPROM for the data content responging to the user + * application */ + IWL_TM_ATTR_EEPROM, + + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE, + * The mandatory fields are: + * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address + */ + IWL_TM_ATTR_TRACE_ADDR, + IWL_TM_ATTR_TRACE_DATA, + + /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ, + * The mandatory fields are: + * IWL_TM_ATTR_FIXRATE for the fixed rate + */ + IWL_TM_ATTR_FIXRATE, + IWL_TM_ATTR_MAX, }; +/* uCode trace buffer */ +#define TRACE_BUFF_SIZE 0x20000 +#define TRACE_BUFF_PADD 0x2000 +#define TRACE_TOTAL_SIZE (TRACE_BUFF_SIZE + TRACE_BUFF_PADD) #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e69597e..686e176 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -32,6 +32,7 @@ #include <linux/slab.h> #include <net/mac80211.h> #include "iwl-eeprom.h" +#include "iwl-agn.h" #include "iwl-dev.h" #include "iwl-core.h" #include "iwl-sta.h" @@ -85,6 +86,158 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) txq->need_update = 0; } +static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + + dma_addr_t addr = get_unaligned_le32(&tb->lo); + if (sizeof(dma_addr_t) > sizeof(u32)) + addr |= + ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; + + return addr; +} + +static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + + return le16_to_cpu(tb->hi_n_len) >> 4; +} + +static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, + dma_addr_t addr, u16 len) +{ + struct iwl_tfd_tb *tb = &tfd->tbs[idx]; + u16 hi_n_len = len << 4; + + put_unaligned_le32(addr, &tb->lo); + if (sizeof(dma_addr_t) > sizeof(u32)) + hi_n_len |= ((addr >> 16) >> 16) & 0xF; + + tb->hi_n_len = cpu_to_le16(hi_n_len); + + tfd->num_tbs = idx + 1; +} + +static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) +{ + return tfd->num_tbs & 0x1f; +} + +static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, + struct iwl_tfd *tfd) +{ + struct pci_dev *dev = priv->pci_dev; + int i; + int num_tbs; + + /* Sanity check on number of chunks */ + num_tbs = iwl_tfd_get_num_tbs(tfd); + + if (num_tbs >= IWL_NUM_OF_TBS) { + IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); + /* @todo issue fatal error, it is quite serious situation */ + return; + } + + /* Unmap tx_cmd */ + if (num_tbs) + pci_unmap_single(dev, + dma_unmap_addr(meta, mapping), + dma_unmap_len(meta, len), + PCI_DMA_BIDIRECTIONAL); + + /* Unmap chunks, if any. */ + for (i = 1; i < num_tbs; i++) + pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), + iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); +} + +/** + * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] + * @priv - driver private data + * @txq - tx queue + * + * Does NOT advance any TFD circular buffer read/write indexes + * Does NOT free the TFD itself (which is within circular buffer) + */ +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) +{ + struct iwl_tfd *tfd_tmp = txq->tfds; + int index = txq->q.read_ptr; + + iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index]); + + /* free SKB */ + if (txq->txb) { + struct sk_buff *skb; + + skb = txq->txb[txq->q.read_ptr].skb; + + /* can be called from irqs-disabled context */ + if (skb) { + dev_kfree_skb_any(skb); + txq->txb[txq->q.read_ptr].skb = NULL; + } + } +} + +int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, + u8 reset) +{ + struct iwl_queue *q; + struct iwl_tfd *tfd, *tfd_tmp; + u32 num_tbs; + + q = &txq->q; + tfd_tmp = txq->tfds; + tfd = &tfd_tmp[q->write_ptr]; + + if (reset) + memset(tfd, 0, sizeof(*tfd)); + + num_tbs = iwl_tfd_get_num_tbs(tfd); + + /* Each TFD can point to a maximum 20 Tx buffers */ + if (num_tbs >= IWL_NUM_OF_TBS) { + IWL_ERR(priv, "Error can not send more than %d chunks\n", + IWL_NUM_OF_TBS); + return -EINVAL; + } + + if (WARN_ON(addr & ~DMA_BIT_MASK(36))) + return -EINVAL; + + if (unlikely(addr & ~IWL_TX_DMA_MASK)) + IWL_ERR(priv, "Unaligned address = %llx\n", + (unsigned long long)addr); + + iwl_tfd_set_tb(tfd, num_tbs, addr, len); + + return 0; +} + +/* + * Tell nic where to find circular buffer of Tx Frame Descriptors for + * given Tx queue, and enable the DMA channel used for that queue. + * + * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA + * channels supported in hardware. + */ +static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) +{ + int txq_id = txq->q.id; + + /* Circular buffer (TFD queue in DRAM) physical base address */ + iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), + txq->q.dma_addr >> 8); + + return 0; +} + /** * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's */ @@ -97,7 +250,7 @@ void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) return; while (q->write_ptr != q->read_ptr) { - priv->cfg->ops->lib->txq_free_tfd(priv, txq); + iwlagn_txq_free_tfd(priv, txq); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } } @@ -154,7 +307,7 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) return; while (q->read_ptr != q->write_ptr) { - i = get_cmd_index(q, q->read_ptr, 0); + i = get_cmd_index(q, q->read_ptr); if (txq->meta[i].flags & CMD_MAPPED) { pci_unmap_single(priv->pci_dev, @@ -166,15 +319,6 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } - - i = q->n_window; - if (txq->meta[i].flags & CMD_MAPPED) { - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(&txq->meta[i], mapping), - dma_unmap_len(&txq->meta[i], len), - PCI_DMA_BIDIRECTIONAL); - txq->meta[i].flags = 0; - } } /** @@ -194,7 +338,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) iwl_cmd_queue_unmap(priv); /* De-alloc array of command/tx buffers */ - for (i = 0; i <= TFD_CMD_SLOTS; i++) + for (i = 0; i < TFD_CMD_SLOTS; i++) kfree(txq->cmd[i]); /* De-alloc circular buffer of TFDs */ @@ -334,33 +478,17 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, { int i, len; int ret; - int actual_slots = slots_num; - - /* - * Alloc buffer array for commands (Tx or other types of commands). - * For the command queue (#4/#9), allocate command space + one big - * command for scan, since scan command is very huge; the system will - * not have two scans at the same time, so only one is needed. - * For normal Tx queues (all other queues), no super-size command - * space is needed. - */ - if (txq_id == priv->cmd_queue) - actual_slots++; - txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots, + txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num, GFP_KERNEL); - txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots, + txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num, GFP_KERNEL); if (!txq->meta || !txq->cmd) goto out_free_arrays; len = sizeof(struct iwl_device_cmd); - for (i = 0; i < actual_slots; i++) { - /* only happens for cmd queue */ - if (i == slots_num) - len = IWL_MAX_CMD_SIZE; - + for (i = 0; i < slots_num; i++) { txq->cmd[i] = kmalloc(len, GFP_KERNEL); if (!txq->cmd[i]) goto err; @@ -391,11 +519,11 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, return ret; /* Tell device where to find queue */ - priv->cfg->ops->lib->txq_init(priv, txq); + iwlagn_tx_queue_init(priv, txq); return 0; err: - for (i = 0; i < actual_slots; i++) + for (i = 0; i < slots_num; i++) kfree(txq->cmd[i]); out_free_arrays: kfree(txq->meta); @@ -420,7 +548,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); /* Tell device where to find queue */ - priv->cfg->ops->lib->txq_init(priv, txq); + iwlagn_tx_queue_init(priv, txq); } /*************** HOST COMMAND QUEUE FUNCTIONS *****/ @@ -443,23 +571,49 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) dma_addr_t phys_addr; unsigned long flags; u32 idx; - u16 fix_size; + u16 copy_size, cmd_size; bool is_ct_kill = false; + bool had_nocopy = false; + int i; + u8 *cmd_dest; +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {}; + int trace_lens[IWL_MAX_CMD_TFDS + 1] = {}; + int trace_idx; +#endif + + if (test_bit(STATUS_FW_ERROR, &priv->status)) { + IWL_WARN(priv, "fw recovery, no hcmd send\n"); + return -EIO; + } - fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); + copy_size = sizeof(out_cmd->hdr); + cmd_size = sizeof(out_cmd->hdr); + + /* need one for the header if the first is NOCOPY */ + BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); + + for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { + if (!cmd->len[i]) + continue; + if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { + had_nocopy = true; + } else { + /* NOCOPY must not be followed by normal! */ + if (WARN_ON(had_nocopy)) + return -EINVAL; + copy_size += cmd->len[i]; + } + cmd_size += cmd->len[i]; + } /* * If any of the command structures end up being larger than - * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then - * we will need to increase the size of the TFD entries - * Also, check to see if command buffer should not exceed the size - * of device_cmd and max_cmd_size. + * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically + * allocated into separate TFDs, then we will need to + * increase the size of the buffers. */ - if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && - !(cmd->flags & CMD_SIZE_HUGE))) - return -EINVAL; - - if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE)) + if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) return -EINVAL; if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { @@ -468,14 +622,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -EIO; } - /* - * As we only have a single huge buffer, check that the command - * is synchronous (otherwise buffers could end up being reused). - */ - - if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE))) - return -EINVAL; - spin_lock_irqsave(&priv->hcmd_lock, flags); if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { @@ -490,7 +636,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) return -ENOSPC; } - idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); + idx = get_cmd_index(q, q->write_ptr); out_cmd = txq->cmd[idx]; out_meta = &txq->meta[idx]; @@ -505,57 +651,84 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (cmd->flags & CMD_ASYNC) out_meta->callback = cmd->callback; - out_cmd->hdr.cmd = cmd->id; - memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len); - - /* At this point, the out_cmd now has all of the incoming cmd - * information */ + /* set up the header */ + out_cmd->hdr.cmd = cmd->id; out_cmd->hdr.flags = 0; out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) | - INDEX_TO_SEQ(q->write_ptr)); - if (cmd->flags & CMD_SIZE_HUGE) - out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; - -#ifdef CONFIG_IWLWIFI_DEBUG - switch (out_cmd->hdr.cmd) { - case REPLY_TX_LINK_QUALITY_CMD: - case SENSITIVITY_CMD: - IWL_DEBUG_HC_DUMP(priv, "Sending command %s (#%x), seq: 0x%04X, " - "%d bytes at %d[%d]:%d\n", - get_cmd_string(out_cmd->hdr.cmd), - out_cmd->hdr.cmd, - le16_to_cpu(out_cmd->hdr.sequence), fix_size, - q->write_ptr, idx, priv->cmd_queue); - break; - default: - IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " - "%d bytes at %d[%d]:%d\n", - get_cmd_string(out_cmd->hdr.cmd), - out_cmd->hdr.cmd, - le16_to_cpu(out_cmd->hdr.sequence), fix_size, - q->write_ptr, idx, priv->cmd_queue); + INDEX_TO_SEQ(q->write_ptr)); + + /* and copy the data that needs to be copied */ + + cmd_dest = &out_cmd->cmd.payload[0]; + for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { + if (!cmd->len[i]) + continue; + if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) + break; + memcpy(cmd_dest, cmd->data[i], cmd->len[i]); + cmd_dest += cmd->len[i]; } -#endif + + IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " + "%d bytes at %d[%d]:%d\n", + get_cmd_string(out_cmd->hdr.cmd), + out_cmd->hdr.cmd, + le16_to_cpu(out_cmd->hdr.sequence), cmd_size, + q->write_ptr, idx, priv->cmd_queue); + phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, - fix_size, PCI_DMA_BIDIRECTIONAL); + copy_size, PCI_DMA_BIDIRECTIONAL); if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { idx = -ENOMEM; goto out; } dma_unmap_addr_set(out_meta, mapping, phys_addr); - dma_unmap_len_set(out_meta, len, fix_size); + dma_unmap_len_set(out_meta, len, copy_size); + + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1); +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + trace_bufs[0] = &out_cmd->hdr; + trace_lens[0] = copy_size; + trace_idx = 1; +#endif + + for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { + if (!cmd->len[i]) + continue; + if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) + continue; + phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i], + cmd->len[i], PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) { + iwlagn_unmap_tfd(priv, out_meta, + &txq->tfds[q->write_ptr]); + idx = -ENOMEM; + goto out; + } + + iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, + cmd->len[i], 0); +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + trace_bufs[trace_idx] = cmd->data[i]; + trace_lens[trace_idx] = cmd->len[i]; + trace_idx++; +#endif + } out_meta->flags = cmd->flags | CMD_MAPPED; txq->need_update = 1; - trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); - - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, fix_size, 1, - U32_PAD(cmd->len)); + /* check that tracing gets all possible blocks */ + BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3); +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + trace_iwlwifi_dev_hcmd(priv, cmd->flags, + trace_bufs[0], trace_lens[0], + trace_bufs[1], trace_lens[1], + trace_bufs[2], trace_lens[2]); +#endif /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); @@ -573,8 +746,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) * need to be reclaimed. As result, some free space forms. If there is * enough free space (> low mark), wake the stack that feeds us. */ -static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, - int idx, int cmd_idx) +static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; @@ -614,7 +786,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); int cmd_index; - bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; @@ -632,14 +803,11 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) return; } - cmd_index = get_cmd_index(&txq->q, index, huge); + cmd_index = get_cmd_index(&txq->q, index); cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; - pci_unmap_single(priv->pci_dev, - dma_unmap_addr(meta, mapping), - dma_unmap_len(meta, len), - PCI_DMA_BIDIRECTIONAL); + iwlagn_unmap_tfd(priv, meta, &txq->tfds[index]); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { @@ -650,7 +818,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) spin_lock_irqsave(&priv->hcmd_lock, flags); - iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); + iwl_hcmd_queue_reclaim(priv, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { clear_bit(STATUS_HCMD_ACTIVE, &priv->status); diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 5665a1a..a414768 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -565,7 +565,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) && iwm->conf.mode == UMAC_MODE_BSS) { cancel_delayed_work(&iwm->disconnect); - cfg80211_roamed(iwm_to_ndev(iwm), + cfg80211_roamed(iwm_to_ndev(iwm), NULL, complete->bssid, iwm->req_ie, iwm->req_ie_len, iwm->resp_ie, iwm->resp_ie_len, @@ -586,7 +586,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, WLAN_STATUS_SUCCESS, GFP_KERNEL); else - cfg80211_roamed(iwm_to_ndev(iwm), + cfg80211_roamed(iwm_to_ndev(iwm), NULL, complete->bssid, iwm->req_ie, iwm->req_ie_len, iwm->resp_ie, iwm->resp_ie_len, diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 63ed579..e269351 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -983,7 +983,7 @@ static void if_cs_detach(struct pcmcia_device *p_dev) /* Module initialization */ /********************************************************************/ -static struct pcmcia_device_id if_cs_ids[] = { +static const struct pcmcia_device_id if_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index d3d5e08..f807447 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -196,6 +196,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, if (skb_src) pra_list->total_pkts_size -= skb_src->len; + atomic_dec(&priv->wmm.tx_pkts_queued); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); @@ -257,6 +259,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, pra_list->total_pkts_size += skb_aggr->len; + atomic_inc(&priv->wmm.tx_pkts_queued); + tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 672701d..8316b3c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -69,7 +69,8 @@ struct mwifiex_drv_mode { #define MWIFIEX_TIMER_10S 10000 #define MWIFIEX_TIMER_1S 1000 -#define MAX_TX_PENDING 60 +#define MAX_TX_PENDING 100 +#define LOW_TX_PENDING 80 #define MWIFIEX_UPLD_SIZE (2312) @@ -202,6 +203,7 @@ struct mwifiex_tid_tbl { #define WMM_HIGHEST_PRIORITY 7 #define HIGH_PRIO_TID 7 #define LOW_PRIO_TID 0 +#define NO_PKT_PRIO_TID (-1) struct mwifiex_wmm_desc { struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; @@ -213,7 +215,10 @@ struct mwifiex_wmm_desc { u32 drv_pkt_delay_max; u8 queue_priority[IEEE80211_MAX_QUEUES]; u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ - + /* Number of transmit packets queued */ + atomic_t tx_pkts_queued; + /* Tracks highest priority with a packet queued */ + atomic_t highest_queued_prio; }; struct mwifiex_802_11_security { diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 2101208..aaa50c0 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -140,7 +140,9 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, } else { priv->stats.tx_errors++; } - atomic_dec(&adapter->tx_pending); + + if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING) + goto done; for (i = 0; i < adapter->priv_num; i++) { diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index faa09e3..91634da 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -177,14 +177,20 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) * This function map ACs to TIDs. */ static void -mwifiex_wmm_queue_priorities_tid(u8 queue_priority[]) +mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm) { + u8 *queue_priority = wmm->queue_priority; int i; for (i = 0; i < 4; ++i) { tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; } + + for (i = 0; i < MAX_NUM_TID; ++i) + tos_to_tid_inv[tos_to_tid[i]] = (u8)i; + + atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); } /* @@ -246,7 +252,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, } } - mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority); + mwifiex_wmm_queue_priorities_tid(&priv->wmm); } /* @@ -399,6 +405,9 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; + + atomic_set(&priv->wmm.tx_pkts_queued, 0); + atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } } @@ -408,17 +417,13 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) { - int i, j; + int i; struct mwifiex_private *priv; - for (j = 0; j < adapter->priv_num; ++j) { - priv = adapter->priv[j]; - if (priv) { - for (i = 0; i < MAX_NUM_TID; i++) - if (!mwifiex_wmm_is_ra_list_empty( - &priv->wmm.tid_tbl_ptr[i].ra_list)) - return false; - } + for (i = 0; i < adapter->priv_num; ++i) { + priv = adapter->priv[i]; + if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) + return false; } return true; @@ -468,6 +473,9 @@ static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) for (i = 0; i < MAX_NUM_TID; i++) mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. ra_list); + + atomic_set(&priv->wmm.tx_pkts_queued, 0); + atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } /* @@ -638,6 +646,13 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter, ra_list->total_pkts_size += skb->len; + atomic_inc(&priv->wmm.tx_pkts_queued); + + if (atomic_read(&priv->wmm.highest_queued_prio) < + tos_to_tid_inv[tid_down]) + atomic_set(&priv->wmm.highest_queued_prio, + tos_to_tid_inv[tid_down]); + spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); } @@ -863,9 +878,14 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, } do { + atomic_t *hqp; + spinlock_t *lock; + priv_tmp = bssprio_node->priv; + hqp = &priv_tmp->wmm.highest_queued_prio; + lock = &priv_tmp->wmm.ra_list_spinlock; - for (i = HIGH_PRIO_TID; i >= LOW_PRIO_TID; --i) { + for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { tid_ptr = &(priv_tmp)->wmm. tid_tbl_ptr[tos_to_tid[i]]; @@ -903,6 +923,11 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, is_list_empty = skb_queue_empty(&ptr->skb_head); if (!is_list_empty) { + spin_lock_irqsave(lock, flags); + if (atomic_read(hqp) > i) + atomic_set(hqp, i); + spin_unlock_irqrestore(lock, + flags); *priv = priv_tmp; *tid = tos_to_tid[i]; return ptr; @@ -921,6 +946,12 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, } while (ptr != head); } + /* No packet at any TID for this priv. Mark as such + * to skip checking TIDs for this priv (until pkt is + * added). + */ + atomic_set(hqp, NO_PKT_PRIO_TID); + /* Get next bss priority node */ bssprio_node = list_first_entry(&bssprio_node->list, struct mwifiex_bss_prio_node, @@ -1028,6 +1059,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv, .bss_prio_cur->list, struct mwifiex_bss_prio_node, list); + atomic_dec(&priv->wmm.tx_pkts_queued); spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); } @@ -1134,6 +1166,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, .bss_prio_cur->list, struct mwifiex_bss_prio_node, list); + atomic_dec(&priv->wmm.tx_pkts_queued); spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); } @@ -1227,5 +1260,5 @@ mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) if (mwifiex_dequeue_tx_packet(adapter)) break; - } while (true); + } while (!mwifiex_wmm_lists_empty(adapter)); } diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 32954c4..88e3c0e 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -237,7 +237,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link) /* Module initialization */ /********************************************************************/ -static struct pcmcia_device_id orinoco_cs_ids[] = { +static const struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */ PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */ PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */ diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index db34c28..81f3673 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -301,7 +301,7 @@ spectrum_cs_resume(struct pcmcia_device *link) /* Module initialization */ /********************************************************************/ -static struct pcmcia_device_id spectrum_cs_ids[] = { +static const struct pcmcia_device_id spectrum_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */ PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */ diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index e183587..a8f3bc7 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -82,6 +82,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {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 */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 0764d1a..2a06ebc 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -2781,7 +2781,7 @@ static const struct file_operations int_proc_fops = { }; #endif -static struct pcmcia_device_id ray_ids[] = { +static const struct pcmcia_device_id ray_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000), PCMCIA_DEVICE_NULL, }; diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 518542b..29f9389 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2830,7 +2830,8 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) req_ie_len, resp_ie, resp_ie_len, 0, GFP_KERNEL); else - cfg80211_roamed(usbdev->net, bssid, req_ie, req_ie_len, + cfg80211_roamed(usbdev->net, NULL, bssid, + req_ie, req_ie_len, resp_ie, resp_ie_len, GFP_KERNEL); } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 2bb7119..39b0297 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -190,7 +190,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) ppsc->swrf_processing = true; - if (ppsc->inactive_pwrstate == ERFOFF && + if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) { if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index c5424ca..d2cc815 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -728,7 +728,7 @@ void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, return; rtlphy->set_bwmode_inprogress = true; if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtlphy->set_bwmode_inprogress = false; + rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw); } else { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("FALSE driver sleep or unload\n")); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index 73ae8a4..abe0fcc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -366,6 +366,75 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, return true; } +void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + ("Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz")) + + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; + return; + } + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + reg_prsr_rsc = + (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); + + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); + break; + } + rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); +} + void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) { u8 tmpreg; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h index ad58085..be2c92a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h @@ -257,5 +257,6 @@ bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, u8 configtype); bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, u8 configtype); +void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw); #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 390bbb5..373dc78 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -232,6 +232,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile, .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, + .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, }; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index fc08f36..6bc7c92 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -2000,7 +2000,7 @@ static int wl3501_resume(struct pcmcia_device *link) } -static struct pcmcia_device_id wl3501_ids[] = { +static const struct pcmcia_device_id wl3501_ids[] = { PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001), PCMCIA_DEVICE_NULL }; diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index db9a763..d29365a 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1581,7 +1581,9 @@ static int xennet_connect(struct net_device *dev) if (err) return err; + rtnl_lock(); netdev_update_features(dev); + rtnl_unlock(); spin_lock_bh(&np->rx_lock); spin_lock_irq(&np->tx_lock); |