Commit d2c2ad54 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull networking fixes from David Miller:

 1) Fix memory leaks and other issues in mwifiex driver, from Amitkumar
    Karwar.

 2) skb_segment() can choke on packets using frag lists, fix from
    Herbert Xu with help from Eric Dumazet and others.

 3) IPv4 output cached route instantiation properly handles races
    involving two threads trying to install the same route, but we
    forgot to propagate this logic to input routes as well.  Fix from
    Alexei Starovoitov.

 4) Put protections in place to make sure that recvmsg() paths never
    accidently copy uninitialized memory back into userspace and also
    make sure that we never try to use more that sockaddr_storage for
    building the on-kernel-stack copy of a sockaddr.  Fixes from Hannes
    Frederic Sowa.

 5) R8152 driver transmit flow bug fixes from Hayes Wang.

 6) Fix some minor fallouts from genetlink changes, from Johannes Berg
    and Michael Opdenacker.

 7) AF_PACKET sendmsg path can race with netdevice unregister notifier,
    fix by using RCU to make sure the network device doesn't go away
    from under us.  Fix from Daniel Borkmann.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (43 commits)
  gso: handle new frag_list of frags GRO packets
  genetlink: fix genl_set_err() group ID
  genetlink: fix genlmsg_multicast() bug
  packet: fix use after free race in send path when dev is released
  xen-netback: stop the VIF thread before unbinding IRQs
  wimax: remove dead code
  net/phy: Add the autocross feature for forced links on VSC82x4
  net/phy: Add VSC8662 support
  net/phy: Add VSC8574 support
  net/phy: Add VSC8234 support
  net: add BUG_ON if kernel advertises msg_namelen > sizeof(struct sockaddr_storage)
  net: rework recvmsg handler msg_name and msg_namelen logic
  bridge: flush br's address entry in fdb when remove the
  net: core: Always propagate flag changes to interfaces
  ipv4: fix race in concurrent ip_route_input_slow()
  r8152: fix incorrect type in assignment
  r8152: support stopping/waking tx queue
  r8152: modify the tx flow
  r8152: fix tx/rx memory overflow
  netfilter: ebt_ip6: fix source and destination matching
  ...
parents 7fa850ab 9d8506cc
......@@ -161,8 +161,6 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
else if (len < ds)
msg->msg_flags |= MSG_TRUNC;
msg->msg_namelen = 0;
lock_sock(sk);
if (ctx->more) {
ctx->more = 0;
......
......@@ -432,7 +432,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
long copied = 0;
lock_sock(sk);
msg->msg_namelen = 0;
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
iovlen--, iov++) {
unsigned long seglen = iov->iov_len;
......
......@@ -117,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
{
struct sk_buff *skb;
struct sock *sk = sock->sk;
struct sockaddr_mISDN *maddr;
int copied, err;
......@@ -135,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if (!skb)
return err;
if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
msg->msg_namelen = sizeof(struct sockaddr_mISDN);
maddr = (struct sockaddr_mISDN *)msg->msg_name;
if (msg->msg_name) {
struct sockaddr_mISDN *maddr = msg->msg_name;
maddr->family = AF_ISDN;
maddr->dev = _pms(sk)->dev->id;
if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
......@@ -150,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
maddr->sapi = _pms(sk)->ch.addr & 0xFF;
maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF;
}
} else {
if (msg->msg_namelen)
printk(KERN_WARNING "%s: too small namelen %d\n",
__func__, msg->msg_namelen);
msg->msg_namelen = 0;
msg->msg_namelen = sizeof(*maddr);
}
copied = skb->len + MISDN_HEADER_LEN;
......
......@@ -697,7 +697,7 @@ static int genphy_config_advert(struct phy_device *phydev)
* to the values in phydev. Assumes that the values are valid.
* Please see phy_sanitize_settings().
*/
static int genphy_setup_forced(struct phy_device *phydev)
int genphy_setup_forced(struct phy_device *phydev)
{
int err;
int ctl = 0;
......@@ -716,7 +716,7 @@ static int genphy_setup_forced(struct phy_device *phydev)
return err;
}
EXPORT_SYMBOL(genphy_setup_forced);
/**
* genphy_restart_aneg - Enable and Restart Autonegotiation
......
......@@ -3,7 +3,7 @@
*
* Author: Kriston Carson
*
* Copyright (c) 2005, 2009 Freescale Semiconductor, Inc.
* Copyright (c) 2005, 2009, 2011 Freescale Semiconductor, Inc.
*
* 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
......@@ -18,6 +18,11 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
/* Vitesse Extended Page Magic Register(s) */
#define MII_VSC82X4_EXT_PAGE_16E 0x10
#define MII_VSC82X4_EXT_PAGE_17E 0x11
#define MII_VSC82X4_EXT_PAGE_18E 0x12
/* Vitesse Extended Control Register 1 */
#define MII_VSC8244_EXT_CON1 0x17
#define MII_VSC8244_EXTCON1_INIT 0x0000
......@@ -54,7 +59,13 @@
#define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */
#define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004
/* Vitesse Extended Page Access Register */
#define MII_VSC82X4_EXT_PAGE_ACCESS 0x1f
#define PHY_ID_VSC8234 0x000fc620
#define PHY_ID_VSC8244 0x000fc6c0
#define PHY_ID_VSC8574 0x000704a0
#define PHY_ID_VSC8662 0x00070660
#define PHY_ID_VSC8221 0x000fc550
#define PHY_ID_VSC8211 0x000fc4b0
......@@ -118,7 +129,9 @@ static int vsc82xx_config_intr(struct phy_device *phydev)
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
err = phy_write(phydev, MII_VSC8244_IMASK,
phydev->drv->phy_id == PHY_ID_VSC8244 ?
(phydev->drv->phy_id == PHY_ID_VSC8234 ||
phydev->drv->phy_id == PHY_ID_VSC8244 ||
phydev->drv->phy_id == PHY_ID_VSC8574) ?
MII_VSC8244_IMASK_MASK :
MII_VSC8221_IMASK_MASK);
else {
......@@ -149,20 +162,113 @@ static int vsc8221_config_init(struct phy_device *phydev)
*/
}
/* Vitesse 824x */
/* vsc82x4_config_autocross_enable - Enable auto MDI/MDI-X for forced links
* @phydev: target phy_device struct
*
* Enable auto MDI/MDI-X when in 10/100 forced link speeds by writing
* special values in the VSC8234/VSC8244 extended reserved registers
*/
static int vsc82x4_config_autocross_enable(struct phy_device *phydev)
{
int ret;
if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed > SPEED_100)
return 0;
/* map extended registers set 0x10 - 0x1e */
ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x52b5);
if (ret >= 0)
ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_18E, 0x0012);
if (ret >= 0)
ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_17E, 0x2803);
if (ret >= 0)
ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_16E, 0x87fa);
/* map standard registers set 0x10 - 0x1e */
if (ret >= 0)
ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000);
else
phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000);
return ret;
}
/* vsc82x4_config_aneg - restart auto-negotiation or write BMCR
* @phydev: target phy_device struct
*
* Description: If auto-negotiation is enabled, we configure the
* advertising, and then restart auto-negotiation. If it is not
* enabled, then we write the BMCR and also start the auto
* MDI/MDI-X feature
*/
static int vsc82x4_config_aneg(struct phy_device *phydev)
{
int ret;
/* Enable auto MDI/MDI-X when in 10/100 forced link speeds by
* writing special values in the VSC8234 extended reserved registers
*/
if (phydev->autoneg != AUTONEG_ENABLE && phydev->speed <= SPEED_100) {
ret = genphy_setup_forced(phydev);
if (ret < 0) /* error */
return ret;
return vsc82x4_config_autocross_enable(phydev);
}
return genphy_config_aneg(phydev);
}
/* Vitesse 82xx */
static struct phy_driver vsc82xx_driver[] = {
{
.phy_id = PHY_ID_VSC8234,
.name = "Vitesse VSC8234",
.phy_id_mask = 0x000ffff0,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = &vsc824x_config_init,
.config_aneg = &vsc82x4_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &vsc824x_ack_interrupt,
.config_intr = &vsc82xx_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_VSC8244,
.name = "Vitesse VSC8244",
.phy_id_mask = 0x000fffc0,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = &vsc824x_config_init,
.config_aneg = &genphy_config_aneg,
.config_aneg = &vsc82x4_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &vsc824x_ack_interrupt,
.config_intr = &vsc82xx_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_VSC8574,
.name = "Vitesse VSC8574",
.phy_id_mask = 0x000ffff0,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = &vsc824x_config_init,
.config_aneg = &vsc82x4_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &vsc824x_ack_interrupt,
.config_intr = &vsc82xx_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_VSC8662,
.name = "Vitesse VSC8662",
.phy_id_mask = 0x000ffff0,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = &vsc824x_config_init,
.config_aneg = &vsc82x4_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &vsc824x_ack_interrupt,
.config_intr = &vsc82xx_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
/* Vitesse 8221 */
.phy_id = PHY_ID_VSC8221,
......@@ -207,7 +313,10 @@ module_init(vsc82xx_init);
module_exit(vsc82xx_exit);
static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
{ PHY_ID_VSC8234, 0x000ffff0 },
{ PHY_ID_VSC8244, 0x000fffc0 },
{ PHY_ID_VSC8574, 0x000ffff0 },
{ PHY_ID_VSC8662, 0x000ffff0 },
{ PHY_ID_VSC8221, 0x000ffff0 },
{ PHY_ID_VSC8211, 0x000ffff0 },
{ }
......
......@@ -979,8 +979,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
if (error < 0)
goto end;
m->msg_namelen = 0;
if (skb) {
total_len = min_t(size_t, total_len, skb->len);
error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
......
......@@ -24,7 +24,7 @@
#include <linux/ipv6.h>
/* Version Information */
#define DRIVER_VERSION "v1.01.0 (2013/08/12)"
#define DRIVER_VERSION "v1.02.0 (2013/10/28)"
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
#define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters"
#define MODULENAME "r8152"
......@@ -307,22 +307,22 @@ enum rtl8152_flags {
#define MCU_TYPE_USB 0x0000
struct rx_desc {
u32 opts1;
__le32 opts1;
#define RX_LEN_MASK 0x7fff
u32 opts2;
u32 opts3;
u32 opts4;
u32 opts5;
u32 opts6;
__le32 opts2;
__le32 opts3;
__le32 opts4;
__le32 opts5;
__le32 opts6;
};
struct tx_desc {
u32 opts1;
__le32 opts1;
#define TX_FS (1 << 31) /* First segment of a packet */
#define TX_LS (1 << 30) /* Final segment of a packet */
#define TX_LEN_MASK 0x3ffff
u32 opts2;
__le32 opts2;
#define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */
#define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */
#define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */
......@@ -365,6 +365,7 @@ struct r8152 {
struct mii_if_info mii;
int intr_interval;
u32 msg_enable;
u32 tx_qlen;
u16 ocp_base;
u8 *intr_buff;
u8 version;
......@@ -876,7 +877,7 @@ static void write_bulk_callback(struct urb *urb)
static void intr_callback(struct urb *urb)
{
struct r8152 *tp;
__u16 *d;
__le16 *d;
int status = urb->status;
int res;
......@@ -1136,14 +1137,14 @@ r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb)
static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
{
u32 remain;
int remain;
u8 *tx_data;
tx_data = agg->head;
agg->skb_num = agg->skb_len = 0;
remain = rx_buf_sz - sizeof(struct tx_desc);
remain = rx_buf_sz;
while (remain >= ETH_ZLEN) {
while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) {
struct tx_desc *tx_desc;
struct sk_buff *skb;
unsigned int len;
......@@ -1152,12 +1153,14 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
if (!skb)
break;
remain -= sizeof(*tx_desc);
len = skb->len;
if (remain < len) {
skb_queue_head(&tp->tx_queue, skb);
break;
}
tx_data = tx_agg_align(tx_data);
tx_desc = (struct tx_desc *)tx_data;
tx_data += sizeof(*tx_desc);
......@@ -1167,11 +1170,18 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
agg->skb_len += len;
dev_kfree_skb_any(skb);
tx_data = tx_agg_align(tx_data + len);
remain = rx_buf_sz - sizeof(*tx_desc) -
(u32)((void *)tx_data - agg->head);
tx_data += len;
remain = rx_buf_sz - (int)(tx_agg_align(tx_data) - agg->head);
}
netif_tx_lock(tp->netdev);
if (netif_queue_stopped(tp->netdev) &&
skb_queue_len(&tp->tx_queue) < tp->tx_qlen)
netif_wake_queue(tp->netdev);
netif_tx_unlock(tp->netdev);
usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
agg->head, (int)(tx_data - (u8 *)agg->head),
(usb_complete_t)write_bulk_callback, agg);
......@@ -1188,7 +1198,6 @@ static void rx_bottom(struct r8152 *tp)
list_for_each_safe(cursor, next, &tp->rx_done) {
struct rx_desc *rx_desc;
struct rx_agg *agg;
unsigned pkt_len;
int len_used = 0;
struct urb *urb;
u8 *rx_data;
......@@ -1204,17 +1213,22 @@ static void rx_bottom(struct r8152 *tp)
rx_desc = agg->head;
rx_data = agg->head;
pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
len_used += sizeof(struct rx_desc) + pkt_len;
len_used += sizeof(struct rx_desc);
while (urb->actual_length >= len_used) {
while (urb->actual_length > len_used) {
struct net_device *netdev = tp->netdev;
struct net_device_stats *stats;
unsigned int pkt_len;
struct sk_buff *skb;
pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
if (pkt_len < ETH_ZLEN)
break;
len_used += pkt_len;
if (urb->actual_length < len_used)
break;
stats = rtl8152_get_stats(netdev);
pkt_len -= 4; /* CRC */
......@@ -1234,9 +1248,8 @@ static void rx_bottom(struct r8152 *tp)
rx_data = rx_agg_align(rx_data + pkt_len + 4);
rx_desc = (struct rx_desc *)rx_data;
pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
len_used = (int)(rx_data - (u8 *)agg->head);
len_used += sizeof(struct rx_desc) + pkt_len;
len_used += sizeof(struct rx_desc);
}
submit:
......@@ -1384,53 +1397,17 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
struct r8152 *tp = netdev_priv(netdev);
struct net_device_stats *stats = rtl8152_get_stats(netdev);
unsigned long flags;
struct tx_agg *agg = NULL;
struct tx_desc *tx_desc;
unsigned int len;
u8 *tx_data;
int res;
skb_tx_timestamp(skb);
/* If tx_queue is not empty, it means at least one previous packt */
/* is waiting for sending. Don't send current one before it. */
if (skb_queue_empty(&tp->tx_queue))
agg = r8152_get_tx_agg(tp);
if (!agg) {
skb_queue_tail(&tp->tx_queue, skb);
return NETDEV_TX_OK;
}
skb_queue_tail(&tp->tx_queue, skb);
tx_desc = (struct tx_desc *)agg->head;
tx_data = agg->head + sizeof(*tx_desc);
agg->skb_num = agg->skb_len = 0;
if (list_empty(&tp->tx_free) &&
skb_queue_len(&tp->tx_queue) > tp->tx_qlen)
netif_stop_queue(netdev);
len = skb->len;
r8152_tx_csum(tp, tx_desc, skb);
memcpy(tx_data, skb->data, len);
dev_kfree_skb_any(skb);
agg->skb_num++;
agg->skb_len += len;
usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
agg->head, len + sizeof(*tx_desc),
(usb_complete_t)write_bulk_callback, agg);
res = usb_submit_urb(agg->urb, GFP_ATOMIC);
if (res) {
/* Can we get/handle EPIPE here? */
if (res == -ENODEV) {
netif_device_detach(tp->netdev);
} else {
netif_warn(tp, tx_err, netdev,
"failed tx_urb %d\n", res);
stats->tx_dropped++;
spin_lock_irqsave(&tp->tx_lock, flags);
list_add_tail(&agg->list, &tp->tx_free);
spin_unlock_irqrestore(&tp->tx_lock, flags);
}
}
if (!list_empty(&tp->tx_free))
tasklet_schedule(&tp->tl);
return NETDEV_TX_OK;
}
......@@ -1459,6 +1436,14 @@ static void rtl8152_nic_reset(struct r8152 *tp)
}
}
static void set_tx_qlen(struct r8152 *tp)
{
struct net_device *netdev = tp->netdev;
tp->tx_qlen = rx_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + VLAN_HLEN +
sizeof(struct tx_desc));
}
static inline u8 rtl8152_get_speed(struct r8152 *tp)
{
return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS);
......@@ -1470,6 +1455,7 @@ static int rtl8152_enable(struct r8152 *tp)
int i, ret;
u8 speed;
set_tx_qlen(tp);
speed = rtl8152_get_speed(tp);
if (speed & _10bps) {
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
......
......@@ -701,6 +701,54 @@ static int ar9550_hw_get_modes_txgain_index(struct ath_hw *ah,
return ret;
}
static void ar9003_doubler_fix(struct ath_hw *ah)
{
if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
REG_RMW(ah, AR_PHY_65NM_CH0_RXTX2,
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0);
REG_RMW(ah, AR_PHY_65NM_CH1_RXTX2,
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0);
REG_RMW(ah, AR_PHY_65NM_CH2_RXTX2,
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0);
udelay(200);
REG_CLR_BIT(ah, AR_PHY_65NM_CH0_RXTX2,
AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK);
REG_CLR_BIT(ah, AR_PHY_65NM_CH1_RXTX2,
AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK);
REG_CLR_BIT(ah, AR_PHY_65NM_CH2_RXTX2,
AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK);
udelay(1);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX2,
AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX2,
AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX2,
AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1);
udelay(200);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH12,
AR_PHY_65NM_CH0_SYNTH12_VREFMUL3, 0xf);
REG_RMW(ah, AR_PHY_65NM_CH0_RXTX2, 0,
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S);
REG_RMW(ah, AR_PHY_65NM_CH1_RXTX2, 0,
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S);
REG_RMW(ah, AR_PHY_65NM_CH2_RXTX2, 0,
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S);
}
}
static int ar9003_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan)
{
......@@ -726,6 +774,8 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
modesIndex);
}
ar9003_doubler_fix(ah);
/*
* RXGAIN initvals.
*/
......
......@@ -656,13 +656,24 @@
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x00000001 : 0x00000002)
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0 : 1)
#define AR_PHY_65NM_CH0_SYNTH7 0x16098
#define AR_PHY_65NM_CH0_SYNTH12 0x160ac
#define AR_PHY_65NM_CH0_BIAS1 0x160c0
#define AR_PHY_65NM_CH0_BIAS2 0x160c4
#define AR_PHY_65NM_CH0_BIAS4 0x160cc
#define AR_PHY_65NM_CH0_RXTX2 0x16104
#define AR_PHY_65NM_CH1_RXTX2 0x16504
#define AR_PHY_65NM_CH2_RXTX2 0x16904
#define AR_PHY_65NM_CH0_RXTX4 0x1610c
#define AR_PHY_65NM_CH1_RXTX4 0x1650c
#define AR_PHY_65NM_CH2_RXTX4 0x1690c
#define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3 0x00780000
#define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3_S 19
#define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK 0x00000004
#define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S 2
#define AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK 0x00000008
#define AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S 3
#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
(((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x1628c : 0x16280)))
#define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300)
......
......@@ -361,7 +361,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = {
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e},
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
......@@ -400,7 +400,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = {
{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000},
{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
{0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce},
{0x0000ae20, 0x000001a6, 0x000001a6, 0x000001aa, 0x000001aa},
{0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
};
......@@ -472,7 +472,7 @@ static const u32 ar9462_2p1_radio_postamble[][5] = {
static const u32 ar9462_2p1_soc_preamble[][2] = {
/* Addr allmodes */
{0x000040a4, 0x00a0c1c9},
{0x000040a4, 0x00a0c9c9},
{0x00007020, 0x00000000},
{0x00007034, 0x00000002},
{0x00007038, 0x000004c2},
......
......@@ -362,7 +362,8 @@ static int __ath_reg_dyn_country(struct wiphy *wiphy,
{
u16 country_code;
if (!ath_is_world_regd(reg))
if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
!ath_is_world_regd(reg))
return -EINVAL;
country_code = ath_regd_find_country_by_name(request->alpha2);
......