Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

Conflicts:
	include/net/bluetooth/bluetooth.h
This commit is contained in:
John W. Linville 2011-11-17 13:11:43 -05:00
commit e11c259f74
205 changed files with 9029 additions and 6464 deletions

View File

@ -69,6 +69,9 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we /* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here. * have to define SOCK_NONBLOCK to a different value here.
*/ */

View File

@ -62,4 +62,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */

View File

@ -62,4 +62,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* __ASM_AVR32_SOCKET_H */ #endif /* __ASM_AVR32_SOCKET_H */

View File

@ -64,6 +64,9 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */

View File

@ -62,5 +62,8 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */

View File

@ -62,4 +62,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */

View File

@ -71,4 +71,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_IA64_SOCKET_H */ #endif /* _ASM_IA64_SOCKET_H */

View File

@ -62,4 +62,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_M32R_SOCKET_H */ #endif /* _ASM_M32R_SOCKET_H */

View File

@ -62,4 +62,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */

View File

@ -82,6 +82,9 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#ifdef __KERNEL__ #ifdef __KERNEL__
/** sock_type - Socket types /** sock_type - Socket types

View File

@ -62,4 +62,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */

View File

@ -61,6 +61,9 @@
#define SO_RXQ_OVFL 0x4021 #define SO_RXQ_OVFL 0x4021
#define SO_WIFI_STATUS 0x4022
#define SCM_WIFI_STATUS SO_WIFI_STATUS
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we /* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here. * have to define SOCK_NONBLOCK to a different value here.
*/ */

View File

@ -69,4 +69,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_POWERPC_SOCKET_H */ #endif /* _ASM_POWERPC_SOCKET_H */

View File

@ -70,4 +70,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _ASM_SOCKET_H */ #endif /* _ASM_SOCKET_H */

View File

@ -58,6 +58,9 @@
#define SO_RXQ_OVFL 0x0024 #define SO_RXQ_OVFL 0x0024
#define SO_WIFI_STATUS 0x0025
#define SCM_WIFI_STATUS SO_WIFI_STATUS
/* Security levels - as per NRL IPv6 - don't actually do anything */ /* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001 #define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002

View File

@ -73,4 +73,7 @@
#define SO_RXQ_OVFL 40 #define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#endif /* _XTENSA_SOCKET_H */ #endif /* _XTENSA_SOCKET_H */

View File

@ -30,6 +30,7 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#define VERSION "1.0" #define VERSION "1.0"
#define ATH3K_FIRMWARE "ath3k-1.fw"
#define ATH3K_DNLOAD 0x01 #define ATH3K_DNLOAD 0x01
#define ATH3K_GETSTATE 0x05 #define ATH3K_GETSTATE 0x05
@ -400,9 +401,15 @@ static int ath3k_probe(struct usb_interface *intf,
return 0; return 0;
} }
if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { ret = request_firmware(&firmware, ATH3K_FIRMWARE, &udev->dev);
BT_ERR("Error loading firmware"); if (ret < 0) {
return -EIO; if (ret == -ENOENT)
BT_ERR("Firmware file \"%s\" not found",
ATH3K_FIRMWARE);
else
BT_ERR("Firmware file \"%s\" request failed (err=%d)",
ATH3K_FIRMWARE, ret);
return ret;
} }
ret = ath3k_load_firmware(udev, firmware); ret = ath3k_load_firmware(udev, firmware);
@ -441,4 +448,4 @@ MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Atheros AR30xx firmware driver"); MODULE_DESCRIPTION("Atheros AR30xx firmware driver");
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE("ath3k-1.fw"); MODULE_FIRMWARE(ATH3K_FIRMWARE);

View File

@ -751,9 +751,7 @@ static void bfusb_disconnect(struct usb_interface *intf)
bfusb_close(hdev); bfusb_close(hdev);
if (hci_unregister_dev(hdev) < 0) hci_unregister_dev(hdev);
BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev); hci_free_dev(hdev);
} }

View File

@ -844,9 +844,7 @@ static int bluecard_close(bluecard_info_t *info)
/* Turn FPGA off */ /* Turn FPGA off */
outb(0x80, iobase + 0x30); outb(0x80, iobase + 0x30);
if (hci_unregister_dev(hdev) < 0) hci_unregister_dev(hdev);
BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev); hci_free_dev(hdev);
return 0; return 0;

View File

@ -636,9 +636,7 @@ static int bt3c_close(bt3c_info_t *info)
bt3c_hci_close(hdev); bt3c_hci_close(hdev);
if (hci_unregister_dev(hdev) < 0) hci_unregister_dev(hdev);
BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev); hci_free_dev(hdev);
return 0; return 0;

View File

@ -565,9 +565,7 @@ static int btuart_close(btuart_info_t *info)
spin_unlock_irqrestore(&(info->lock), flags); spin_unlock_irqrestore(&(info->lock), flags);
if (hci_unregister_dev(hdev) < 0) hci_unregister_dev(hdev);
BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev); hci_free_dev(hdev);
return 0; return 0;

View File

@ -100,6 +100,9 @@ static struct usb_device_id btusb_table[] = {
/* Canyon CN-BTU1 with HID interfaces */ /* Canyon CN-BTU1 with HID interfaces */
{ USB_DEVICE(0x0c10, 0x0000) }, { USB_DEVICE(0x0c10, 0x0000) },
/* Broadcom BCM20702A0 */
{ USB_DEVICE(0x413c, 0x8197) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
@ -312,7 +315,8 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
err = usb_submit_urb(urb, mem_flags); err = usb_submit_urb(urb, mem_flags);
if (err < 0) { if (err < 0) {
BT_ERR("%s urb %p submission failed (%d)", if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err); hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -397,7 +401,8 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
err = usb_submit_urb(urb, mem_flags); err = usb_submit_urb(urb, mem_flags);
if (err < 0) { if (err < 0) {
BT_ERR("%s urb %p submission failed (%d)", if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err); hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -520,7 +525,8 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
err = usb_submit_urb(urb, mem_flags); err = usb_submit_urb(urb, mem_flags);
if (err < 0) { if (err < 0) {
BT_ERR("%s urb %p submission failed (%d)", if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err); hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} }
@ -724,6 +730,9 @@ static int btusb_send_frame(struct sk_buff *skb)
usb_fill_bulk_urb(urb, data->udev, pipe, usb_fill_bulk_urb(urb, data->udev, pipe,
skb->data, skb->len, btusb_tx_complete, skb); skb->data, skb->len, btusb_tx_complete, skb);
if (skb->priority >= HCI_PRIO_MAX - 1)
urb->transfer_flags = URB_ISO_ASAP;
hdev->stat.acl_tx++; hdev->stat.acl_tx++;
break; break;
@ -767,7 +776,9 @@ static int btusb_send_frame(struct sk_buff *skb)
err = usb_submit_urb(urb, GFP_ATOMIC); err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) { if (err < 0) {
BT_ERR("%s urb %p submission failed", hdev->name, urb); if (err != -EPERM && err != -ENODEV)
BT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
kfree(urb->setup_packet); kfree(urb->setup_packet);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
} else { } else {

View File

@ -551,9 +551,7 @@ static int dtl1_close(dtl1_info_t *info)
spin_unlock_irqrestore(&(info->lock), flags); spin_unlock_irqrestore(&(info->lock), flags);
if (hci_unregister_dev(hdev) < 0) hci_unregister_dev(hdev);
BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev); hci_free_dev(hdev);
return 0; return 0;

View File

@ -264,10 +264,7 @@ static int vhci_release(struct inode *inode, struct file *file)
struct vhci_data *data = file->private_data; struct vhci_data *data = file->private_data;
struct hci_dev *hdev = data->hdev; struct hci_dev *hdev = data->hdev;
if (hci_unregister_dev(hdev) < 0) { hci_unregister_dev(hdev);
BT_ERR("Can't unregister HCI device %s", hdev->name);
}
hci_free_dev(hdev); hci_free_dev(hdev);
file->private_data = NULL; file->private_data = NULL;

View File

@ -58,6 +58,6 @@ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
obj-$(CONFIG_IWM) += iwmc3200wifi/ obj-$(CONFIG_IWM) += iwmc3200wifi/
obj-$(CONFIG_MWIFIEX) += mwifiex/ obj-$(CONFIG_MWIFIEX) += mwifiex/
obj-$(CONFIG_BRCMFMAC) += brcm80211/
obj-$(CONFIG_BRCMUMAC) += brcm80211/ obj-$(CONFIG_BRCMFMAC) += brcm80211/
obj-$(CONFIG_BRCMSMAC) += brcm80211/ obj-$(CONFIG_BRCMSMAC) += brcm80211/

View File

@ -239,6 +239,7 @@ enum ATH_DEBUG {
ATH_DBG_BTCOEX = 0x00002000, ATH_DBG_BTCOEX = 0x00002000,
ATH_DBG_WMI = 0x00004000, ATH_DBG_WMI = 0x00004000,
ATH_DBG_BSTUCK = 0x00008000, ATH_DBG_BSTUCK = 0x00008000,
ATH_DBG_MCI = 0x00010000,
ATH_DBG_ANY = 0xffffffff ATH_DBG_ANY = 0xffffffff
}; };

View File

@ -1734,7 +1734,8 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan, bool offchan, struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type, enum nl80211_channel_type channel_type,
bool channel_type_valid, unsigned int wait, bool channel_type_valid, unsigned int wait,
const u8 *buf, size_t len, bool no_cck, u64 *cookie) const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{ {
struct ath6kl *ar = ath6kl_priv(dev); struct ath6kl *ar = ath6kl_priv(dev);
u32 id; u32 id;

View File

@ -1548,7 +1548,8 @@ static int ath6kl_init(struct net_device *dev)
ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
WIPHY_FLAG_HAVE_AP_SME;
status = ath6kl_target_config_wlan_params(ar); status = ath6kl_target_config_wlan_params(ar);
if (!status) if (!status)

View File

@ -25,6 +25,7 @@ config ATH9K
config ATH9K_PCI config ATH9K_PCI
bool "Atheros ath9k PCI/PCIe bus support" bool "Atheros ath9k PCI/PCIe bus support"
default y
depends on ATH9K && PCI depends on ATH9K && PCI
---help--- ---help---
This option enables the PCI bus support in ath9k. This option enables the PCI bus support in ath9k.

View File

@ -4,6 +4,7 @@ ath9k-y += beacon.o \
main.o \ main.o \
recv.o \ recv.o \
xmit.o \ xmit.o \
mci.o \
ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o ath9k-$(CONFIG_ATH9K_PCI) += pci.o

View File

@ -121,10 +121,8 @@ static const struct ar9300_eeprom ar9300_default = {
* if the register is per chain * if the register is per chain
*/ */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {1, 1, 1},/* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {1, 1, 1}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {0, 0, 0},
.db_stage4 = {0, 0, 0},
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -144,7 +142,7 @@ static const struct ar9300_eeprom ar9300_default = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -323,10 +321,8 @@ static const struct ar9300_eeprom ar9300_default = {
.spurChans = {0, 0, 0, 0, 0}, .spurChans = {0, 0, 0, 0, 0},
/* noiseFloorThreshCh Check if the register is per chain */ /* noiseFloorThreshCh Check if the register is per chain */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {3, 3, 3}, /* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {3, 3, 3}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -698,10 +694,8 @@ static const struct ar9300_eeprom ar9300_x113 = {
* if the register is per chain * if the register is per chain
*/ */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {1, 1, 1},/* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {1, 1, 1}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {0, 0, 0},
.db_stage4 = {0, 0, 0},
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -721,7 +715,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -900,10 +894,8 @@ static const struct ar9300_eeprom ar9300_x113 = {
.spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0}, .spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0},
/* noiseFloorThreshCh Check if the register is per chain */ /* noiseFloorThreshCh Check if the register is per chain */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {3, 3, 3}, /* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {3, 3, 3}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
.xpaBiasLvl = 0xf, .xpaBiasLvl = 0xf,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -1276,10 +1268,8 @@ static const struct ar9300_eeprom ar9300_h112 = {
* if the register is per chain * if the register is per chain
*/ */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {1, 1, 1},/* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {1, 1, 1}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {0, 0, 0},
.db_stage4 = {0, 0, 0},
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -1291,20 +1281,20 @@ static const struct ar9300_eeprom ar9300_h112 = {
.txEndToRxOn = 0x2, .txEndToRxOn = 0x2,
.txFrameToXpaOn = 0xe, .txFrameToXpaOn = 0xe,
.thresh62 = 28, .thresh62 = 28,
.papdRateMaskHt20 = LE32(0x80c080), .papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x80c080), .papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = { .futureModal = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}, },
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
FREQ2FBIN(2437, 1), FREQ2FBIN(2437, 1),
FREQ2FBIN(2472, 1), FREQ2FBIN(2462, 1),
}, },
/* ar9300_cal_data_per_freq_op_loop 2g */ /* ar9300_cal_data_per_freq_op_loop 2g */
.calPierData2G = { .calPierData2G = {
@ -1314,7 +1304,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
}, },
.calTarget_freqbin_Cck = { .calTarget_freqbin_Cck = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
FREQ2FBIN(2484, 1), FREQ2FBIN(2472, 1),
}, },
.calTarget_freqbin_2G = { .calTarget_freqbin_2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -1478,10 +1468,8 @@ static const struct ar9300_eeprom ar9300_h112 = {
.spurChans = {0, 0, 0, 0, 0}, .spurChans = {0, 0, 0, 0, 0},
/* noiseFloorThreshCh Check if the register is per chain */ /* noiseFloorThreshCh Check if the register is per chain */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {3, 3, 3}, /* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {3, 3, 3}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -1515,7 +1503,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
FREQ2FBIN(5500, 0), FREQ2FBIN(5500, 0),
FREQ2FBIN(5600, 0), FREQ2FBIN(5600, 0),
FREQ2FBIN(5700, 0), FREQ2FBIN(5700, 0),
FREQ2FBIN(5825, 0) FREQ2FBIN(5785, 0)
}, },
.calPierData5G = { .calPierData5G = {
{ {
@ -1854,10 +1842,8 @@ static const struct ar9300_eeprom ar9300_x112 = {
* if the register is per chain * if the register is per chain
*/ */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {1, 1, 1},/* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {1, 1, 1}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {0, 0, 0},
.db_stage4 = {0, 0, 0},
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -1877,7 +1863,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
@ -2056,10 +2042,8 @@ static const struct ar9300_eeprom ar9300_x112 = {
.spurChans = {0, 0, 0, 0, 0}, .spurChans = {0, 0, 0, 0, 0},
/* noiseFloorThreshch check if the register is per chain */ /* noiseFloorThreshch check if the register is per chain */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {3, 3, 3}, /* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {3, 3, 3}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -2431,10 +2415,8 @@ static const struct ar9300_eeprom ar9300_h116 = {
* if the register is per chain * if the register is per chain
*/ */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {1, 1, 1},/* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {1, 1, 1}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {0, 0, 0},
.db_stage4 = {0, 0, 0},
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -2454,12 +2436,12 @@ static const struct ar9300_eeprom ar9300_h116 = {
}, },
.base_ext1 = { .base_ext1 = {
.ant_div_control = 0, .ant_div_control = 0,
.future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}, },
.calFreqPier2G = { .calFreqPier2G = {
FREQ2FBIN(2412, 1), FREQ2FBIN(2412, 1),
FREQ2FBIN(2437, 1), FREQ2FBIN(2437, 1),
FREQ2FBIN(2472, 1), FREQ2FBIN(2462, 1),
}, },
/* ar9300_cal_data_per_freq_op_loop 2g */ /* ar9300_cal_data_per_freq_op_loop 2g */
.calPierData2G = { .calPierData2G = {
@ -2633,10 +2615,8 @@ static const struct ar9300_eeprom ar9300_h116 = {
.spurChans = {0, 0, 0, 0, 0}, .spurChans = {0, 0, 0, 0, 0},
/* noiseFloorThreshCh Check if the register is per chain */ /* noiseFloorThreshCh Check if the register is per chain */
.noiseFloorThreshCh = {-1, 0, 0}, .noiseFloorThreshCh = {-1, 0, 0},
.ob = {3, 3, 3}, /* 3 chain */ .reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.db_stage2 = {3, 3, 3}, /* 3 chain */ .quick_drop = 0,
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
.xpaBiasLvl = 0, .xpaBiasLvl = 0,
.txFrameToDataStart = 0x0e, .txFrameToDataStart = 0x0e,
.txFrameToPaOn = 0x0e, .txFrameToPaOn = 0x0e,
@ -2663,7 +2643,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.xatten1MarginHigh = {0, 0, 0} .xatten1MarginHigh = {0, 0, 0}
}, },
.calFreqPier5G = { .calFreqPier5G = {
FREQ2FBIN(5180, 0), FREQ2FBIN(5160, 0),
FREQ2FBIN(5220, 0), FREQ2FBIN(5220, 0),
FREQ2FBIN(5320, 0), FREQ2FBIN(5320, 0),
FREQ2FBIN(5400, 0), FREQ2FBIN(5400, 0),
@ -3023,6 +3003,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
return eep->modalHeader5G.antennaGain; return eep->modalHeader5G.antennaGain;
case EEP_ANTENNA_GAIN_2G: case EEP_ANTENNA_GAIN_2G:
return eep->modalHeader2G.antennaGain; return eep->modalHeader2G.antennaGain;
case EEP_QUICK_DROP:
return pBase->miscConfiguration & BIT(1);
default: default:
return 0; return 0;
} }
@ -3428,25 +3410,14 @@ static u32 ar9003_dump_modal_eeprom(char *buf, u32 len, u32 size,
PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]); PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]); PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]); PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
PR_EEP("Quick Drop", modal_hdr->quick_drop);
PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl); PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart); PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn); PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn); PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
PR_EEP("txClip", modal_hdr->txClip); PR_EEP("txClip", modal_hdr->txClip);
PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize); PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
PR_EEP("Chain0 ob", modal_hdr->ob[0]);
PR_EEP("Chain1 ob", modal_hdr->ob[1]);
PR_EEP("Chain2 ob", modal_hdr->ob[2]);
PR_EEP("Chain0 db_stage2", modal_hdr->db_stage2[0]);
PR_EEP("Chain1 db_stage2", modal_hdr->db_stage2[1]);
PR_EEP("Chain2 db_stage2", modal_hdr->db_stage2[2]);
PR_EEP("Chain0 db_stage3", modal_hdr->db_stage3[0]);
PR_EEP("Chain1 db_stage3", modal_hdr->db_stage3[1]);
PR_EEP("Chain2 db_stage3", modal_hdr->db_stage3[2]);
PR_EEP("Chain0 db_stage4", modal_hdr->db_stage4[0]);
PR_EEP("Chain1 db_stage4", modal_hdr->db_stage4[1]);
PR_EEP("Chain2 db_stage4", modal_hdr->db_stage4[2]);
return len; return len;
} }
@ -3503,6 +3474,7 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
PR_EEP("Internal regulator", !!(pBase->featureEnable & BIT(4))); PR_EEP("Internal regulator", !!(pBase->featureEnable & BIT(4)));
PR_EEP("Enable Paprd", !!(pBase->featureEnable & BIT(5))); PR_EEP("Enable Paprd", !!(pBase->featureEnable & BIT(5)));
PR_EEP("Driver Strength", !!(pBase->miscConfiguration & BIT(0))); PR_EEP("Driver Strength", !!(pBase->miscConfiguration & BIT(0)));
PR_EEP("Quick Drop", !!(pBase->miscConfiguration & BIT(1)));
PR_EEP("Chain mask Reduce", (pBase->miscConfiguration >> 0x3) & 0x1); PR_EEP("Chain mask Reduce", (pBase->miscConfiguration >> 0x3) & 0x1);
PR_EEP("Write enable Gpio", pBase->eepromWriteEnableGpio); PR_EEP("Write enable Gpio", pBase->eepromWriteEnableGpio);
PR_EEP("WLAN Disable Gpio", pBase->wlanDisableGpio); PR_EEP("WLAN Disable Gpio", pBase->wlanDisableGpio);
@ -3965,6 +3937,40 @@ static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
} }
} }
static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
int quick_drop = ath9k_hw_ar9300_get_eeprom(ah, EEP_QUICK_DROP);
s32 t[3], f[3] = {5180, 5500, 5785};
if (!quick_drop)
return;
if (freq < 4000)
quick_drop = eep->modalHeader2G.quick_drop;
else {
t[0] = eep->base_ext1.quick_drop_low;
t[1] = eep->modalHeader5G.quick_drop;
t[2] = eep->base_ext1.quick_drop_high;
quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
}
REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
}
static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, u16 freq)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
u32 value;
value = (freq < 4000) ? eep->modalHeader2G.txEndToXpaOff :
eep->modalHeader5G.txEndToXpaOff;
REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF, value);
REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF, value);
}
static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
@ -3972,10 +3978,12 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
ar9003_hw_drive_strength_apply(ah); ar9003_hw_drive_strength_apply(ah);
ar9003_hw_atten_apply(ah, chan); ar9003_hw_atten_apply(ah, chan);
ar9003_hw_quick_drop_apply(ah, chan->channel);
if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah)) if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
ar9003_hw_internal_regulator_apply(ah); ar9003_hw_internal_regulator_apply(ah);
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah)) if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
ar9003_hw_apply_tuning_caps(ah); ar9003_hw_apply_tuning_caps(ah);
ar9003_hw_txend_to_xpa_off_apply(ah, chan->channel);
} }
static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah, static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
@ -5051,6 +5059,8 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
regulatory->max_power_level = targetPowerValT2[i]; regulatory->max_power_level = targetPowerValT2[i];
} }
ath9k_hw_update_regulatory_maxpower(ah);
if (test) if (test)
return; return;

View File

@ -216,10 +216,8 @@ struct ar9300_modal_eep_header {
u8 spurChans[AR_EEPROM_MODAL_SPURS]; u8 spurChans[AR_EEPROM_MODAL_SPURS];
/* 3 Check if the register is per chain */ /* 3 Check if the register is per chain */
int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS]; int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS];
u8 ob[AR9300_MAX_CHAINS]; u8 reserved[11];
u8 db_stage2[AR9300_MAX_CHAINS]; int8_t quick_drop;
u8 db_stage3[AR9300_MAX_CHAINS];
u8 db_stage4[AR9300_MAX_CHAINS];
u8 xpaBiasLvl; u8 xpaBiasLvl;
u8 txFrameToDataStart; u8 txFrameToDataStart;
u8 txFrameToPaOn; u8 txFrameToPaOn;
@ -269,7 +267,9 @@ struct cal_ctl_data_5g {
struct ar9300_BaseExtension_1 { struct ar9300_BaseExtension_1 {
u8 ant_div_control; u8 ant_div_control;
u8 future[13]; u8 future[11];
int8_t quick_drop_low;
int8_t quick_drop_high;
} __packed; } __packed;
struct ar9300_BaseExtension_2 { struct ar9300_BaseExtension_2 {

View File

@ -199,12 +199,14 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
synth_freq = chan->channel; synth_freq = chan->channel;
} }
} else { } else {
range = 10; range = AR_SREV_9462(ah) ? 5 : 10;
max_spur_cnts = 4; max_spur_cnts = 4;
synth_freq = chan->channel; synth_freq = chan->channel;
} }
for (i = 0; i < max_spur_cnts; i++) { for (i = 0; i < max_spur_cnts; i++) {
if (AR_SREV_9462(ah) && (i == 0 || i == 3))
continue;
negative = 0; negative = 0;
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i], cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],

View File

@ -389,6 +389,8 @@
#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 #define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
#define AR_PHY_RIFS_INIT_DELAY 0x3ff0000 #define AR_PHY_RIFS_INIT_DELAY 0x3ff0000
#define AR_PHY_AGC_QUICK_DROP 0x03c00000
#define AR_PHY_AGC_QUICK_DROP_S 22
#define AR_PHY_AGC_COARSE_LOW 0x00007F80 #define AR_PHY_AGC_COARSE_LOW 0x00007F80
#define AR_PHY_AGC_COARSE_LOW_S 7 #define AR_PHY_AGC_COARSE_LOW_S 7
#define AR_PHY_AGC_COARSE_HIGH 0x003F8000 #define AR_PHY_AGC_COARSE_HIGH 0x003F8000

View File

@ -43,16 +43,16 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x5ac640de},
{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x0796be89},
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x92c84d2e},
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3039605e, 0x33795d5e}, {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
@ -688,8 +688,8 @@ static const u32 ar9462_2p0_mac_postamble_emulation[][5] = {
static const u32 ar9462_2p0_radio_postamble_sys3ant[][5] = { static const u32 ar9462_2p0_radio_postamble_sys3ant[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
{0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008}, {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
{0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008}, {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
}; };
static const u32 ar9462_2p0_baseband_postamble_emulation[][5] = { static const u32 ar9462_2p0_baseband_postamble_emulation[][5] = {
@ -717,8 +717,8 @@ static const u32 ar9462_2p0_baseband_postamble_emulation[][5] = {
static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = { static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
{0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008}, {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
{0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008}, {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
}; };
static const u32 ar9462_common_wo_xlna_rx_gain_table_2p0[][2] = { static const u32 ar9462_common_wo_xlna_rx_gain_table_2p0[][2] = {
@ -1059,7 +1059,7 @@ static const u32 ar9462_modes_low_ob_db_tx_gain_table_2p0[][5] = {
static const u32 ar9462_2p0_soc_postamble[][5] = { static const u32 ar9462_2p0_soc_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00007010, 0x00002233, 0x00002233, 0x00002233, 0x00002233}, {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033},
}; };
static const u32 ar9462_2p0_baseband_core[][2] = { static const u32 ar9462_2p0_baseband_core[][2] = {
@ -1257,8 +1257,8 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
{0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
{0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
{0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
{0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
{0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
@ -1850,8 +1850,8 @@ static const u32 ar9462_modes_green_ob_db_tx_gain_table_2p0[][5] = {
{0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
{0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
{0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
{0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
{0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},

View File

@ -25,6 +25,7 @@
#include "debug.h" #include "debug.h"
#include "common.h" #include "common.h"
#include "mci.h"
/* /*
* Header for the ath9k.ko driver core *only* -- hw code nor any other driver * Header for the ath9k.ko driver core *only* -- hw code nor any other driver
@ -252,6 +253,7 @@ struct ath_node {
#ifdef CONFIG_ATH9K_DEBUGFS #ifdef CONFIG_ATH9K_DEBUGFS
struct list_head list; /* for sc->nodes */ struct list_head list; /* for sc->nodes */
struct ieee80211_sta *sta; /* station struct we're part of */ struct ieee80211_sta *sta; /* station struct we're part of */
struct ieee80211_vif *vif; /* interface with which we're associated */
#endif #endif
struct ath_atx_tid tid[WME_NUM_TID]; struct ath_atx_tid tid[WME_NUM_TID];
struct ath_atx_ac ac[WME_NUM_AC]; struct ath_atx_ac ac[WME_NUM_AC];
@ -443,7 +445,9 @@ struct ath_btcoex {
u32 btcoex_no_stomp; /* in usec */ u32 btcoex_no_stomp; /* in usec */
u32 btcoex_period; /* in usec */ u32 btcoex_period; /* in usec */
u32 btscan_no_stomp; /* in usec */ u32 btscan_no_stomp; /* in usec */
u32 duty_cycle;
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
struct ath_mci_profile mci;
}; };
int ath_init_btcoex_timer(struct ath_softc *sc); int ath_init_btcoex_timer(struct ath_softc *sc);

View File

@ -709,24 +709,29 @@ static ssize_t read_file_stations(struct file *file, char __user *user_buf,
len += snprintf(buf + len, size - len, len += snprintf(buf + len, size - len,
"Stations:\n" "Stations:\n"
" tid: addr sched paused buf_q-empty an ac\n" " tid: addr sched paused buf_q-empty an ac baw\n"
" ac: addr sched tid_q-empty txq\n"); " ac: addr sched tid_q-empty txq\n");
spin_lock(&sc->nodes_lock); spin_lock(&sc->nodes_lock);
list_for_each_entry(an, &sc->nodes, list) { list_for_each_entry(an, &sc->nodes, list) {
unsigned short ma = an->maxampdu;
if (ma == 0)
ma = 65535; /* see ath_lookup_rate */
len += snprintf(buf + len, size - len, len += snprintf(buf + len, size - len,
"%pM\n", an->sta->addr); "iface: %pM sta: %pM max-ampdu: %hu mpdu-density: %uus\n",
an->vif->addr, an->sta->addr, ma,
(unsigned int)(an->mpdudensity));
if (len >= size) if (len >= size)
goto done; goto done;
for (q = 0; q < WME_NUM_TID; q++) { for (q = 0; q < WME_NUM_TID; q++) {
struct ath_atx_tid *tid = &(an->tid[q]); struct ath_atx_tid *tid = &(an->tid[q]);
len += snprintf(buf + len, size - len, len += snprintf(buf + len, size - len,
" tid: %p %s %s %i %p %p\n", " tid: %p %s %s %i %p %p %hu\n",
tid, tid->sched ? "sched" : "idle", tid, tid->sched ? "sched" : "idle",
tid->paused ? "paused" : "running", tid->paused ? "paused" : "running",
skb_queue_empty(&tid->buf_q), skb_queue_empty(&tid->buf_q),
tid->an, tid->ac); tid->an, tid->ac, tid->baw_size);
if (len >= size) if (len >= size)
goto done; goto done;
} }

View File

@ -249,7 +249,8 @@ enum eeprom_param {
EEP_ANT_DIV_CTL1, EEP_ANT_DIV_CTL1,
EEP_CHAIN_MASK_REDUCE, EEP_CHAIN_MASK_REDUCE,
EEP_ANTENNA_GAIN_2G, EEP_ANTENNA_GAIN_2G,
EEP_ANTENNA_GAIN_5G EEP_ANTENNA_GAIN_5G,
EEP_QUICK_DROP
}; };
enum ar5416_rates { enum ar5416_rates {

View File

@ -189,8 +189,8 @@ static void ath_btcoex_period_timer(unsigned long data)
bool is_btscan; bool is_btscan;
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ath_detect_bt_priority(sc); if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
ath_detect_bt_priority(sc);
is_btscan = sc->sc_flags & SC_OP_BT_SCAN; is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
spin_lock_bh(&btcoex->btcoex_lock); spin_lock_bh(&btcoex->btcoex_lock);
@ -212,8 +212,9 @@ static void ath_btcoex_period_timer(unsigned long data)
} }
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
timer_period = btcoex->btcoex_period / 1000;
mod_timer(&btcoex->period_timer, jiffies + mod_timer(&btcoex->period_timer, jiffies +
msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); msecs_to_jiffies(timer_period));
} }
/* /*

View File

@ -2335,7 +2335,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
ah->enabled_cals |= TX_IQ_ON_AGC_CAL; ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
} }
if (AR_SREV_9462(ah)) if (AR_SREV_9462(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RTT; pCap->hw_caps |= ATH9K_HW_CAP_RTT | ATH9K_HW_CAP_MCI;
return 0; return 0;
} }
@ -2583,7 +2583,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
struct ath9k_channel *chan = ah->curchan; struct ath9k_channel *chan = ah->curchan;
struct ieee80211_channel *channel = chan->chan; struct ieee80211_channel *channel = chan->chan;
reg->power_limit = min_t(int, limit, MAX_RATE_POWER); reg->power_limit = min_t(u32, limit, MAX_RATE_POWER);
if (test) if (test)
channel->max_power = MAX_RATE_POWER / 2; channel->max_power = MAX_RATE_POWER / 2;

View File

@ -203,6 +203,7 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_5GHZ = BIT(14), ATH9K_HW_CAP_5GHZ = BIT(14),
ATH9K_HW_CAP_APM = BIT(15), ATH9K_HW_CAP_APM = BIT(15),
ATH9K_HW_CAP_RTT = BIT(16), ATH9K_HW_CAP_RTT = BIT(16),
ATH9K_HW_CAP_MCI = BIT(17),
}; };
struct ath9k_hw_capabilities { struct ath9k_hw_capabilities {
@ -419,6 +420,16 @@ enum ath9k_rx_qtype {
ATH9K_RX_QUEUE_MAX, ATH9K_RX_QUEUE_MAX,
}; };
enum ath_mci_gpm_coex_profile_type {
MCI_GPM_COEX_PROFILE_UNKNOWN,
MCI_GPM_COEX_PROFILE_RFCOMM,
MCI_GPM_COEX_PROFILE_A2DP,
MCI_GPM_COEX_PROFILE_HID,
MCI_GPM_COEX_PROFILE_BNEP,
MCI_GPM_COEX_PROFILE_VOICE,
MCI_GPM_COEX_PROFILE_MAX
};
struct ath9k_beacon_state { struct ath9k_beacon_state {
u32 bs_nexttbtt; u32 bs_nexttbtt;
u32 bs_nextdtim; u32 bs_nextdtim;

View File

@ -424,6 +424,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
txq = sc->tx.txq_map[WME_AC_BE]; txq = sc->tx.txq_map[WME_AC_BE];
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
INIT_LIST_HEAD(&sc->btcoex.mci.info);
break; break;
default: default:
WARN_ON(1); WARN_ON(1);
@ -695,6 +697,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
hw->queues = 4; hw->queues = 4;
hw->max_rates = 4; hw->max_rates = 4;

View File

@ -630,7 +630,8 @@ void ath_ani_calibrate(unsigned long data)
} }
} }
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
struct ieee80211_vif *vif)
{ {
struct ath_node *an; struct ath_node *an;
an = (struct ath_node *)sta->drv_priv; an = (struct ath_node *)sta->drv_priv;
@ -640,6 +641,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
list_add(&an->list, &sc->nodes); list_add(&an->list, &sc->nodes);
spin_unlock(&sc->nodes_lock); spin_unlock(&sc->nodes_lock);
an->sta = sta; an->sta = sta;
an->vif = vif;
#endif #endif
if (sc->sc_flags & SC_OP_TXAGGR) { if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an); ath_tx_node_init(sc, an);
@ -1133,8 +1135,9 @@ static int ath9k_start(struct ieee80211_hw *hw)
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
!ah->btcoex_hw.enabled) { !ah->btcoex_hw.enabled) {
ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
AR_STOMP_LOW_WLAN_WGHT); ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
AR_STOMP_LOW_WLAN_WGHT);
ath9k_hw_btcoex_enable(ah); ath9k_hw_btcoex_enable(ah);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
@ -1237,6 +1240,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath9k_hw_btcoex_disable(ah); ath9k_hw_btcoex_disable(ah);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_pause(sc); ath9k_btcoex_timer_pause(sc);
ath_mci_flush_profile(&sc->btcoex.mci);
} }
spin_lock_bh(&sc->sc_pcu_lock); spin_lock_bh(&sc->sc_pcu_lock);
@ -1798,7 +1802,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
struct ath_node *an = (struct ath_node *) sta->drv_priv; struct ath_node *an = (struct ath_node *) sta->drv_priv;
struct ieee80211_key_conf ps_key = { }; struct ieee80211_key_conf ps_key = { };
ath_node_attach(sc, sta); ath_node_attach(sc, sta, vif);
if (vif->type != NL80211_IFTYPE_AP && if (vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_AP_VLAN) vif->type != NL80211_IFTYPE_AP_VLAN)

View File

@ -0,0 +1,254 @@
/*
* 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.
*/
#include "ath9k.h"
#include "mci.h"
u8 ath_mci_duty_cycle[] = { 0, 50, 60, 70, 80, 85, 90, 95, 98 };
static struct ath_mci_profile_info*
ath_mci_find_profile(struct ath_mci_profile *mci,
struct ath_mci_profile_info *info)
{
struct ath_mci_profile_info *entry;
list_for_each_entry(entry, &mci->info, list) {
if (entry->conn_handle == info->conn_handle)
break;
}
return entry;
}
static bool ath_mci_add_profile(struct ath_common *common,
struct ath_mci_profile *mci,
struct ath_mci_profile_info *info)
{
struct ath_mci_profile_info *entry;
if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
(info->type == MCI_GPM_COEX_PROFILE_VOICE)) {
ath_dbg(common, ATH_DBG_MCI,
"Too many SCO profile, failed to add new profile\n");
return false;
}
if (((NUM_PROF(mci) - mci->num_sco) == ATH_MCI_MAX_ACL_PROFILE) &&
(info->type != MCI_GPM_COEX_PROFILE_VOICE)) {
ath_dbg(common, ATH_DBG_MCI,
"Too many ACL profile, failed to add new profile\n");
return false;
}
entry = ath_mci_find_profile(mci, info);
if (entry)
memcpy(entry, info, 10);
else {
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return false;
memcpy(entry, info, 10);
INC_PROF(mci, info);
list_add_tail(&info->list, &mci->info);
}
return true;
}
static void ath_mci_del_profile(struct ath_common *common,
struct ath_mci_profile *mci,
struct ath_mci_profile_info *info)
{
struct ath_mci_profile_info *entry;
entry = ath_mci_find_profile(mci, info);
if (!entry) {
ath_dbg(common, ATH_DBG_MCI,
"Profile to be deleted not found\n");
return;
}
DEC_PROF(mci, entry);
list_del(&entry->list);
kfree(entry);
}
void ath_mci_flush_profile(struct ath_mci_profile *mci)
{
struct ath_mci_profile_info *info, *tinfo;
list_for_each_entry_safe(info, tinfo, &mci->info, list) {
list_del(&info->list);
DEC_PROF(mci, info);
kfree(info);
}
mci->aggr_limit = 0;
}
static void ath_mci_adjust_aggr_limit(struct ath_btcoex *btcoex)
{
struct ath_mci_profile *mci = &btcoex->mci;
u32 wlan_airtime = btcoex->btcoex_period *
(100 - btcoex->duty_cycle) / 100;
/*
* Scale: wlan_airtime is in ms, aggr_limit is in 0.25 ms.
* When wlan_airtime is less than 4ms, aggregation limit has to be
* adjusted half of wlan_airtime to ensure that the aggregation can fit
* without collision with BT traffic.
*/
if ((wlan_airtime <= 4) &&
(!mci->aggr_limit || (mci->aggr_limit > (2 * wlan_airtime))))
mci->aggr_limit = 2 * wlan_airtime;
}
static void ath_mci_update_scheme(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_btcoex *btcoex = &sc->btcoex;
struct ath_mci_profile *mci = &btcoex->mci;
struct ath_mci_profile_info *info;
u32 num_profile = NUM_PROF(mci);
if (num_profile == 1) {
info = list_first_entry(&mci->info,
struct ath_mci_profile_info,
list);
if (mci->num_sco && info->T == 12) {
mci->aggr_limit = 8;
ath_dbg(common, ATH_DBG_MCI,
"Single SCO, aggregation limit 2 ms\n");
} else if ((info->type == MCI_GPM_COEX_PROFILE_BNEP) &&
!info->master) {
btcoex->btcoex_period = 60;
ath_dbg(common, ATH_DBG_MCI,
"Single slave PAN/FTP, bt period 60 ms\n");
} else if ((info->type == MCI_GPM_COEX_PROFILE_HID) &&
(info->T > 0 && info->T < 50) &&
(info->A > 1 || info->W > 1)) {
btcoex->duty_cycle = 30;
mci->aggr_limit = 8;
ath_dbg(common, ATH_DBG_MCI,
"Multiple attempt/timeout single HID "
"aggregation limit 2 ms dutycycle 30%%\n");
}
} else if ((num_profile == 2) && (mci->num_hid == 2)) {
btcoex->duty_cycle = 30;
mci->aggr_limit = 8;
ath_dbg(common, ATH_DBG_MCI,
"Two HIDs aggregation limit 2 ms dutycycle 30%%\n");
} else if (num_profile > 3) {
mci->aggr_limit = 6;
ath_dbg(common, ATH_DBG_MCI,
"Three or more profiles aggregation limit 1.5 ms\n");
}
if (IS_CHAN_2GHZ(sc->sc_ah->curchan)) {
if (IS_CHAN_HT(sc->sc_ah->curchan))
ath_mci_adjust_aggr_limit(btcoex);
else
btcoex->btcoex_period >>= 1;
}
ath9k_hw_btcoex_disable(sc->sc_ah);
ath9k_btcoex_timer_pause(sc);
if (IS_CHAN_5GHZ(sc->sc_ah->curchan))
return;
btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_MAX_DUTY_CYCLE : 0);
if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE)
btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE;
btcoex->btcoex_period *= 1000;
btcoex->btcoex_no_stomp = btcoex->btcoex_period *
(100 - btcoex->duty_cycle) / 100;
ath9k_hw_btcoex_enable(sc->sc_ah);
ath9k_btcoex_timer_resume(sc);
}
void ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *info)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_btcoex *btcoex = &sc->btcoex;
struct ath_mci_profile *mci = &btcoex->mci;
if (info->start) {
if (!ath_mci_add_profile(common, mci, info))
return;
} else
ath_mci_del_profile(common, mci, info);
btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD;
mci->aggr_limit = mci->num_sco ? 6 : 0;
if (NUM_PROF(mci)) {
btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)];
} else {
btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL :
ATH_BTCOEX_STOMP_LOW;
btcoex->duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
}
ath_mci_update_scheme(sc);
}
void ath_mci_process_status(struct ath_softc *sc,
struct ath_mci_profile_status *status)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_btcoex *btcoex = &sc->btcoex;
struct ath_mci_profile *mci = &btcoex->mci;
struct ath_mci_profile_info info;
int i = 0, old_num_mgmt = mci->num_mgmt;
/* Link status type are not handled */
if (status->is_link) {
ath_dbg(common, ATH_DBG_MCI,
"Skip link type status update\n");
return;
}
memset(&info, 0, sizeof(struct ath_mci_profile_info));
info.conn_handle = status->conn_handle;
if (ath_mci_find_profile(mci, &info)) {
ath_dbg(common, ATH_DBG_MCI,
"Skip non link state update for existing profile %d\n",
status->conn_handle);
return;
}
if (status->conn_handle >= ATH_MCI_MAX_PROFILE) {
ath_dbg(common, ATH_DBG_MCI,
"Ignore too many non-link update\n");
return;
}
if (status->is_critical)
__set_bit(status->conn_handle, mci->status);
else
__clear_bit(status->conn_handle, mci->status);
mci->num_mgmt = 0;
do {
if (test_bit(i, mci->status))
mci->num_mgmt++;
} while (++i < ATH_MCI_MAX_PROFILE);
if (old_num_mgmt != mci->num_mgmt)
ath_mci_update_scheme(sc);
}

View File

@ -0,0 +1,118 @@
/*
* 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 MCI_H
#define MCI_H
#define ATH_MCI_DEF_BT_PERIOD 40
#define ATH_MCI_BDR_DUTY_CYCLE 20
#define ATH_MCI_MAX_DUTY_CYCLE 90
#define ATH_MCI_DEF_AGGR_LIMIT 6 /* in 0.24 ms */
#define ATH_MCI_MAX_ACL_PROFILE 7
#define ATH_MCI_MAX_SCO_PROFILE 1
#define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\
ATH_MCI_MAX_SCO_PROFILE)
#define INC_PROF(_mci, _info) do { \
switch (_info->type) { \
case MCI_GPM_COEX_PROFILE_RFCOMM:\
_mci->num_other_acl++; \
break; \
case MCI_GPM_COEX_PROFILE_A2DP: \
_mci->num_a2dp++; \
if (!_info->edr) \
_mci->num_bdr++; \
break; \
case MCI_GPM_COEX_PROFILE_HID: \
_mci->num_hid++; \
break; \
case MCI_GPM_COEX_PROFILE_BNEP: \
_mci->num_pan++; \
break; \
case MCI_GPM_COEX_PROFILE_VOICE: \
_mci->num_sco++; \
break; \
default: \
break; \
} \
} while (0)
#define DEC_PROF(_mci, _info) do { \
switch (_info->type) { \
case MCI_GPM_COEX_PROFILE_RFCOMM:\
_mci->num_other_acl--; \
break; \
case MCI_GPM_COEX_PROFILE_A2DP: \
_mci->num_a2dp--; \
if (!_info->edr) \
_mci->num_bdr--; \
break; \
case MCI_GPM_COEX_PROFILE_HID: \
_mci->num_hid--; \
break; \
case MCI_GPM_COEX_PROFILE_BNEP: \
_mci->num_pan--; \
break; \
case MCI_GPM_COEX_PROFILE_VOICE: \
_mci->num_sco--; \
break; \
default: \
break; \
} \
} while (0)
#define NUM_PROF(_mci) (_mci->num_other_acl + _mci->num_a2dp + \
_mci->num_hid + _mci->num_pan + _mci->num_sco)
struct ath_mci_profile_info {
u8 type;
u8 conn_handle;
bool start;
bool master;
bool edr;
u8 voice_type;
u16 T; /* Voice: Tvoice, HID: Tsniff, in slots */
u8 W; /* Voice: Wvoice, HID: Sniff timeout, in slots */
u8 A; /* HID: Sniff attempt, in slots */
struct list_head list;
};
struct ath_mci_profile_status {
bool is_critical;
bool is_link;
u8 conn_handle;
};
struct ath_mci_profile {
struct list_head info;
DECLARE_BITMAP(status, ATH_MCI_MAX_PROFILE);
u16 aggr_limit;
u8 num_mgmt;
u8 num_sco;
u8 num_a2dp;
u8 num_hid;
u8 num_pan;
u8 num_other_acl;
u8 num_bdr;
};
void ath_mci_flush_profile(struct ath_mci_profile *mci);
void ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *info);
void ath_mci_process_status(struct ath_softc *sc,
struct ath_mci_profile_status *status);
#endif

View File

@ -601,6 +601,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
struct sk_buff *skb; struct sk_buff *skb;
struct ieee80211_tx_info *tx_info; struct ieee80211_tx_info *tx_info;
struct ieee80211_tx_rate *rates; struct ieee80211_tx_rate *rates;
struct ath_mci_profile *mci = &sc->btcoex.mci;
u32 max_4ms_framelen, frmlen; u32 max_4ms_framelen, frmlen;
u16 aggr_limit, legacy = 0; u16 aggr_limit, legacy = 0;
int i; int i;
@ -645,7 +646,9 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
return 0; return 0;
if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED) if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit)
aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4;
else if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED)
aggr_limit = min((max_4ms_framelen * 3) / 8, aggr_limit = min((max_4ms_framelen * 3) / 8,
(u32)ATH_AMPDU_LIMIT_MAX); (u32)ATH_AMPDU_LIMIT_MAX);
else else

View File

@ -254,6 +254,8 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
int r; int r;
sband = wiphy->bands[IEEE80211_BAND_2GHZ]; sband = wiphy->bands[IEEE80211_BAND_2GHZ];
if (!sband)
return;
/* /*
* If no country IE has been received always enable active scan * If no country IE has been received always enable active scan

View File

@ -175,6 +175,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
} }
} }
/* TODO: verify if needed for SSLPN or LCN */
static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate) static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
{ {
const struct b43_phy *phy = &dev->phy; const struct b43_phy *phy = &dev->phy;
@ -256,6 +257,9 @@ int b43_generate_txhdr(struct b43_wldev *dev,
unsigned int plcp_fragment_len; unsigned int plcp_fragment_len;
u32 mac_ctl = 0; u32 mac_ctl = 0;
u16 phy_ctl = 0; u16 phy_ctl = 0;
bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP ||
phy->type == B43_PHYTYPE_N ||
phy->type == B43_PHYTYPE_HT);
u8 extra_ft = 0; u8 extra_ft = 0;
struct ieee80211_rate *txrate; struct ieee80211_rate *txrate;
struct ieee80211_tx_rate *rates; struct ieee80211_tx_rate *rates;
@ -531,7 +535,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
extra_ft |= B43_TXH_EFT_RTSFB_CCK; extra_ft |= B43_TXH_EFT_RTSFB_CCK;
if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS && if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
phy->type == B43_PHYTYPE_N) { fill_phy_ctl1) {
txhdr->phy_ctl1_rts = cpu_to_le16( txhdr->phy_ctl1_rts = cpu_to_le16(
b43_generate_tx_phy_ctl1(dev, rts_rate)); b43_generate_tx_phy_ctl1(dev, rts_rate));
txhdr->phy_ctl1_rts_fb = cpu_to_le16( txhdr->phy_ctl1_rts_fb = cpu_to_le16(
@ -552,7 +556,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
break; break;
} }
if (phy->type == B43_PHYTYPE_N) { if (fill_phy_ctl1) {
txhdr->phy_ctl1 = txhdr->phy_ctl1 =
cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate)); cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
txhdr->phy_ctl1_fb = txhdr->phy_ctl1_fb =
@ -736,7 +740,14 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
/* Link quality statistics */ /* Link quality statistics */
switch (chanstat & B43_RX_CHAN_PHYTYPE) { switch (chanstat & B43_RX_CHAN_PHYTYPE) {
case B43_PHYTYPE_HT:
/* TODO: is max the right choice? */
status.signal = max_t(__s8,
max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1),
rxhdr->phy_ht_power2);
break;
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
/* Broadcom has code for min and avg, but always uses max */
if (rxhdr->power0 == 16 || rxhdr->power0 == 32) if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
status.signal = max(rxhdr->power1, rxhdr->power2); status.signal = max(rxhdr->power1, rxhdr->power2);
else else

View File

@ -249,6 +249,12 @@ struct b43_rxhdr_fw4 {
} __packed; } __packed;
} __packed; } __packed;
union { union {
/* HT-PHY */
struct {
PAD_BYTES(1);
__s8 phy_ht_power0;
} __packed;
/* RSSI for N-PHYs */ /* RSSI for N-PHYs */
struct { struct {
__s8 power2; __s8 power2;
@ -257,7 +263,15 @@ struct b43_rxhdr_fw4 {
__le16 phy_status2; /* PHY RX Status 2 */ __le16 phy_status2; /* PHY RX Status 2 */
} __packed; } __packed;
__le16 phy_status3; /* PHY RX Status 3 */ union {
/* HT-PHY */
struct {
__s8 phy_ht_power1;
__s8 phy_ht_power2;
} __packed;
__le16 phy_status3; /* PHY RX Status 3 */
} __packed;
union { union {
/* Tested with 598.314, 644.1001 and 666.2 */ /* Tested with 598.314, 644.1001 and 666.2 */
struct { struct {

View File

@ -26,7 +26,8 @@ DHDOFILES = \
dhd_sdio.o \ dhd_sdio.o \
dhd_linux.o \ dhd_linux.o \
bcmsdh.o \ bcmsdh.o \
bcmsdh_sdmmc.o bcmsdh_sdmmc.o \
sdio_chip.o
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += $(DHDOFILES) brcmfmac-objs += $(DHDOFILES)

View File

@ -18,13 +18,6 @@
#define _bcmchip_h_ #define _bcmchip_h_
/* bcm4329 */ /* bcm4329 */
/* SDIO device core, ID 0x829 */
#define BCM4329_CORE_BUS_BASE 0x18011000
/* internal memory core, ID 0x80e */
#define BCM4329_CORE_SOCRAM_BASE 0x18003000
/* ARM Cortex M3 core, ID 0x82a */
#define BCM4329_CORE_ARM_BASE 0x18002000
#define BCM4329_RAMSIZE 0x48000
/* firmware name */ /* firmware name */
#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin" #define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin"
#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt" #define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt"

View File

@ -87,7 +87,7 @@
#define TOE_TX_CSUM_OL 0x00000001 #define TOE_TX_CSUM_OL 0x00000001
#define TOE_RX_CSUM_OL 0x00000002 #define TOE_RX_CSUM_OL 0x00000002
#define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */ #define BRCMF_BSS_INFO_VERSION 108 /* curr ver of brcmf_bss_info_le struct */
/* size of brcmf_scan_params not including variable length array */ /* size of brcmf_scan_params not including variable length array */
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
@ -122,8 +122,6 @@
/* For supporting multiple interfaces */ /* For supporting multiple interfaces */
#define BRCMF_MAX_IFS 16 #define BRCMF_MAX_IFS 16
#define BRCMF_DEL_IF -0xe
#define BRCMF_BAD_IF -0xf
#define DOT11_BSSTYPE_ANY 2 #define DOT11_BSSTYPE_ANY 2
#define DOT11_MAX_DEFAULT_KEYS 4 #define DOT11_MAX_DEFAULT_KEYS 4
@ -365,7 +363,7 @@ struct brcmf_pkt_filter_enable_le {
* Applications MUST CHECK ie_offset field and length field to access IEs and * Applications MUST CHECK ie_offset field and length field to access IEs and
* next bss_info structure in a vector (in struct brcmf_scan_results) * next bss_info structure in a vector (in struct brcmf_scan_results)
*/ */
struct brcmf_bss_info { struct brcmf_bss_info_le {
__le32 version; /* version field */ __le32 version; /* version field */
__le32 length; /* byte length of data in this record, __le32 length; /* byte length of data in this record,
* starting at version and including IEs * starting at version and including IEs
@ -466,14 +464,13 @@ struct brcmf_scan_results {
u32 buflen; u32 buflen;
u32 version; u32 version;
u32 count; u32 count;
struct brcmf_bss_info bss_info[1]; struct brcmf_bss_info_le bss_info_le[];
}; };
struct brcmf_scan_results_le { struct brcmf_scan_results_le {
__le32 buflen; __le32 buflen;
__le32 version; __le32 version;
__le32 count; __le32 count;
struct brcmf_bss_info bss_info[1];
}; };
/* used for association with a specific BSSID and chanspec list */ /* used for association with a specific BSSID and chanspec list */
@ -493,10 +490,6 @@ struct brcmf_join_params {
struct brcmf_assoc_params_le params_le; struct brcmf_assoc_params_le params_le;
}; };
/* size of brcmf_scan_results not including variable length array */
#define BRCMF_SCAN_RESULTS_FIXED_SIZE \
(sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info))
/* incremental scan results struct */ /* incremental scan results struct */
struct brcmf_iscan_results { struct brcmf_iscan_results {
union { union {
@ -511,7 +504,7 @@ struct brcmf_iscan_results {
/* size of brcmf_iscan_results not including variable length array */ /* size of brcmf_iscan_results not including variable length array */
#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \ #define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
(BRCMF_SCAN_RESULTS_FIXED_SIZE + \ (sizeof(struct brcmf_scan_results) + \
offsetof(struct brcmf_iscan_results, results)) offsetof(struct brcmf_iscan_results, results))
struct brcmf_wsec_key { struct brcmf_wsec_key {
@ -734,8 +727,7 @@ extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
extern void brcmf_c_init(void); extern void brcmf_c_init(void);
extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx,
struct net_device *ndev, char *name, u8 *mac_addr, char *name, u8 *mac_addr);
u32 flags, u8 bssidx);
extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx); extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
/* Send packet to dongle via data channel */ /* Send packet to dongle via data channel */

View File

@ -488,10 +488,9 @@ brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) { if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
if (ifevent->action == BRCMF_E_IF_ADD) if (ifevent->action == BRCMF_E_IF_ADD)
brcmf_add_if(drvr_priv, ifevent->ifidx, NULL, brcmf_add_if(drvr_priv, ifevent->ifidx,
event->ifname, event->ifname,
pvt_data->eth.h_dest, pvt_data->eth.h_dest);
ifevent->flags, ifevent->bssidx);
else else
brcmf_del_if(drvr_priv, ifevent->ifidx); brcmf_del_if(drvr_priv, ifevent->ifidx);
} else { } else {

View File

@ -58,7 +58,6 @@ struct brcmf_if {
struct net_device *ndev; struct net_device *ndev;
struct net_device_stats stats; struct net_device_stats stats;
int idx; /* iface idx in dongle */ int idx; /* iface idx in dongle */
int state; /* interface state */
u8 mac_addr[ETH_ALEN]; /* assigned MAC address */ u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
}; };
@ -80,20 +79,6 @@ struct brcmf_info {
/* Error bits */ /* Error bits */
module_param(brcmf_msg_level, int, 0); module_param(brcmf_msg_level, int, 0);
static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev)
{
int i = 0;
while (i < BRCMF_MAX_IFS) {
if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev)
return i;
i++;
}
return BRCMF_BAD_IF;
}
int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name) int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
{ {
int i = BRCMF_MAX_IFS; int i = BRCMF_MAX_IFS;
@ -285,14 +270,9 @@ _brcmf_set_mac_address(struct work_struct *work)
static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
struct sockaddr *sa = (struct sockaddr *)addr; struct sockaddr *sa = (struct sockaddr *)addr;
int ifidx;
ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return -1;
memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN); memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
schedule_work(&drvr_priv->setmacaddr_work); schedule_work(&drvr_priv->setmacaddr_work);
@ -301,13 +281,8 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
static void brcmf_netdev_set_multicast_list(struct net_device *ndev) static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
int ifidx;
ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return;
schedule_work(&drvr_priv->multicast_work); schedule_work(&drvr_priv->multicast_work);
} }
@ -341,9 +316,8 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ {
int ret; int ret;
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
int ifidx;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
@ -355,9 +329,8 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
return -ENODEV; return -ENODEV;
} }
ifidx = brcmf_net2idx(drvr_priv, ndev); if (!drvr_priv->iflist[ifp->idx]) {
if (ifidx == BRCMF_BAD_IF) { brcmf_dbg(ERROR, "bad ifidx %d\n", ifp->idx);
brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx);
netif_stop_queue(ndev); netif_stop_queue(ndev);
return -ENODEV; return -ENODEV;
} }
@ -367,20 +340,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
struct sk_buff *skb2; struct sk_buff *skb2;
brcmf_dbg(INFO, "%s: insufficient headroom\n", brcmf_dbg(INFO, "%s: insufficient headroom\n",
brcmf_ifname(&drvr_priv->pub, ifidx)); brcmf_ifname(&drvr_priv->pub, ifp->idx));
drvr_priv->pub.tx_realloc++; drvr_priv->pub.tx_realloc++;
skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen); skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
dev_kfree_skb(skb); dev_kfree_skb(skb);
skb = skb2; skb = skb2;
if (skb == NULL) { if (skb == NULL) {
brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n", brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
brcmf_ifname(&drvr_priv->pub, ifidx)); brcmf_ifname(&drvr_priv->pub, ifp->idx));
ret = -ENOMEM; ret = -ENOMEM;
goto done; goto done;
} }
} }
ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb); ret = brcmf_sendpkt(&drvr_priv->pub, ifp->idx, skb);
done: done:
if (ret) if (ret)
@ -482,12 +455,10 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
skb_mac_header(skb), skb_mac_header(skb),
&event, &data); &event, &data);
if (drvr_priv->iflist[ifidx] && if (drvr_priv->iflist[ifidx]) {
!drvr_priv->iflist[ifidx]->state)
ifp = drvr_priv->iflist[ifidx]; ifp = drvr_priv->iflist[ifidx];
if (ifp->ndev)
ifp->ndev->last_rx = jiffies; ifp->ndev->last_rx = jiffies;
}
drvr->dstats.rx_bytes += skb->len; drvr->dstats.rx_bytes += skb->len;
drvr->rx_packets++; /* Local count */ drvr->rx_packets++; /* Local count */
@ -524,19 +495,11 @@ void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
struct brcmf_if *ifp;
int ifidx;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
ifidx = brcmf_net2idx(drvr_priv, ndev);
if (ifidx == BRCMF_BAD_IF)
return NULL;
ifp = drvr_priv->iflist[ifidx];
if (drvr_priv->pub.up) if (drvr_priv->pub.up)
/* Use the protocol to get dongle stats */ /* Use the protocol to get dongle stats */
brcmf_proto_dstats(&drvr_priv->pub); brcmf_proto_dstats(&drvr_priv->pub);
@ -637,8 +600,8 @@ static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info) struct ethtool_drvinfo *info)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
sprintf(info->driver, KBUILD_MODNAME); sprintf(info->driver, KBUILD_MODNAME);
sprintf(info->version, "%lu", drvr_priv->pub.drv_version); sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
@ -765,14 +728,12 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
int cmd) int cmd)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
int ifidx;
ifidx = brcmf_net2idx(drvr_priv, ndev); brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
if (ifidx == BRCMF_BAD_IF) if (!drvr_priv->iflist[ifp->idx])
return -1; return -1;
if (cmd == SIOCETHTOOL) if (cmd == SIOCETHTOOL)
@ -788,17 +749,14 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
s32 err = 0; s32 err = 0;
int buflen = 0; int buflen = 0;
bool is_set_key_cmd; bool is_set_key_cmd;
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
int ifidx;
memset(&dcmd, 0, sizeof(dcmd)); memset(&dcmd, 0, sizeof(dcmd));
dcmd.cmd = cmd; dcmd.cmd = cmd;
dcmd.buf = arg; dcmd.buf = arg;
dcmd.len = len; dcmd.len = len;
ifidx = brcmf_net2idx(drvr_priv, ndev);
if (dcmd.buf != NULL) if (dcmd.buf != NULL)
buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN); buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
@ -826,7 +784,7 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
if (is_set_key_cmd) if (is_set_key_cmd)
brcmf_netdev_wait_pend8021x(ndev); brcmf_netdev_wait_pend8021x(ndev);
err = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, buflen); err = brcmf_proto_dcmd(&drvr_priv->pub, ifp->idx, &dcmd, buflen);
done: done:
if (err > 0) if (err > 0)
@ -837,7 +795,8 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
static int brcmf_netdev_stop(struct net_device *ndev) static int brcmf_netdev_stop(struct net_device *ndev)
{ {
struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = &ifp->info->pub;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
brcmf_cfg80211_down(drvr->config); brcmf_cfg80211_down(drvr->config);
@ -853,16 +812,14 @@ static int brcmf_netdev_stop(struct net_device *ndev)
static int brcmf_netdev_open(struct net_device *ndev) static int brcmf_netdev_open(struct net_device *ndev)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **) struct brcmf_if *ifp = netdev_priv(ndev);
netdev_priv(ndev); struct brcmf_info *drvr_priv = ifp->info;
u32 toe_ol; u32 toe_ol;
int ifidx = brcmf_net2idx(drvr_priv, ndev);
s32 ret = 0; s32 ret = 0;
brcmf_dbg(TRACE, "ifidx %d\n", ifidx); brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
if (ifidx == 0) { /* do it only for primary eth0 */
if (ifp->idx == 0) { /* do it only for primary eth0 */
/* try to bring up bus */ /* try to bring up bus */
ret = brcmf_bus_start(&drvr_priv->pub); ret = brcmf_bus_start(&drvr_priv->pub);
if (ret != 0) { if (ret != 0) {
@ -874,12 +831,12 @@ static int brcmf_netdev_open(struct net_device *ndev)
memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN); memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
/* Get current TOE mode from dongle */ /* Get current TOE mode from dongle */
if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0 if (brcmf_toe_get(drvr_priv, ifp->idx, &toe_ol) >= 0
&& (toe_ol & TOE_TX_CSUM_OL) != 0) && (toe_ol & TOE_TX_CSUM_OL) != 0)
drvr_priv->iflist[ifidx]->ndev->features |= drvr_priv->iflist[ifp->idx]->ndev->features |=
NETIF_F_IP_CSUM; NETIF_F_IP_CSUM;
else else
drvr_priv->iflist[ifidx]->ndev->features &= drvr_priv->iflist[ifp->idx]->ndev->features &=
~NETIF_F_IP_CSUM; ~NETIF_F_IP_CSUM;
} }
/* Allow transmit calls */ /* Allow transmit calls */
@ -893,75 +850,62 @@ static int brcmf_netdev_open(struct net_device *ndev)
return ret; return ret;
} }
static const struct net_device_ops brcmf_netdev_ops_pri = {
.ndo_open = brcmf_netdev_open,
.ndo_stop = brcmf_netdev_stop,
.ndo_get_stats = brcmf_netdev_get_stats,
.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
.ndo_start_xmit = brcmf_netdev_start_xmit,
.ndo_set_mac_address = brcmf_netdev_set_mac_address,
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
};
int int
brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev, brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
char *name, u8 *mac_addr, u32 flags, u8 bssidx)
{ {
struct brcmf_if *ifp; struct brcmf_if *ifp;
int ret = 0, err = 0; struct net_device *ndev;
brcmf_dbg(TRACE, "idx %d, handle->%p\n", ifidx, ndev); brcmf_dbg(TRACE, "idx %d\n", ifidx);
ifp = drvr_priv->iflist[ifidx]; ifp = drvr_priv->iflist[ifidx];
if (!ifp) { /*
ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC); * Delete the existing interface before overwriting it
if (!ifp) * in case we missed the BRCMF_E_IF_DEL event.
return -ENOMEM; */
if (ifp) {
brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
ifp->ndev->name);
netif_stop_queue(ifp->ndev);
unregister_netdev(ifp->ndev);
free_netdev(ifp->ndev);
drvr_priv->iflist[ifidx] = NULL;
} }
memset(ifp, 0, sizeof(struct brcmf_if)); /* Allocate netdev, including space for private structure */
ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
if (!ndev) {
brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
return -ENOMEM;
}
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
ifp->info = drvr_priv; ifp->info = drvr_priv;
drvr_priv->iflist[ifidx] = ifp; drvr_priv->iflist[ifidx] = ifp;
ifp->idx = ifidx;
if (mac_addr != NULL) if (mac_addr != NULL)
memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
if (ndev == NULL) { if (brcmf_net_attach(&drvr_priv->pub, ifp->idx)) {
ifp->state = BRCMF_E_IF_ADD; brcmf_dbg(ERROR, "brcmf_net_attach failed");
ifp->idx = ifidx; free_netdev(ifp->ndev);
/* drvr_priv->iflist[ifidx] = NULL;
* Delete the existing interface before overwriting it return -EOPNOTSUPP;
* in case we missed the BRCMF_E_IF_DEL event. }
*/
if (ifp->ndev != NULL) {
brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
ifp->ndev->name);
netif_stop_queue(ifp->ndev);
unregister_netdev(ifp->ndev);
free_netdev(ifp->ndev);
}
/* Allocate netdev, including space for private structure */ brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", current->pid, ifp->ndev->name);
ether_setup);
if (!ifp->ndev) {
brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
ret = -ENOMEM;
}
if (ret == 0) {
memcpy(netdev_priv(ifp->ndev), &drvr_priv,
sizeof(drvr_priv));
err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
if (err != 0) {
brcmf_dbg(ERROR, "brcmf_net_attach failed, err %d\n",
err);
ret = -EOPNOTSUPP;
} else {
brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
current->pid, ifp->ndev->name);
ifp->state = 0;
}
}
if (ret < 0) {
if (ifp->ndev)
free_netdev(ifp->ndev);
drvr_priv->iflist[ifp->idx] = NULL;
kfree(ifp);
}
} else
ifp->ndev = ndev;
return 0; return 0;
} }
@ -977,47 +921,36 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
brcmf_dbg(ERROR, "Null interface\n"); brcmf_dbg(ERROR, "Null interface\n");
return; return;
} }
if (ifp->ndev) {
if (ifidx == 0) {
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
rtnl_lock();
brcmf_netdev_stop(ifp->ndev);
rtnl_unlock();
}
} else {
netif_stop_queue(ifp->ndev);
}
ifp->state = BRCMF_E_IF_DEL;
ifp->idx = ifidx;
if (ifp->ndev != NULL) {
netif_stop_queue(ifp->ndev);
unregister_netdev(ifp->ndev); unregister_netdev(ifp->ndev);
free_netdev(ifp->ndev);
drvr_priv->iflist[ifidx] = NULL; drvr_priv->iflist[ifidx] = NULL;
kfree(ifp); if (ifidx == 0)
brcmf_cfg80211_detach(drvr_priv->pub.config);
free_netdev(ifp->ndev);
} }
} }
struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
{ {
struct brcmf_info *drvr_priv = NULL; struct brcmf_info *drvr_priv = NULL;
struct net_device *ndev;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
/* Allocate netdev, including space for private structure */
ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup);
if (!ndev) {
brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
goto fail;
}
/* Allocate primary brcmf_info */ /* Allocate primary brcmf_info */
drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC); drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
if (!drvr_priv) if (!drvr_priv)
goto fail; goto fail;
/*
* Save the brcmf_info into the priv
*/
memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
if (brcmf_add_if(drvr_priv, 0, ndev, ndev->name, NULL, 0, 0) ==
BRCMF_BAD_IF)
goto fail;
ndev->netdev_ops = NULL;
mutex_init(&drvr_priv->proto_block); mutex_init(&drvr_priv->proto_block);
/* Link to info module */ /* Link to info module */
@ -1033,29 +966,12 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
goto fail; goto fail;
} }
/* Attach and link in the cfg80211 */
drvr_priv->pub.config =
brcmf_cfg80211_attach(ndev,
brcmf_bus_get_device(bus),
&drvr_priv->pub);
if (drvr_priv->pub.config == NULL) {
brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
goto fail;
}
INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address); INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address);
INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list); INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list);
/*
* Save the brcmf_info into the priv
*/
memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
return &drvr_priv->pub; return &drvr_priv->pub;
fail: fail:
if (ndev)
free_netdev(ndev);
if (drvr_priv) if (drvr_priv)
brcmf_detach(&drvr_priv->pub); brcmf_detach(&drvr_priv->pub);
@ -1123,16 +1039,6 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
return 0; return 0;
} }
static struct net_device_ops brcmf_netdev_ops_pri = {
.ndo_open = brcmf_netdev_open,
.ndo_stop = brcmf_netdev_stop,
.ndo_get_stats = brcmf_netdev_get_stats,
.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
.ndo_start_xmit = brcmf_netdev_start_xmit,
.ndo_set_mac_address = brcmf_netdev_set_mac_address,
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
};
int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx) int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
{ {
struct brcmf_info *drvr_priv = drvr->info; struct brcmf_info *drvr_priv = drvr->info;
@ -1169,6 +1075,18 @@ int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
/* attach to cfg80211 for primary interface */
if (!ifidx) {
drvr->config =
brcmf_cfg80211_attach(ndev,
brcmf_bus_get_device(drvr->bus),
drvr);
if (drvr->config == NULL) {
brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
goto fail;
}
}
if (register_netdev(ndev) != 0) { if (register_netdev(ndev) != 0) {
brcmf_dbg(ERROR, "couldn't register the net device\n"); brcmf_dbg(ERROR, "couldn't register the net device\n");
goto fail; goto fail;
@ -1210,21 +1128,13 @@ void brcmf_detach(struct brcmf_pub *drvr)
if (drvr) { if (drvr) {
drvr_priv = drvr->info; drvr_priv = drvr->info;
if (drvr_priv) { if (drvr_priv) {
struct brcmf_if *ifp;
int i; int i;
for (i = 1; i < BRCMF_MAX_IFS; i++) /* make sure primary interface removed last */
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
if (drvr_priv->iflist[i]) if (drvr_priv->iflist[i])
brcmf_del_if(drvr_priv, i); brcmf_del_if(drvr_priv, i);
ifp = drvr_priv->iflist[0];
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
rtnl_lock();
brcmf_netdev_stop(ifp->ndev);
rtnl_unlock();
unregister_netdev(ifp->ndev);
}
cancel_work_sync(&drvr_priv->setmacaddr_work); cancel_work_sync(&drvr_priv->setmacaddr_work);
cancel_work_sync(&drvr_priv->multicast_work); cancel_work_sync(&drvr_priv->multicast_work);
@ -1233,10 +1143,6 @@ void brcmf_detach(struct brcmf_pub *drvr)
if (drvr->prot) if (drvr->prot)
brcmf_proto_detach(drvr); brcmf_proto_detach(drvr);
brcmf_cfg80211_detach(drvr->config);
free_netdev(ifp->ndev);
kfree(ifp);
kfree(drvr_priv); kfree(drvr_priv);
} }
} }
@ -1302,7 +1208,8 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
int brcmf_netdev_wait_pend8021x(struct net_device *ndev) int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
{ {
struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_info *drvr_priv = ifp->info;
int timeout = 10 * HZ / 1000; int timeout = 10 * HZ / 1000;
int ntimes = MAX_WAIT_FOR_8021X_TX; int ntimes = MAX_WAIT_FOR_8021X_TX;
int pend = brcmf_get_pend_8021x_cnt(drvr_priv); int pend = brcmf_get_pend_8021x_cnt(drvr_priv);

View File

@ -28,6 +28,7 @@
#include <linux/semaphore.h> #include <linux/semaphore.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/bcma/bcma.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <defs.h> #include <defs.h>
#include <brcmu_wifi.h> #include <brcmu_wifi.h>
@ -35,6 +36,7 @@
#include <brcm_hw_ids.h> #include <brcm_hw_ids.h>
#include <soc.h> #include <soc.h>
#include "sdio_host.h" #include "sdio_host.h"
#include "sdio_chip.h"
#define DCMD_RESP_TIMEOUT 2000 /* In milli second */ #define DCMD_RESP_TIMEOUT 2000 /* In milli second */
@ -134,33 +136,6 @@ struct rte_console {
/* Force no backplane reset */ /* Force no backplane reset */
#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 #define SBSDIO_DEVCTL_RST_NOBPRESET 0x20
/* SBSDIO_FUNC1_CHIPCLKCSR */
/* Force ALP request to backplane */
#define SBSDIO_FORCE_ALP 0x01
/* Force HT request to backplane */
#define SBSDIO_FORCE_HT 0x02
/* Force ILP request to backplane */
#define SBSDIO_FORCE_ILP 0x04
/* Make ALP ready (power up xtal) */
#define SBSDIO_ALP_AVAIL_REQ 0x08
/* Make HT ready (power up PLL) */
#define SBSDIO_HT_AVAIL_REQ 0x10
/* Squelch clock requests from HW */
#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20
/* Status: ALP is ready */
#define SBSDIO_ALP_AVAIL 0x40
/* Status: HT is ready */
#define SBSDIO_HT_AVAIL 0x80
#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
#define SBSDIO_CLKAV(regval, alponly) \
(SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
/* direct(mapped) cis space */ /* direct(mapped) cis space */
/* MAPPED common CIS address */ /* MAPPED common CIS address */
@ -335,50 +310,6 @@ struct rte_console {
/* Flags for SDH calls */ /* Flags for SDH calls */
#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
/* sbimstate */
#define SBIM_IBE 0x20000 /* inbanderror */
#define SBIM_TO 0x40000 /* timeout */
#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */
#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */
/* sbtmstatelow */
/* reset */
#define SBTML_RESET 0x0001
/* reject field */
#define SBTML_REJ_MASK 0x0006
/* reject */
#define SBTML_REJ 0x0002
/* temporary reject, for error recovery */
#define SBTML_TMPREJ 0x0004
/* Shift to locate the SI control flags in sbtml */
#define SBTML_SICF_SHIFT 16
/* sbtmstatehigh */
#define SBTMH_SERR 0x0001 /* serror */
#define SBTMH_INT 0x0002 /* interrupt */
#define SBTMH_BUSY 0x0004 /* busy */
#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */
/* Shift to locate the SI status flags in sbtmh */
#define SBTMH_SISF_SHIFT 16
/* sbidlow */
#define SBIDL_INIT 0x80 /* initiator */
/* sbidhigh */
#define SBIDH_RC_MASK 0x000f /* revision code */
#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */
#define SBIDH_RCE_SHIFT 8
#define SBCOREREV(sbidh) \
((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | \
((sbidh) & SBIDH_RC_MASK))
#define SBIDH_CC_MASK 0x8ff0 /* core code */
#define SBIDH_CC_SHIFT 4
#define SBIDH_VC_MASK 0xffff0000 /* vendor code */
#define SBIDH_VC_SHIFT 16
/* /*
* Conversion of 802.1D priority to precedence level * Conversion of 802.1D priority to precedence level
*/ */
@ -388,17 +319,6 @@ static uint prio2prec(u32 prio)
(prio^2) : prio; (prio^2) : prio;
} }
/*
* Core reg address translation.
* Both macro's returns a 32 bits byte address on the backplane bus.
*/
#define CORE_CC_REG(base, field) \
(base + offsetof(struct chipcregs, field))
#define CORE_BUS_REG(base, field) \
(base + offsetof(struct sdpcmd_regs, field))
#define CORE_SB(base, field) \
(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
/* core registers */ /* core registers */
struct sdpcmd_regs { struct sdpcmd_regs {
u32 corecontrol; /* 0x00, rev8 */ u32 corecontrol; /* 0x00, rev8 */
@ -524,21 +444,6 @@ struct sdpcm_shared_le {
/* misc chip info needed by some of the routines */ /* misc chip info needed by some of the routines */
struct chip_info {
u32 chip;
u32 chiprev;
u32 cccorebase;
u32 ccrev;
u32 cccaps;
u32 buscorebase; /* 32 bits backplane bus address */
u32 buscorerev;
u32 buscoretype;
u32 ramcorebase;
u32 armcorebase;
u32 pmurev;
u32 ramsize;
};
/* Private data for SDIO bus interaction */ /* Private data for SDIO bus interaction */
struct brcmf_bus { struct brcmf_bus {
struct brcmf_pub *drvr; struct brcmf_pub *drvr;
@ -574,7 +479,7 @@ struct brcmf_bus {
uint txminmax; uint txminmax;
struct sk_buff *glomd; /* Packet containing glomming descriptor */ struct sk_buff *glomd; /* Packet containing glomming descriptor */
struct sk_buff *glom; /* Packet chain for glommed superframe */ struct sk_buff_head glom; /* Packet list for glommed superframe */
uint glomerr; /* Glom packet read errors */ uint glomerr; /* Glom packet read errors */
u8 *rxbuf; /* Buffer for receiving control packets */ u8 *rxbuf; /* Buffer for receiving control packets */
@ -663,46 +568,6 @@ struct brcmf_bus {
u32 fw_ptr; u32 fw_ptr;
}; };
struct sbconfig {
u32 PAD[2];
u32 sbipsflag; /* initiator port ocp slave flag */
u32 PAD[3];
u32 sbtpsflag; /* target port ocp slave flag */
u32 PAD[11];
u32 sbtmerrloga; /* (sonics >= 2.3) */
u32 PAD;
u32 sbtmerrlog; /* (sonics >= 2.3) */
u32 PAD[3];
u32 sbadmatch3; /* address match3 */
u32 PAD;
u32 sbadmatch2; /* address match2 */
u32 PAD;
u32 sbadmatch1; /* address match1 */
u32 PAD[7];
u32 sbimstate; /* initiator agent state */
u32 sbintvec; /* interrupt mask */
u32 sbtmstatelow; /* target state */
u32 sbtmstatehigh; /* target state */
u32 sbbwa0; /* bandwidth allocation table0 */
u32 PAD;
u32 sbimconfiglow; /* initiator configuration */
u32 sbimconfighigh; /* initiator configuration */
u32 sbadmatch0; /* address match0 */
u32 PAD;
u32 sbtmconfiglow; /* target configuration */
u32 sbtmconfighigh; /* target configuration */
u32 sbbconfig; /* broadcast configuration */
u32 PAD;
u32 sbbstate; /* broadcast state */
u32 PAD[3];
u32 sbactcnfg; /* activate configuration */
u32 PAD[3];
u32 sbflagst; /* current sbflags */
u32 PAD[3];
u32 sbidlow; /* identification */
u32 sbidhigh; /* identification */
};
/* clkstate */ /* clkstate */
#define CLK_NONE 0 #define CLK_NONE 0
#define CLK_SDONLY 1 #define CLK_SDONLY 1
@ -750,10 +615,12 @@ static bool data_ok(struct brcmf_bus *bus)
static void static void
r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
{ {
u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
*retryvar = 0; *retryvar = 0;
do { do {
*regvar = brcmf_sdcard_reg_read(bus->sdiodev, *regvar = brcmf_sdcard_reg_read(bus->sdiodev,
bus->ci->buscorebase + reg_offset, sizeof(u32)); bus->ci->c_inf[idx].base + reg_offset,
sizeof(u32));
} while (brcmf_sdcard_regfail(bus->sdiodev) && } while (brcmf_sdcard_regfail(bus->sdiodev) &&
(++(*retryvar) <= retry_limit)); (++(*retryvar) <= retry_limit));
if (*retryvar) { if (*retryvar) {
@ -768,10 +635,11 @@ r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
static void static void
w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar) w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar)
{ {
u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
*retryvar = 0; *retryvar = 0;
do { do {
brcmf_sdcard_reg_write(bus->sdiodev, brcmf_sdcard_reg_write(bus->sdiodev,
bus->ci->buscorebase + reg_offset, bus->ci->c_inf[idx].base + reg_offset,
sizeof(u32), regval); sizeof(u32), regval);
} while (brcmf_sdcard_regfail(bus->sdiodev) && } while (brcmf_sdcard_regfail(bus->sdiodev) &&
(++(*retryvar) <= retry_limit)); (++(*retryvar) <= retry_limit));
@ -812,10 +680,6 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
clkreq = clkreq =
bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
if ((bus->ci->chip == BCM4329_CHIP_ID)
&& (bus->ci->chiprev == 0))
clkreq |= SBSDIO_FORCE_ALP;
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
if (err) { if (err) {
@ -823,14 +687,6 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
return -EBADE; return -EBADE;
} }
if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID)
&& (bus->ci->buscorerev == 9))) {
u32 dummy, retries;
r_sdreg32(bus, &dummy,
offsetof(struct sdpcmd_regs, clockctlstatus),
&retries);
}
/* Check current status */ /* Check current status */
clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, &err); SBSDIO_FUNC1_CHIPCLKCSR, &err);
@ -1034,11 +890,9 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
/* Isolate the bus */ /* Isolate the bus */
if (bus->ci->chip != BCM4329_CHIP_ID) { brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
SBSDIO_DEVICE_CTL, SBSDIO_DEVCTL_PADS_ISO, NULL);
SBSDIO_DEVCTL_PADS_ISO, NULL);
}
/* Change state */ /* Change state */
bus->sleeping = true; bus->sleeping = true;
@ -1049,13 +903,6 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep)
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
/* Force pad isolation off if possible
(in case power never toggled) */
if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
&& (bus->ci->buscorerev >= 10))
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_DEVICE_CTL, 0, NULL);
/* Make sure the controller has the bus up */ /* Make sure the controller has the bus up */
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
@ -1222,6 +1069,51 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
bus->drvr->busstate = BRCMF_BUS_DOWN; bus->drvr->busstate = BRCMF_BUS_DOWN;
} }
/* copy a buffer into a pkt buffer chain */
static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_bus *bus, uint len)
{
uint n, ret = 0;
struct sk_buff *p;
u8 *buf;
buf = bus->dataptr;
/* copy the data */
skb_queue_walk(&bus->glom, p) {
n = min_t(uint, p->len, len);
memcpy(p->data, buf, n);
buf += n;
len -= n;
ret += n;
if (!len)
break;
}
return ret;
}
/* return total length of buffer chain */
static uint brcmf_sdbrcm_glom_len(struct brcmf_bus *bus)
{
struct sk_buff *p;
uint total;
total = 0;
skb_queue_walk(&bus->glom, p)
total += p->len;
return total;
}
static void brcmf_sdbrcm_free_glom(struct brcmf_bus *bus)
{
struct sk_buff *cur, *next;
skb_queue_walk_safe(&bus->glom, cur, next) {
skb_unlink(cur, &bus->glom);
brcmu_pkt_buf_free_skb(cur);
}
}
static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq) static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
{ {
u16 dlen, totlen; u16 dlen, totlen;
@ -1240,7 +1132,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
/* If packets, issue read(s) and send up packet chain */ /* If packets, issue read(s) and send up packet chain */
/* Return sequence numbers consumed? */ /* Return sequence numbers consumed? */
brcmf_dbg(TRACE, "start: glomd %p glom %p\n", bus->glomd, bus->glom); brcmf_dbg(TRACE, "start: glomd %p glom %p\n",
bus->glomd, skb_peek(&bus->glom));
/* If there's a descriptor, generate the packet chain */ /* If there's a descriptor, generate the packet chain */
if (bus->glomd) { if (bus->glomd) {
@ -1287,12 +1180,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
num, sublen); num, sublen);
break; break;
} }
if (!pfirst) { skb_queue_tail(&bus->glom, pnext);
pfirst = plast = pnext;
} else {
plast->next = pnext;
plast = pnext;
}
/* Adhere to start alignment requirements */ /* Adhere to start alignment requirements */
pkt_align(pnext, sublen, BRCMF_SDALIGN); pkt_align(pnext, sublen, BRCMF_SDALIGN);
@ -1308,12 +1196,9 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n",
bus->nextlen, totlen, rxseq); bus->nextlen, totlen, rxseq);
} }
bus->glom = pfirst;
pfirst = pnext = NULL; pfirst = pnext = NULL;
} else { } else {
if (pfirst) brcmf_sdbrcm_free_glom(bus);
brcmu_pkt_buf_free_skb(pfirst);
bus->glom = NULL;
num = 0; num = 0;
} }
@ -1325,18 +1210,18 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
/* Ok -- either we just generated a packet chain, /* Ok -- either we just generated a packet chain,
or had one from before */ or had one from before */
if (bus->glom) { if (!skb_queue_empty(&bus->glom)) {
if (BRCMF_GLOM_ON()) { if (BRCMF_GLOM_ON()) {
brcmf_dbg(GLOM, "try superframe read, packet chain:\n"); brcmf_dbg(GLOM, "try superframe read, packet chain:\n");
for (pnext = bus->glom; pnext; pnext = pnext->next) { skb_queue_walk(&bus->glom, pnext) {
brcmf_dbg(GLOM, " %p: %p len 0x%04x (%d)\n", brcmf_dbg(GLOM, " %p: %p len 0x%04x (%d)\n",
pnext, (u8 *) (pnext->data), pnext, (u8 *) (pnext->data),
pnext->len, pnext->len); pnext->len, pnext->len);
} }
} }
pfirst = bus->glom; pfirst = skb_peek(&bus->glom);
dlen = (u16) brcmu_pkttotlen(pfirst); dlen = (u16) brcmf_sdbrcm_glom_len(bus);
/* Do an SDIO read for the superframe. Configurable iovar to /* Do an SDIO read for the superframe. Configurable iovar to
* read directly into the chained packet, or allocate a large * read directly into the chained packet, or allocate a large
@ -1354,8 +1239,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
SDIO_FUNC_2, SDIO_FUNC_2,
F2SYNC, bus->dataptr, dlen, F2SYNC, bus->dataptr, dlen,
NULL); NULL);
sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen, sublen = (u16) brcmf_sdbrcm_glom_from_buf(bus, dlen);
bus->dataptr);
if (sublen != dlen) { if (sublen != dlen) {
brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n", brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n",
dlen, sublen); dlen, sublen);
@ -1380,9 +1264,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
} else { } else {
bus->glomerr = 0; bus->glomerr = 0;
brcmf_sdbrcm_rxfail(bus, true, false); brcmf_sdbrcm_rxfail(bus, true, false);
brcmu_pkt_buf_free_skb(bus->glom);
bus->rxglomfail++; bus->rxglomfail++;
bus->glom = NULL; brcmf_sdbrcm_free_glom(bus);
} }
return 0; return 0;
} }
@ -1503,9 +1386,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
} else { } else {
bus->glomerr = 0; bus->glomerr = 0;
brcmf_sdbrcm_rxfail(bus, true, false); brcmf_sdbrcm_rxfail(bus, true, false);
brcmu_pkt_buf_free_skb(bus->glom);
bus->rxglomfail++; bus->rxglomfail++;
bus->glom = NULL; brcmf_sdbrcm_free_glom(bus);
} }
bus->nextlen = 0; bus->nextlen = 0;
return 0; return 0;
@ -1513,7 +1395,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
/* Basic SD framing looks ok - process each packet (header) */ /* Basic SD framing looks ok - process each packet (header) */
save_pfirst = pfirst; save_pfirst = pfirst;
bus->glom = NULL;
plast = NULL; plast = NULL;
for (num = 0; pfirst; rxseq++, pfirst = pnext) { for (num = 0; pfirst; rxseq++, pfirst = pnext) {
@ -1850,10 +1731,10 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
rxseq++, rxleft--) { rxseq++, rxleft--) {
/* Handle glomming separately */ /* Handle glomming separately */
if (bus->glom || bus->glomd) { if (bus->glomd || !skb_queue_empty(&bus->glom)) {
u8 cnt; u8 cnt;
brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n",
bus->glomd, bus->glom); bus->glomd, skb_peek(&bus->glom));
cnt = brcmf_sdbrcm_rxglom(bus, rxseq); cnt = brcmf_sdbrcm_rxglom(bus, rxseq);
brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); brcmf_dbg(GLOM, "rxglom returned %d\n", cnt);
rxseq += cnt - 1; rxseq += cnt - 1;
@ -3210,135 +3091,11 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
return bcmerror; return bcmerror;
} }
static void
brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
{
u32 regdata;
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbtmstatelow), 4);
if (regdata & SBTML_RESET)
return;
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbtmstatelow), 4);
if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
/*
* set target reject and spin until busy is clear
* (preserve core-specific bits)
*/
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbtmstatelow), 4);
brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow),
4, regdata | SBTML_REJ);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbtmstatelow), 4);
udelay(1);
SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbtmstatehigh), 4) &
SBTMH_BUSY), 100000);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbtmstatehigh), 4);
if (regdata & SBTMH_BUSY)
brcmf_dbg(ERROR, "ARM core still busy\n");
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbidlow), 4);
if (regdata & SBIDL_INIT) {
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbimstate), 4) |
SBIM_RJ;
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(corebase, sbimstate), 4,
regdata);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbimstate), 4);
udelay(1);
SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbimstate), 4) &
SBIM_BY), 100000);
}
/* set reset and reject while enabling the clocks */
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(corebase, sbtmstatelow), 4,
(((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
SBTML_REJ | SBTML_RESET));
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbtmstatelow), 4);
udelay(10);
/* clear the initiator reject bit */
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbidlow), 4);
if (regdata & SBIDL_INIT) {
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbimstate), 4) &
~SBIM_RJ;
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(corebase, sbimstate), 4,
regdata);
}
}
/* leave reset and reject asserted */
brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
(SBTML_REJ | SBTML_RESET));
udelay(1);
}
static void
brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_dev *sdiodev, u32 corebase)
{
u32 regdata;
/*
* Must do the disable sequence first to work for
* arbitrary current core state.
*/
brcmf_sdbrcm_chip_disablecore(sdiodev, corebase);
/*
* Now do the initialization sequence.
* set reset while enabling the clock and
* forcing them on throughout the core
*/
brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
SBTML_RESET);
udelay(1);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbtmstatehigh), 4);
if (regdata & SBTMH_SERR)
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(corebase, sbtmstatehigh), 4, 0);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(corebase, sbimstate), 4);
if (regdata & (SBIM_IBE | SBIM_TO))
brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbimstate), 4,
regdata & ~(SBIM_IBE | SBIM_TO));
/* clear reset and allow it to propagate throughout the core */
brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
(SICF_FGC << SBTML_SICF_SHIFT) |
(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
udelay(1);
/* leave clock enabled */
brcmf_sdcard_reg_write(sdiodev, CORE_SB(corebase, sbtmstatelow), 4,
(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
udelay(1);
}
static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter) static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
{ {
uint retries; uint retries;
u32 regdata;
int bcmerror = 0; int bcmerror = 0;
struct chip_info *ci = bus->ci;
/* To enter download state, disable ARM and reset SOCRAM. /* To enter download state, disable ARM and reset SOCRAM.
* To exit download state, simply reset ARM (default is RAM boot). * To exit download state, simply reset ARM (default is RAM boot).
@ -3346,10 +3103,9 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
if (enter) { if (enter) {
bus->alp_only = true; bus->alp_only = true;
brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ci->coredisable(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
bus->ci->armcorebase);
brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase); ci->resetcore(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM);
/* Clear the top bit of memory */ /* Clear the top bit of memory */
if (bus->ramsize) { if (bus->ramsize) {
@ -3358,11 +3114,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
(u8 *)&zeros, 4); (u8 *)&zeros, 4);
} }
} else { } else {
regdata = brcmf_sdcard_reg_read(bus->sdiodev, if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
regdata &= (SBTML_RESET | SBTML_REJ_MASK |
(SICF_CLOCK_EN << SBTML_SICF_SHIFT));
if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n"); brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n");
bcmerror = -EBADE; bcmerror = -EBADE;
goto fail; goto fail;
@ -3377,7 +3129,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
w_sdreg32(bus, 0xFFFFFFFF, w_sdreg32(bus, 0xFFFFFFFF,
offsetof(struct sdpcmd_regs, intstatus), &retries); offsetof(struct sdpcmd_regs, intstatus), &retries);
brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->armcorebase); ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
/* Allow HT Clock now that the ARM is running. */ /* Allow HT Clock now that the ARM is running. */
bus->alp_only = false; bus->alp_only = false;
@ -3661,11 +3413,7 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
/* Clear any held glomming stuff */ /* Clear any held glomming stuff */
if (bus->glomd) if (bus->glomd)
brcmu_pkt_buf_free_skb(bus->glomd); brcmu_pkt_buf_free_skb(bus->glomd);
brcmf_sdbrcm_free_glom(bus);
if (bus->glom)
brcmu_pkt_buf_free_skb(bus->glom);
bus->glom = bus->glomd = NULL;
/* Clear rx control and wake any waiters */ /* Clear rx control and wake any waiters */
bus->rxlen = 0; bus->rxlen = 0;
@ -3950,269 +3698,6 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus)
return false; return false;
} }
/* SDIO Pad drive strength to select value mappings */
struct sdiod_drive_str {
u8 strength; /* Pad Drive Strength in mA */
u8 sel; /* Chip-specific select value */
};
/* SDIO Drive Strength to sel value table for PMU Rev 1 */
static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
{
4, 0x2}, {
2, 0x3}, {
1, 0x0}, {
0, 0x0}
};
/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
{
12, 0x7}, {
10, 0x6}, {
8, 0x5}, {
6, 0x4}, {
4, 0x2}, {
2, 0x1}, {
0, 0x0}
};
/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
{
32, 0x7}, {
26, 0x6}, {
22, 0x5}, {
16, 0x4}, {
12, 0x3}, {
8, 0x2}, {
4, 0x1}, {
0, 0x0}
};
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
static char *brcmf_chipname(uint chipid, char *buf, uint len)
{
const char *fmt;
fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
snprintf(buf, len, fmt, chipid);
return buf;
}
static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus,
u32 drivestrength) {
struct sdiod_drive_str *str_tab = NULL;
u32 str_mask = 0;
u32 str_shift = 0;
char chn[8];
if (!(bus->ci->cccaps & CC_CAP_PMU))
return;
switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) {
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
str_mask = 0x30000000;
str_shift = 28;
break;
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
str_mask = 0x00003800;
str_shift = 11;
break;
case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
str_mask = 0x00003800;
str_shift = 11;
break;
default:
brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
brcmf_chipname(bus->ci->chip, chn, 8),
bus->ci->chiprev, bus->ci->pmurev);
break;
}
if (str_tab != NULL) {
u32 drivestrength_sel = 0;
u32 cc_data_temp;
int i;
for (i = 0; str_tab[i].strength != 0; i++) {
if (drivestrength >= str_tab[i].strength) {
drivestrength_sel = str_tab[i].sel;
break;
}
}
brcmf_sdcard_reg_write(bus->sdiodev,
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
4, 1);
cc_data_temp = brcmf_sdcard_reg_read(bus->sdiodev,
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
cc_data_temp &= ~str_mask;
drivestrength_sel <<= str_shift;
cc_data_temp |= drivestrength_sel;
brcmf_sdcard_reg_write(bus->sdiodev,
CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
4, cc_data_temp);
brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
drivestrength, cc_data_temp);
}
}
static int
brcmf_sdbrcm_chip_recognition(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u32 regs)
{
u32 regdata;
/*
* Get CC core rev
* Chipid is assume to be at offset 0 from regs arg
* For different chiptypes or old sdio hosts w/o chipcommon,
* other ways of recognition should be added here.
*/
ci->cccorebase = regs;
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_CC_REG(ci->cccorebase, chipid), 4);
ci->chip = regdata & CID_ID_MASK;
ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
/* Address of cores for new chips should be added here */
switch (ci->chip) {
case BCM4329_CHIP_ID:
ci->buscorebase = BCM4329_CORE_BUS_BASE;
ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
ci->armcorebase = BCM4329_CORE_ARM_BASE;
ci->ramsize = BCM4329_RAMSIZE;
break;
default:
brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
return -ENODEV;
}
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->cccorebase, sbidhigh), 4);
ci->ccrev = SBCOREREV(regdata);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
ci->pmurev = regdata & PCAP_REV_MASK;
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->buscorebase, sbidhigh), 4);
ci->buscorerev = SBCOREREV(regdata);
ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
ci->ccrev, ci->pmurev, ci->buscorerev, ci->buscoretype);
/* get chipcommon capabilites */
ci->cccaps = brcmf_sdcard_reg_read(sdiodev,
CORE_CC_REG(ci->cccorebase, capabilities), 4);
return 0;
}
static int
brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs)
{
struct chip_info *ci;
int err;
u8 clkval, clkset;
brcmf_dbg(TRACE, "Enter\n");
/* alloc chip_info_t */
ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
if (NULL == ci)
return -ENOMEM;
/* bus/core/clk setup for register access */
/* Try forcing SDIO core to do ALPAvail request only */
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
if (err) {
brcmf_dbg(ERROR, "error writing for HT off\n");
goto fail;
}
/* If register supported, wait for ALPAvail and then force ALP */
/* This may take up to 15 milliseconds */
clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, NULL);
if ((clkval & ~SBSDIO_AVBITS) == clkset) {
SPINWAIT(((clkval =
brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR,
NULL)),
!SBSDIO_ALPAV(clkval)),
PMU_MAX_TRANSITION_DLY);
if (!SBSDIO_ALPAV(clkval)) {
brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
clkval);
err = -EBUSY;
goto fail;
}
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
SBSDIO_FORCE_ALP;
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR,
clkset, &err);
udelay(65);
} else {
brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
clkset, clkval);
err = -EACCES;
goto fail;
}
/* Also, disable the extra SDIO pull-ups */
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
err = brcmf_sdbrcm_chip_recognition(bus->sdiodev, ci, regs);
if (err)
goto fail;
/*
* Make sure any on-chip ARM is off (in case strapping is wrong),
* or downloaded code was already running.
*/
brcmf_sdbrcm_chip_disablecore(bus->sdiodev, ci->armcorebase);
brcmf_sdcard_reg_write(bus->sdiodev,
CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
brcmf_sdcard_reg_write(bus->sdiodev,
CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
/* Disable F2 to clear any intermediate frame state on the dongle */
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx,
SDIO_FUNC_ENABLE_1, NULL);
/* WAR: cmd52 backplane read so core HW will drop ALPReq */
clkval = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
0, NULL);
/* Done with backplane-dependent accesses, can drop clock... */
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
bus->ci = ci;
return 0;
fail:
bus->ci = NULL;
kfree(ci);
return err;
}
static bool static bool
brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
{ {
@ -4220,6 +3705,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
int err = 0; int err = 0;
int reg_addr; int reg_addr;
u32 reg_val; u32 reg_val;
u8 idx;
bus->alp_only = true; bus->alp_only = true;
@ -4234,7 +3720,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
#endif /* BCMDBG */ #endif /* BCMDBG */
/* /*
* Force PLL off until brcmf_sdbrcm_chip_attach() * Force PLL off until brcmf_sdio_chip_attach()
* programs PLL control regs * programs PLL control regs
*/ */
@ -4252,8 +3738,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
goto fail; goto fail;
} }
if (brcmf_sdbrcm_chip_attach(bus, regsva)) { if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci, regsva)) {
brcmf_dbg(ERROR, "brcmf_sdbrcm_chip_attach failed!\n"); brcmf_dbg(ERROR, "brcmf_sdio_chip_attach failed!\n");
goto fail; goto fail;
} }
@ -4262,11 +3748,10 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
goto fail; goto fail;
} }
brcmf_sdbrcm_sdiod_drive_strength_init(bus, SDIO_DRIVE_STRENGTH); brcmf_sdio_chip_drivestrengthinit(bus->sdiodev, bus->ci,
SDIO_DRIVE_STRENGTH);
/* Get info on the ARM and SOCRAM cores... */ /* Get info on the SOCRAM cores... */
brcmf_sdcard_reg_read(bus->sdiodev,
CORE_SB(bus->ci->armcorebase, sbidhigh), 4);
bus->ramsize = bus->ci->ramsize; bus->ramsize = bus->ci->ramsize;
if (!(bus->ramsize)) { if (!(bus->ramsize)) {
brcmf_dbg(ERROR, "failed to find SOCRAM memory!\n"); brcmf_dbg(ERROR, "failed to find SOCRAM memory!\n");
@ -4274,7 +3759,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
} }
/* Set core control so an SDIO reset does a backplane reset */ /* Set core control so an SDIO reset does a backplane reset */
reg_addr = bus->ci->buscorebase + idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
reg_addr = bus->ci->c_inf[idx].base +
offsetof(struct sdpcmd_regs, corecontrol); offsetof(struct sdpcmd_regs, corecontrol);
reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32)); reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32));
brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32), brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32),
@ -4364,15 +3850,6 @@ brcmf_sdbrcm_watchdog(unsigned long data)
} }
} }
static void
brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus)
{
brcmf_dbg(TRACE, "Enter\n");
kfree(bus->ci);
bus->ci = NULL;
}
static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus) static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
{ {
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
@ -4380,7 +3857,7 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
if (bus->ci) { if (bus->ci) {
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
brcmf_sdbrcm_chip_detach(bus); brcmf_sdio_chip_detach(&bus->ci);
if (bus->vars && bus->varsz) if (bus->vars && bus->varsz)
kfree(bus->vars); kfree(bus->vars);
bus->vars = NULL; bus->vars = NULL;
@ -4440,6 +3917,7 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
bus->sdiodev = sdiodev; bus->sdiodev = sdiodev;
sdiodev->bus = bus; sdiodev->bus = bus;
skb_queue_head_init(&bus->glom);
bus->txbound = BRCMF_TXBOUND; bus->txbound = BRCMF_TXBOUND;
bus->rxbound = BRCMF_RXBOUND; bus->rxbound = BRCMF_RXBOUND;
bus->txminmax = BRCMF_TXMINMAX; bus->txminmax = BRCMF_TXMINMAX;
@ -4521,9 +3999,10 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
goto fail; goto fail;
} }
} }
/* Ok, have the per-port tell the stack we're open for business */
if (brcmf_net_attach(bus->drvr, 0) != 0) { /* add interface and open for business */
brcmf_dbg(ERROR, "Net attach failed!!\n"); if (brcmf_add_if((struct brcmf_info *)bus->drvr, 0, "wlan%d", NULL)) {
brcmf_dbg(ERROR, "Add primary net device interface failed!!\n");
goto fail; goto fail;
} }
@ -4554,10 +4033,6 @@ struct device *brcmf_bus_get_device(struct brcmf_bus *bus)
void void
brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick) brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
{ {
/* don't start the wd until fw is loaded */
if (bus->drvr->busstate == BRCMF_BUS_DOWN)
return;
/* Totally stop the timer */ /* Totally stop the timer */
if (!wdtick && bus->wd_timer_valid == true) { if (!wdtick && bus->wd_timer_valid == true) {
del_timer_sync(&bus->timer); del_timer_sync(&bus->timer);
@ -4566,6 +4041,10 @@ brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
return; return;
} }
/* don't start the wd until fw is loaded */
if (bus->drvr->busstate == BRCMF_BUS_DOWN)
return;
if (wdtick) { if (wdtick) {
if (bus->save_ms != BRCMF_WD_POLL_MS) { if (bus->save_ms != BRCMF_WD_POLL_MS) {
if (bus->wd_timer_valid == true) if (bus->wd_timer_valid == true)

View File

@ -0,0 +1,622 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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.
*/
/* ***** SDIO interface chip backplane handle functions ***** */
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/mmc/card.h>
#include <linux/ssb/ssb_regs.h>
#include <linux/bcma/bcma.h>
#include <chipcommon.h>
#include <brcm_hw_ids.h>
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include <soc.h>
#include "dhd.h"
#include "dhd_dbg.h"
#include "sdio_host.h"
#include "sdio_chip.h"
/* chip core base & ramsize */
/* bcm4329 */
/* SDIO device core, ID 0x829 */
#define BCM4329_CORE_BUS_BASE 0x18011000
/* internal memory core, ID 0x80e */
#define BCM4329_CORE_SOCRAM_BASE 0x18003000
/* ARM Cortex M3 core, ID 0x82a */
#define BCM4329_CORE_ARM_BASE 0x18002000
#define BCM4329_RAMSIZE 0x48000
#define SBCOREREV(sbidh) \
((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
((sbidh) & SSB_IDHIGH_RCLO))
/* SOC Interconnect types (aka chip types) */
#define SOCI_SB 0
#define SOCI_AI 1
/* EROM CompIdentB */
#define CIB_REV_MASK 0xff000000
#define CIB_REV_SHIFT 24
#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
/* SDIO Pad drive strength to select value mappings */
struct sdiod_drive_str {
u8 strength; /* Pad Drive Strength in mA */
u8 sel; /* Chip-specific select value */
};
/* SDIO Drive Strength to sel value table for PMU Rev 1 */
static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
{
4, 0x2}, {
2, 0x3}, {
1, 0x0}, {
0, 0x0}
};
/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
{
12, 0x7}, {
10, 0x6}, {
8, 0x5}, {
6, 0x4}, {
4, 0x2}, {
2, 0x1}, {
0, 0x0}
};
/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
{
32, 0x7}, {
26, 0x6}, {
22, 0x5}, {
16, 0x4}, {
12, 0x3}, {
8, 0x2}, {
4, 0x1}, {
0, 0x0}
};
u8
brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
{
u8 idx;
for (idx = 0; idx < BRCMF_MAX_CORENUM; idx++)
if (coreid == ci->c_inf[idx].id)
return idx;
return BRCMF_MAX_CORENUM;
}
static u32
brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid)
{
u32 regdata;
u8 idx;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbidhigh), 4);
return SBCOREREV(regdata);
}
static u32
brcmf_sdio_ai_corerev(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid)
{
u8 idx;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
return (ci->c_inf[idx].cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
}
static bool
brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid)
{
u32 regdata;
u8 idx;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
return (SSB_TMSLOW_CLOCK == regdata);
}
static bool
brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid)
{
u32 regdata;
u8 idx;
bool ret;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
regdata = brcmf_sdcard_reg_read(sdiodev,
ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
regdata = brcmf_sdcard_reg_read(sdiodev,
ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
4);
ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
return ret;
}
static void
brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid)
{
u32 regdata;
u8 idx;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
if (regdata & SSB_TMSLOW_RESET)
return;
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
if ((regdata & SSB_TMSLOW_CLOCK) != 0) {
/*
* set target reject and spin until busy is clear
* (preserve core-specific bits)
*/
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
4, regdata | SSB_TMSLOW_REJECT);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
udelay(1);
SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4) &
SSB_TMSHIGH_BUSY), 100000);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4);
if (regdata & SSB_TMSHIGH_BUSY)
brcmf_dbg(ERROR, "core state still busy\n");
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbidlow), 4);
if (regdata & SSB_IDLOW_INITIATOR) {
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbimstate), 4) |
SSB_IMSTATE_REJECT;
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
regdata);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbimstate), 4);
udelay(1);
SPINWAIT((brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbimstate), 4) &
SSB_IMSTATE_BUSY), 100000);
}
/* set reset and reject while enabling the clocks */
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
(SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
udelay(10);
/* clear the initiator reject bit */
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbidlow), 4);
if (regdata & SSB_IDLOW_INITIATOR) {
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbimstate), 4) &
~SSB_IMSTATE_REJECT;
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
regdata);
}
}
/* leave reset and reject asserted */
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
(SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
udelay(1);
}
static void
brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid)
{
u8 idx;
u32 regdata;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
/* if core is already in reset, just return */
regdata = brcmf_sdcard_reg_read(sdiodev,
ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
4);
if ((regdata & BCMA_RESET_CTL_RESET) != 0)
return;
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
4, 0);
regdata = brcmf_sdcard_reg_read(sdiodev,
ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
udelay(10);
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
4, BCMA_RESET_CTL_RESET);
udelay(1);
}
static void
brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid)
{
u32 regdata;
u8 idx;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
/*
* Must do the disable sequence first to work for
* arbitrary current core state.
*/
brcmf_sdio_sb_coredisable(sdiodev, ci, coreid);
/*
* Now do the initialization sequence.
* set reset while enabling the clock and
* forcing them on throughout the core
*/
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
udelay(1);
/* clear any serror */
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4);
if (regdata & SSB_TMSHIGH_SERR)
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4, 0);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbimstate), 4);
if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO))
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbimstate), 4,
regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO));
/* clear reset and allow it to propagate throughout the core */
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4,
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
udelay(1);
/* leave clock enabled */
brcmf_sdcard_reg_write(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow),
4, SSB_TMSLOW_CLOCK);
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4);
udelay(1);
}
static void
brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid)
{
u8 idx;
u32 regdata;
idx = brcmf_sdio_chip_getinfidx(ci, coreid);
/* must disable first to work for arbitrary current core state */
brcmf_sdio_ai_coredisable(sdiodev, ci, coreid);
/* now do initialization sequence */
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
4, BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
regdata = brcmf_sdcard_reg_read(sdiodev,
ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL,
4, 0);
udelay(1);
brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL,
4, BCMA_IOCTL_CLK);
regdata = brcmf_sdcard_reg_read(sdiodev,
ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4);
udelay(1);
}
static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u32 regs)
{
u32 regdata;
/*
* Get CC core rev
* Chipid is assume to be at offset 0 from regs arg
* For different chiptypes or old sdio hosts w/o chipcommon,
* other ways of recognition should be added here.
*/
ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON;
ci->c_inf[0].base = regs;
regdata = brcmf_sdcard_reg_read(sdiodev,
CORE_CC_REG(ci->c_inf[0].base, chipid), 4);
ci->chip = regdata & CID_ID_MASK;
ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
brcmf_dbg(INFO, "chipid=0x%x chiprev=%d\n", ci->chip, ci->chiprev);
/* Address of cores for new chips should be added here */
switch (ci->chip) {
case BCM4329_CHIP_ID:
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
ci->c_inf[1].base = BCM4329_CORE_BUS_BASE;
ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
ci->c_inf[2].base = BCM4329_CORE_SOCRAM_BASE;
ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
ci->ramsize = BCM4329_RAMSIZE;
break;
default:
brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
return -ENODEV;
}
switch (ci->socitype) {
case SOCI_SB:
ci->iscoreup = brcmf_sdio_sb_iscoreup;
ci->corerev = brcmf_sdio_sb_corerev;
ci->coredisable = brcmf_sdio_sb_coredisable;
ci->resetcore = brcmf_sdio_sb_resetcore;
break;
case SOCI_AI:
ci->iscoreup = brcmf_sdio_ai_iscoreup;
ci->corerev = brcmf_sdio_ai_corerev;
ci->coredisable = brcmf_sdio_ai_coredisable;
ci->resetcore = brcmf_sdio_ai_resetcore;
break;
default:
brcmf_dbg(ERROR, "socitype %u not supported\n", ci->socitype);
return -ENODEV;
}
return 0;
}
static int
brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev)
{
int err = 0;
u8 clkval, clkset;
/* Try forcing SDIO core to do ALPAvail request only */
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
if (err) {
brcmf_dbg(ERROR, "error writing for HT off\n");
return err;
}
/* If register supported, wait for ALPAvail and then force ALP */
/* This may take up to 15 milliseconds */
clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, NULL);
if ((clkval & ~SBSDIO_AVBITS) != clkset) {
brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
clkset, clkval);
return -EACCES;
}
SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
!SBSDIO_ALPAV(clkval)),
PMU_MAX_TRANSITION_DLY);
if (!SBSDIO_ALPAV(clkval)) {
brcmf_dbg(ERROR, "timeout on ALPAV wait, clkval 0x%02x\n",
clkval);
return -EBUSY;
}
clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
udelay(65);
/* Also, disable the extra SDIO pull-ups */
brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1,
SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
return 0;
}
static void
brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci)
{
/* get chipcommon rev */
ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id);
/* get chipcommon capabilites */
ci->c_inf[0].caps =
brcmf_sdcard_reg_read(sdiodev,
CORE_CC_REG(ci->c_inf[0].base, capabilities), 4);
/* get pmu caps & rev */
if (ci->c_inf[0].caps & CC_CAP_PMU) {
ci->pmucaps = brcmf_sdcard_reg_read(sdiodev,
CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4);
ci->pmurev = ci->pmucaps & PCAP_REV_MASK;
}
ci->c_inf[1].rev = ci->corerev(sdiodev, ci, ci->c_inf[1].id);
brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
ci->c_inf[0].rev, ci->pmurev,
ci->c_inf[1].rev, ci->c_inf[1].id);
/*
* Make sure any on-chip ARM is off (in case strapping is wrong),
* or downloaded code was already running.
*/
ci->coredisable(sdiodev, ci, BCMA_CORE_ARM_CM3);
}
int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
struct chip_info **ci_ptr, u32 regs)
{
int ret;
struct chip_info *ci;
brcmf_dbg(TRACE, "Enter\n");
/* alloc chip_info_t */
ci = kzalloc(sizeof(struct chip_info), GFP_ATOMIC);
if (!ci)
return -ENOMEM;
ret = brcmf_sdio_chip_buscoreprep(sdiodev);
if (ret != 0)
goto err;
ret = brcmf_sdio_chip_recognition(sdiodev, ci, regs);
if (ret != 0)
goto err;
brcmf_sdio_chip_buscoresetup(sdiodev, ci);
brcmf_sdcard_reg_write(sdiodev,
CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0);
brcmf_sdcard_reg_write(sdiodev,
CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0);
*ci_ptr = ci;
return 0;
err:
kfree(ci);
return ret;
}
void
brcmf_sdio_chip_detach(struct chip_info **ci_ptr)
{
brcmf_dbg(TRACE, "Enter\n");
kfree(*ci_ptr);
*ci_ptr = NULL;
}
static char *brcmf_sdio_chip_name(uint chipid, char *buf, uint len)
{
const char *fmt;
fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
snprintf(buf, len, fmt, chipid);
return buf;
}
void
brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u32 drivestrength)
{
struct sdiod_drive_str *str_tab = NULL;
u32 str_mask = 0;
u32 str_shift = 0;
char chn[8];
if (!(ci->c_inf[0].caps & CC_CAP_PMU))
return;
switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
str_mask = 0x30000000;
str_shift = 28;
break;
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
str_mask = 0x00003800;
str_shift = 11;
break;
case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
str_mask = 0x00003800;
str_shift = 11;
break;
default:
brcmf_dbg(ERROR, "No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
brcmf_sdio_chip_name(ci->chip, chn, 8),
ci->chiprev, ci->pmurev);
break;
}
if (str_tab != NULL) {
u32 drivestrength_sel = 0;
u32 cc_data_temp;
int i;
for (i = 0; str_tab[i].strength != 0; i++) {
if (drivestrength >= str_tab[i].strength) {
drivestrength_sel = str_tab[i].sel;
break;
}
}
brcmf_sdcard_reg_write(sdiodev,
CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
4, 1);
cc_data_temp = brcmf_sdcard_reg_read(sdiodev,
CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4);
cc_data_temp &= ~str_mask;
drivestrength_sel <<= str_shift;
cc_data_temp |= drivestrength_sel;
brcmf_sdcard_reg_write(sdiodev,
CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr),
4, cc_data_temp);
brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n",
drivestrength, cc_data_temp);
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2011 Broadcom Corporation
*
* 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 _BRCMFMAC_SDIO_CHIP_H_
#define _BRCMFMAC_SDIO_CHIP_H_
/*
* Core reg address translation.
* Both macro's returns a 32 bits byte address on the backplane bus.
*/
#define CORE_CC_REG(base, field) \
(base + offsetof(struct chipcregs, field))
#define CORE_BUS_REG(base, field) \
(base + offsetof(struct sdpcmd_regs, field))
#define CORE_SB(base, field) \
(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
/* SDIO function 1 register CHIPCLKCSR */
/* Force ALP request to backplane */
#define SBSDIO_FORCE_ALP 0x01
/* Force HT request to backplane */
#define SBSDIO_FORCE_HT 0x02
/* Force ILP request to backplane */
#define SBSDIO_FORCE_ILP 0x04
/* Make ALP ready (power up xtal) */
#define SBSDIO_ALP_AVAIL_REQ 0x08
/* Make HT ready (power up PLL) */
#define SBSDIO_HT_AVAIL_REQ 0x10
/* Squelch clock requests from HW */
#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20
/* Status: ALP is ready */
#define SBSDIO_ALP_AVAIL 0x40
/* Status: HT is ready */
#define SBSDIO_HT_AVAIL 0x80
#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS)
#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
#define SBSDIO_CLKAV(regval, alponly) \
(SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
#define BRCMF_MAX_CORENUM 6
struct chip_core_info {
u16 id;
u16 rev;
u32 base;
u32 wrapbase;
u32 caps;
u32 cib;
};
struct chip_info {
u32 chip;
u32 chiprev;
u32 socitype;
/* core info */
/* always put chipcommon core at 0, bus core at 1 */
struct chip_core_info c_inf[BRCMF_MAX_CORENUM];
u32 pmurev;
u32 pmucaps;
u32 ramsize;
bool (*iscoreup)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
u16 coreid);
u32 (*corerev)(struct brcmf_sdio_dev *sdiodev, struct chip_info *ci,
u16 coreid);
void (*coredisable)(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid);
void (*resetcore)(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci, u16 coreid);
};
struct sbconfig {
u32 PAD[2];
u32 sbipsflag; /* initiator port ocp slave flag */
u32 PAD[3];
u32 sbtpsflag; /* target port ocp slave flag */
u32 PAD[11];
u32 sbtmerrloga; /* (sonics >= 2.3) */
u32 PAD;
u32 sbtmerrlog; /* (sonics >= 2.3) */
u32 PAD[3];
u32 sbadmatch3; /* address match3 */
u32 PAD;
u32 sbadmatch2; /* address match2 */
u32 PAD;
u32 sbadmatch1; /* address match1 */
u32 PAD[7];
u32 sbimstate; /* initiator agent state */
u32 sbintvec; /* interrupt mask */
u32 sbtmstatelow; /* target state */
u32 sbtmstatehigh; /* target state */
u32 sbbwa0; /* bandwidth allocation table0 */
u32 PAD;
u32 sbimconfiglow; /* initiator configuration */
u32 sbimconfighigh; /* initiator configuration */
u32 sbadmatch0; /* address match0 */
u32 PAD;
u32 sbtmconfiglow; /* target configuration */
u32 sbtmconfighigh; /* target configuration */
u32 sbbconfig; /* broadcast configuration */
u32 PAD;
u32 sbbstate; /* broadcast state */
u32 PAD[3];
u32 sbactcnfg; /* activate configuration */
u32 PAD[3];
u32 sbflagst; /* current sbflags */
u32 PAD[3];
u32 sbidlow; /* identification */
u32 sbidhigh; /* identification */
};
extern int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
struct chip_info **ci_ptr, u32 regs);
extern void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
extern void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
struct chip_info *ci,
u32 drivestrength);
extern u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid);
#endif /* _BRCMFMAC_SDIO_CHIP_H_ */

View File

@ -1997,7 +1997,7 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
} }
static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
struct brcmf_bss_info *bi) struct brcmf_bss_info_le *bi)
{ {
struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
struct ieee80211_channel *notify_channel; struct ieee80211_channel *notify_channel;
@ -2049,18 +2049,27 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
notify_timestamp, notify_capability, notify_interval, notify_ie, notify_timestamp, notify_capability, notify_interval, notify_ie,
notify_ielen, notify_signal, GFP_KERNEL); notify_ielen, notify_signal, GFP_KERNEL);
if (!bss) { if (!bss)
WL_ERR("cfg80211_inform_bss_frame error\n"); return -ENOMEM;
return -EINVAL;
} cfg80211_put_bss(bss);
return err; return err;
} }
static struct brcmf_bss_info_le *
next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
{
if (bss == NULL)
return list->bss_info_le;
return (struct brcmf_bss_info_le *)((unsigned long)bss +
le32_to_cpu(bss->length));
}
static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv) static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
{ {
struct brcmf_scan_results *bss_list; struct brcmf_scan_results *bss_list;
struct brcmf_bss_info *bi = NULL; /* must be initialized */ struct brcmf_bss_info_le *bi = NULL; /* must be initialized */
s32 err = 0; s32 err = 0;
int i; int i;
@ -2072,7 +2081,7 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
} }
WL_SCAN("scanned AP count (%d)\n", bss_list->count); WL_SCAN("scanned AP count (%d)\n", bss_list->count);
for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) { for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
bi = next_bss(bss_list, bi); bi = next_bss_le(bss_list, bi);
err = brcmf_inform_single_bss(cfg_priv, bi); err = brcmf_inform_single_bss(cfg_priv, bi);
if (err) if (err)
break; break;
@ -2085,8 +2094,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
{ {
struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
struct ieee80211_channel *notify_channel; struct ieee80211_channel *notify_channel;
struct brcmf_bss_info *bi = NULL; struct brcmf_bss_info_le *bi = NULL;
struct ieee80211_supported_band *band; struct ieee80211_supported_band *band;
struct cfg80211_bss *bss;
u8 *buf = NULL; u8 *buf = NULL;
s32 err = 0; s32 err = 0;
u16 channel; u16 channel;
@ -2114,7 +2124,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
goto CleanUp; goto CleanUp;
} }
bi = (struct brcmf_bss_info *)(buf + 4); bi = (struct brcmf_bss_info_le *)(buf + 4);
channel = bi->ctl_ch ? bi->ctl_ch : channel = bi->ctl_ch ? bi->ctl_ch :
CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
@ -2140,10 +2150,17 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
WL_CONN("signal: %d\n", notify_signal); WL_CONN("signal: %d\n", notify_signal);
WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
cfg80211_inform_bss(wiphy, notify_channel, bssid, bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
notify_timestamp, notify_capability, notify_interval, notify_timestamp, notify_capability, notify_interval,
notify_ie, notify_ielen, notify_signal, GFP_KERNEL); notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
if (!bss) {
err = -ENOMEM;
goto CleanUp;
}
cfg80211_put_bss(bss);
CleanUp: CleanUp:
kfree(buf); kfree(buf);
@ -2188,7 +2205,7 @@ static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
{ {
struct brcmf_bss_info *bi; struct brcmf_bss_info_le *bi;
struct brcmf_ssid *ssid; struct brcmf_ssid *ssid;
struct brcmf_tlv *tim; struct brcmf_tlv *tim;
u16 beacon_interval; u16 beacon_interval;
@ -2211,7 +2228,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
goto update_bss_info_out; goto update_bss_info_out;
} }
bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4); bi = (struct brcmf_bss_info_le *)(cfg_priv->extra_buf + 4);
err = brcmf_inform_single_bss(cfg_priv, bi); err = brcmf_inform_single_bss(cfg_priv, bi);
if (err) if (err)
goto update_bss_info_out; goto update_bss_info_out;

View File

@ -352,15 +352,6 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg)
return &cfg->conn_info; return &cfg->conn_info;
} }
static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
struct brcmf_bss_info *bss)
{
return bss = bss ?
(struct brcmf_bss_info *)((unsigned long)bss +
le32_to_cpu(bss->length)) :
list->bss_info;
}
extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
struct device *busdev, struct device *busdev,
void *data); void *data);

View File

@ -38,88 +38,12 @@
/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */ /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
#define SI_PCIE_DMA_H32 0x80000000 #define SI_PCIE_DMA_H32 0x80000000
/* core codes */
#define NODEV_CORE_ID 0x700 /* Invalid coreid */
#define CC_CORE_ID 0x800 /* chipcommon core */
#define ILINE20_CORE_ID 0x801 /* iline20 core */
#define SRAM_CORE_ID 0x802 /* sram core */
#define SDRAM_CORE_ID 0x803 /* sdram core */
#define PCI_CORE_ID 0x804 /* pci core */
#define MIPS_CORE_ID 0x805 /* mips core */
#define ENET_CORE_ID 0x806 /* enet mac core */
#define CODEC_CORE_ID 0x807 /* v90 codec core */
#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */
#define ADSL_CORE_ID 0x809 /* ADSL core */
#define ILINE100_CORE_ID 0x80a /* iline100 core */
#define IPSEC_CORE_ID 0x80b /* ipsec core */
#define UTOPIA_CORE_ID 0x80c /* utopia core */
#define PCMCIA_CORE_ID 0x80d /* pcmcia core */
#define SOCRAM_CORE_ID 0x80e /* internal memory core */
#define MEMC_CORE_ID 0x80f /* memc sdram core */
#define OFDM_CORE_ID 0x810 /* OFDM phy core */
#define EXTIF_CORE_ID 0x811 /* external interface core */
#define D11_CORE_ID 0x812 /* 802.11 MAC core */
#define APHY_CORE_ID 0x813 /* 802.11a phy core */
#define BPHY_CORE_ID 0x814 /* 802.11b phy core */
#define GPHY_CORE_ID 0x815 /* 802.11g phy core */
#define MIPS33_CORE_ID 0x816 /* mips3302 core */
#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */
#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */
#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */
#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */
#define SDIOH_CORE_ID 0x81b /* sdio host core */
#define ROBO_CORE_ID 0x81c /* roboswitch core */
#define ATA100_CORE_ID 0x81d /* parallel ATA core */
#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */
#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */
#define PCIE_CORE_ID 0x820 /* pci express core */
#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */
#define SRAMC_CORE_ID 0x822 /* SRAM controller core */
#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */
#define ARM11_CORE_ID 0x824 /* ARM 1176 core */
#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */
#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */
#define PMU_CORE_ID 0x827 /* PMU core */
#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */
#define SDIOD_CORE_ID 0x829 /* SDIO device core */
#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */
#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */
#define MIPS74K_CORE_ID 0x82c /* mips 74k core */
#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */
#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */
#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */
#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */
#define SC_CORE_ID 0x831 /* shared common core */
#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */
#define SPIH_CORE_ID 0x833 /* SPI host core */
#define I2S_CORE_ID 0x834 /* I2S core */
#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */
#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */
#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */
#define DEF_AI_COMP 0xfff /* Default component, in ai chips it
* maps all unused address ranges
*/
/* chipcommon being the first core: */ /* chipcommon being the first core: */
#define SI_CC_IDX 0 #define SI_CC_IDX 0
/* SOC Interconnect types (aka chip types) */ /* SOC Interconnect types (aka chip types) */
#define SOCI_AI 1 #define SOCI_AI 1
/* Common core control flags */
#define SICF_BIST_EN 0x8000
#define SICF_PME_EN 0x4000
#define SICF_CORE_BITS 0x3ffc
#define SICF_FGC 0x0002
#define SICF_CLOCK_EN 0x0001
/* Common core status flags */
#define SISF_BIST_DONE 0x8000
#define SISF_BIST_ERROR 0x4000
#define SISF_GATED_CLK 0x2000
#define SISF_DMA64 0x1000
#define SISF_CORE_BITS 0x0fff
/* A register that is common to all cores to /* A register that is common to all cores to
* communicate w/PMU regarding clock control. * communicate w/PMU regarding clock control.
*/ */

View File

@ -649,7 +649,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
len = roundup(len, 4); len = roundup(len, 4);
ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN); ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
dma_len += (u16) brcmu_pkttotlen(p); dma_len += (u16) p->len;
BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d" BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
" seg_cnt %d null delim %d\n", " seg_cnt %d null delim %d\n",
@ -741,9 +741,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
if (p) { if (p) {
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
((u8) (p->priority) == tid)) { ((u8) (p->priority) == tid)) {
plen = p->len + AMPDU_MAX_MPDU_OVERHEAD;
plen = brcmu_pkttotlen(p) +
AMPDU_MAX_MPDU_OVERHEAD;
plen = max(scb_ampdu->min_len, plen); plen = max(scb_ampdu->min_len, plen);
if ((plen + ampdu_len) > max_ampdu_bytes) { if ((plen + ampdu_len) > max_ampdu_bytes) {

View File

@ -1153,121 +1153,6 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
&txpwr); &txpwr);
} }
#ifdef POWER_DBG
static void wlc_phy_txpower_limits_dump(struct txpwr_limits *txpwr)
{
int i;
char buf[80];
char fraction[4][4] = { " ", ".25", ".5 ", ".75" };
sprintf(buf, "CCK ");
for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->cck[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->cck[i] % BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz OFDM SISO ");
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm[i] % BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz OFDM CDD ");
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_cdd[i] % BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz OFDM SISO ");
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_40_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_40_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz OFDM CDD ");
for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->ofdm_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->ofdm_40_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 SISO ");
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 CDD ");
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS0-7 STBC ");
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_stbc[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_stbc[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "20 MHz MCS8-15 SDM ");
for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_20_mimo[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_20_mimo[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 SISO ");
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_siso[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_siso[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 CDD ");
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_cdd[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_cdd[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS0-7 STBC ");
for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_stbc[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_stbc[i] %
BRCMS_TXPWR_DB_FACTOR]);
printk(KERN_DEBUG "%s\n", buf);
sprintf(buf, "40 MHz MCS8-15 SDM ");
for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++)
sprintf(buf[strlen(buf)], " %2d%s",
txpwr->mcs_40_mimo[i] / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs_40_mimo[i] %
BRCMS_TXPWR_DB_FACTOR]);
}
printk(KERN_DEBUG "%s\n", buf);
printk(KERN_DEBUG "MCS32 %2d%s\n",
txpwr->mcs32 / BRCMS_TXPWR_DB_FACTOR,
fraction[txpwr->mcs32 % BRCMS_TXPWR_DB_FACTOR]);
}
#endif /* POWER_DBG */
void void
brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec, brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
struct txpwr_limits *txpwr) struct txpwr_limits *txpwr)
@ -1478,9 +1363,6 @@ brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i]; txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
} }
#ifdef POWER_DBG
wlc_phy_txpower_limits_dump(txpwr);
#endif
return; return;
} }

View File

@ -14,7 +14,6 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pci.h> #include <linux/pci.h>
@ -22,6 +21,7 @@
#include <aiutils.h> #include <aiutils.h>
#include "types.h" #include "types.h"
#include "dma.h" #include "dma.h"
#include "soc.h"
/* /*
* DMA hardware requires each descriptor ring to be 8kB aligned, and fit within * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within
@ -358,13 +358,14 @@ static uint nrxdactive(struct dma_info *di, uint h, uint t)
static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags) static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
{ {
uint dmactrlflags = di->dma.dmactrlflags; uint dmactrlflags;
if (di == NULL) { if (di == NULL) {
DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name)); DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n"));
return 0; return 0;
} }
dmactrlflags = di->dma.dmactrlflags;
dmactrlflags &= ~mask; dmactrlflags &= ~mask;
dmactrlflags |= flags; dmactrlflags |= flags;
@ -900,7 +901,7 @@ static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)
/* /*
* !! rx entry routine * !! rx entry routine
* returns a pointer to the next frame received, or NULL if there are no more * returns the number packages in the next frame, or 0 if there are no more
* if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is * if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is
* supported with pkts chain * supported with pkts chain
* otherwise, it's treated as giant pkt and will be tossed. * otherwise, it's treated as giant pkt and will be tossed.
@ -908,38 +909,40 @@ static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)
* buffer data. After it reaches the max size of buffer, the data continues * buffer data. After it reaches the max size of buffer, the data continues
* in next DMA descriptor buffer WITHOUT DMA header * in next DMA descriptor buffer WITHOUT DMA header
*/ */
struct sk_buff *dma_rx(struct dma_pub *pub) int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
{ {
struct dma_info *di = (struct dma_info *)pub; struct dma_info *di = (struct dma_info *)pub;
struct sk_buff *p, *head, *tail; struct sk_buff_head dma_frames;
struct sk_buff *p, *next;
uint len; uint len;
uint pkt_len; uint pkt_len;
int resid = 0; int resid = 0;
int pktcnt = 1;
skb_queue_head_init(&dma_frames);
next_frame: next_frame:
head = _dma_getnextrxp(di, false); p = _dma_getnextrxp(di, false);
if (head == NULL) if (p == NULL)
return NULL; return 0;
len = le16_to_cpu(*(__le16 *) (head->data)); len = le16_to_cpu(*(__le16 *) (p->data));
DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
dma_spin_for_len(len, head); dma_spin_for_len(len, p);
/* set actual length */ /* set actual length */
pkt_len = min((di->rxoffset + len), di->rxbufsize); pkt_len = min((di->rxoffset + len), di->rxbufsize);
__skb_trim(head, pkt_len); __skb_trim(p, pkt_len);
skb_queue_tail(&dma_frames, p);
resid = len - (di->rxbufsize - di->rxoffset); resid = len - (di->rxbufsize - di->rxoffset);
/* check for single or multi-buffer rx */ /* check for single or multi-buffer rx */
if (resid > 0) { if (resid > 0) {
tail = head;
while ((resid > 0) && (p = _dma_getnextrxp(di, false))) { while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
tail->next = p;
pkt_len = min_t(uint, resid, di->rxbufsize); pkt_len = min_t(uint, resid, di->rxbufsize);
__skb_trim(p, pkt_len); __skb_trim(p, pkt_len);
skb_queue_tail(&dma_frames, p);
tail = p;
resid -= di->rxbufsize; resid -= di->rxbufsize;
pktcnt++;
} }
#ifdef BCMDBG #ifdef BCMDBG
@ -958,13 +961,18 @@ struct sk_buff *dma_rx(struct dma_pub *pub)
if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
di->name, len)); di->name, len));
brcmu_pkt_buf_free_skb(head); skb_queue_walk_safe(&dma_frames, p, next) {
skb_unlink(p, &dma_frames);
brcmu_pkt_buf_free_skb(p);
}
di->dma.rxgiants++; di->dma.rxgiants++;
pktcnt = 1;
goto next_frame; goto next_frame;
} }
} }
return head; skb_queue_splice_tail(&dma_frames, skb_list);
return pktcnt;
} }
static bool dma64_rxidle(struct dma_info *di) static bool dma64_rxidle(struct dma_info *di)

View File

@ -18,6 +18,7 @@
#define _BRCM_DMA_H_ #define _BRCM_DMA_H_
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/skbuff.h>
#include "types.h" /* forward structure declarations */ #include "types.h" /* forward structure declarations */
/* map/unmap direction */ /* map/unmap direction */
@ -80,7 +81,7 @@ extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
uint nrxpost, uint rxoffset, uint *msg_level); uint nrxpost, uint rxoffset, uint *msg_level);
void dma_rxinit(struct dma_pub *pub); void dma_rxinit(struct dma_pub *pub);
struct sk_buff *dma_rx(struct dma_pub *pub); int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
bool dma_rxfill(struct dma_pub *pub); bool dma_rxfill(struct dma_pub *pub);
bool dma_rxreset(struct dma_pub *pub); bool dma_rxreset(struct dma_pub *pub);
bool dma_txreset(struct dma_pub *pub); bool dma_txreset(struct dma_pub *pub);

View File

@ -216,8 +216,7 @@ static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = {
.ht_cap = { .ht_cap = {
/* from include/linux/ieee80211.h */ /* from include/linux/ieee80211.h */
.cap = IEEE80211_HT_CAP_GRN_FLD | .cap = IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40,
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
.ht_supported = true, .ht_supported = true,
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
.ampdu_density = AMPDU_DEF_MPDU_DENSITY, .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
@ -238,8 +237,7 @@ static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = {
BRCMS_LEGACY_5G_RATE_OFFSET, BRCMS_LEGACY_5G_RATE_OFFSET,
.ht_cap = { .ht_cap = {
.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_40,
IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */
.ht_supported = true, .ht_supported = true,
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
.ampdu_density = AMPDU_DEF_MPDU_DENSITY, .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
@ -287,6 +285,7 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
{ {
struct brcms_info *wl = hw->priv; struct brcms_info *wl = hw->priv;
bool blocked; bool blocked;
int err;
ieee80211_wake_queues(hw); ieee80211_wake_queues(hw);
spin_lock_bh(&wl->lock); spin_lock_bh(&wl->lock);
@ -295,33 +294,10 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
if (!blocked) if (!blocked)
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
return 0;
}
static void brcms_ops_stop(struct ieee80211_hw *hw)
{
ieee80211_stop_queues(hw);
}
static int
brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct brcms_info *wl;
int err;
/* Just STA for now */
if (vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_MESH_POINT &&
vif->type != NL80211_IFTYPE_STATION &&
vif->type != NL80211_IFTYPE_WDS &&
vif->type != NL80211_IFTYPE_ADHOC) {
wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
" STA for now\n", __func__, vif->type);
return -EOPNOTSUPP;
}
wl = hw->priv;
spin_lock_bh(&wl->lock); spin_lock_bh(&wl->lock);
/* avoid acknowledging frames before a non-monitor device is added */
wl->mute_tx = true;
if (!wl->pub->up) if (!wl->pub->up)
err = brcms_up(wl); err = brcms_up(wl);
else else
@ -331,16 +307,28 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
if (err != 0) if (err != 0)
wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__, wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
err); err);
return err; return err;
} }
static void static void brcms_ops_stop(struct ieee80211_hw *hw)
brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{ {
struct brcms_info *wl; struct brcms_info *wl = hw->priv;
int status;
wl = hw->priv; ieee80211_stop_queues(hw);
if (wl->wlc == NULL)
return;
spin_lock_bh(&wl->lock);
status = brcms_c_chipmatch(wl->wlc->hw->vendorid,
wl->wlc->hw->deviceid);
spin_unlock_bh(&wl->lock);
if (!status) {
wiphy_err(wl->wiphy,
"wl: brcms_ops_stop: chipmatch failed\n");
return;
}
/* put driver in down state */ /* put driver in down state */
spin_lock_bh(&wl->lock); spin_lock_bh(&wl->lock);
@ -348,6 +336,29 @@ brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
spin_unlock_bh(&wl->lock); spin_unlock_bh(&wl->lock);
} }
static int
brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct brcms_info *wl = hw->priv;
/* Just STA for now */
if (vif->type != NL80211_IFTYPE_STATION) {
wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
" STA for now\n", __func__, vif->type);
return -EOPNOTSUPP;
}
wl->mute_tx = false;
brcms_c_mute(wl->wlc, false);
return 0;
}
static void
brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
}
static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
{ {
struct ieee80211_conf *conf = &hw->conf; struct ieee80211_conf *conf = &hw->conf;
@ -609,13 +620,6 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
wl->pub->global_ampdu->scb = scb; wl->pub->global_ampdu->scb = scb;
wl->pub->global_ampdu->max_pdu = 16; wl->pub->global_ampdu->max_pdu = 16;
sta->ht_cap.ht_supported = true;
sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY;
sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
/* /*
* minstrel_ht initiates addBA on our behalf by calling * minstrel_ht initiates addBA on our behalf by calling
* ieee80211_start_tx_ba_session() * ieee80211_start_tx_ba_session()
@ -877,37 +881,18 @@ static void brcms_free(struct brcms_info *wl)
} }
/* /*
* called from both kernel as from this kernel module. * called from both kernel as from this kernel module (error flow on attach)
* precondition: perimeter lock is not acquired. * precondition: perimeter lock is not acquired.
*/ */
static void brcms_remove(struct pci_dev *pdev) static void brcms_remove(struct pci_dev *pdev)
{ {
struct brcms_info *wl; struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ieee80211_hw *hw; struct brcms_info *wl = hw->priv;
int status;
hw = pci_get_drvdata(pdev);
wl = hw->priv;
if (!wl) {
pr_err("wl: brcms_remove: pci_get_drvdata failed\n");
return;
}
spin_lock_bh(&wl->lock);
status = brcms_c_chipmatch(pdev->vendor, pdev->device);
spin_unlock_bh(&wl->lock);
if (!status) {
wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch "
"failed\n");
return;
}
if (wl->wlc) { if (wl->wlc) {
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
ieee80211_unregister_hw(hw); ieee80211_unregister_hw(hw);
spin_lock_bh(&wl->lock);
brcms_down(wl);
spin_unlock_bh(&wl->lock);
} }
pci_disable_device(pdev); pci_disable_device(pdev);
@ -1081,9 +1066,6 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
wl->pub->ieee_hw = hw; wl->pub->ieee_hw = hw;
/* disable mpc */
brcms_c_set_radio_mpc(wl->wlc, false);
/* register our interrupt handler */ /* register our interrupt handler */
if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
@ -1319,8 +1301,7 @@ void brcms_init(struct brcms_info *wl)
{ {
BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit); BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
brcms_reset(wl); brcms_reset(wl);
brcms_c_init(wl->wlc, wl->mute_tx);
brcms_c_init(wl->wlc);
} }
/* /*
@ -1337,6 +1318,14 @@ uint brcms_reset(struct brcms_info *wl)
return 0; return 0;
} }
void brcms_fatal_error(struct brcms_info *wl)
{
wiphy_err(wl->wlc->wiphy, "wl%d: fatal error, reinitializing\n",
wl->wlc->pub->unit);
brcms_reset(wl);
ieee80211_restart_hw(wl->pub->ieee_hw);
}
/* /*
* These are interrupt on/off entry points. Disable interrupts * These are interrupt on/off entry points. Disable interrupts
* during interrupt state transition. * during interrupt state transition.

View File

@ -80,6 +80,7 @@ struct brcms_info {
struct brcms_firmware fw; struct brcms_firmware fw;
struct wiphy *wiphy; struct wiphy *wiphy;
struct brcms_ucode ucode; struct brcms_ucode ucode;
bool mute_tx;
}; };
/* misc callbacks */ /* misc callbacks */
@ -104,5 +105,6 @@ extern bool brcms_del_timer(struct brcms_timer *timer);
extern void brcms_msleep(struct brcms_info *wl, uint ms); extern void brcms_msleep(struct brcms_info *wl, uint ms);
extern void brcms_dpc(unsigned long data); extern void brcms_dpc(unsigned long data);
extern void brcms_timer(struct brcms_timer *t); extern void brcms_timer(struct brcms_timer *t);
extern void brcms_fatal_error(struct brcms_info *wl);
#endif /* _BRCM_MAC80211_IF_H_ */ #endif /* _BRCM_MAC80211_IF_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -44,8 +44,6 @@
/* transmit buffer max headroom for protocol headers */ /* transmit buffer max headroom for protocol headers */
#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN) #define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
#define AC_COUNT 4
/* Macros for doing definition and get/set of bitfields /* Macros for doing definition and get/set of bitfields
* Usage example, e.g. a three-bit field (bits 4-6): * Usage example, e.g. a three-bit field (bits 4-6):
* #define <NAME>_M BITFIELD_MASK(3) * #define <NAME>_M BITFIELD_MASK(3)
@ -427,11 +425,6 @@ struct brcms_txq_info {
* bandinit_pending: track band init in auto band. * bandinit_pending: track band init in auto band.
* radio_monitor: radio timer is running. * radio_monitor: radio timer is running.
* going_down: down path intermediate variable. * going_down: down path intermediate variable.
* mpc: enable minimum power consumption.
* mpc_dlycnt: # of watchdog cnt before turn disable radio.
* mpc_offcnt: # of watchdog cnt that radio is disabled.
* mpc_delay_off: delay radio disable by # of watchdog cnt.
* prev_non_delay_mpc: prev state brcms_c_is_non_delay_mpc.
* wdtimer: timer for watchdog routine. * wdtimer: timer for watchdog routine.
* radio_timer: timer for hw radio button monitor routine. * radio_timer: timer for hw radio button monitor routine.
* monitor: monitor (MPDU sniffing) mode. * monitor: monitor (MPDU sniffing) mode.
@ -441,7 +434,7 @@ struct brcms_txq_info {
* bcn_li_dtim: beacon listen interval in # dtims. * bcn_li_dtim: beacon listen interval in # dtims.
* WDarmed: watchdog timer is armed. * WDarmed: watchdog timer is armed.
* WDlast: last time wlc_watchdog() was called. * WDlast: last time wlc_watchdog() was called.
* edcf_txop[AC_COUNT]: current txop for each ac. * edcf_txop[IEEE80211_NUM_ACS]: current txop for each ac.
* wme_retries: per-AC retry limits. * wme_retries: per-AC retry limits.
* tx_prec_map: Precedence map based on HW FIFO space. * tx_prec_map: Precedence map based on HW FIFO space.
* fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME. * fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME.
@ -522,12 +515,6 @@ struct brcms_c_info {
bool radio_monitor; bool radio_monitor;
bool going_down; bool going_down;
bool mpc;
u8 mpc_dlycnt;
u8 mpc_offcnt;
u8 mpc_delay_off;
u8 prev_non_delay_mpc;
struct brcms_timer *wdtimer; struct brcms_timer *wdtimer;
struct brcms_timer *radio_timer; struct brcms_timer *radio_timer;
@ -546,9 +533,9 @@ struct brcms_c_info {
u32 WDlast; u32 WDlast;
/* WME */ /* WME */
u16 edcf_txop[AC_COUNT]; u16 edcf_txop[IEEE80211_NUM_ACS];
u16 wme_retries[AC_COUNT]; u16 wme_retries[IEEE80211_NUM_ACS];
u16 tx_prec_map; u16 tx_prec_map;
u16 fifo2prec_map[NFIFO]; u16 fifo2prec_map[NFIFO];

View File

@ -112,7 +112,7 @@ static const struct chan_info_basic chan_info_all[] = {
{216, 50800} {216, 50800}
}; };
const u8 ofdm_rate_lookup[] = { static const u8 ofdm_rate_lookup[] = {
BRCM_RATE_48M, BRCM_RATE_48M,
BRCM_RATE_24M, BRCM_RATE_24M,
@ -190,15 +190,7 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
data = R_REG(&pi->regs->radioregdata); data = R_REG(&pi->regs->radioregdata);
} else { } else {
W_REG_FLUSH(&pi->regs->phy4waddr, addr); W_REG_FLUSH(&pi->regs->phy4waddr, addr);
#ifdef __ARM_ARCH_4T__
__asm__(" .align 4 ");
__asm__(" nop ");
data = R_REG(&pi->regs->phy4wdatalo); data = R_REG(&pi->regs->phy4wdatalo);
#else
data = R_REG(&pi->regs->phy4wdatalo);
#endif
} }
pi->phy_wreg = 0; pi->phy_wreg = 0;

View File

@ -774,11 +774,6 @@ struct brcms_phy {
s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ]; s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
u8 nphy_noise_index; u8 nphy_noise_index;
u8 nphy_txpid2g[PHY_CORE_NUM_2];
u8 nphy_txpid5g[PHY_CORE_NUM_2];
u8 nphy_txpid5gl[PHY_CORE_NUM_2];
u8 nphy_txpid5gh[PHY_CORE_NUM_2];
bool nphy_gain_boost; bool nphy_gain_boost;
bool nphy_elna_gain_config; bool nphy_elna_gain_config;
u16 old_bphy_test; u16 old_bphy_test;

View File

@ -29,6 +29,7 @@
#include "phy_radio.h" #include "phy_radio.h"
#include "phyreg_n.h" #include "phyreg_n.h"
#include "phytbl_n.h" #include "phytbl_n.h"
#include "soc.h"
#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \ #define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \ read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
@ -14417,12 +14418,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
switch (band_num) { switch (band_num) {
case 0: case 0:
pi->nphy_txpid2g[PHY_CORE_0] =
(u8) wlapi_getintvar(shim,
BRCMS_SROM_TXPID2GA0);
pi->nphy_txpid2g[PHY_CORE_1] =
(u8) wlapi_getintvar(shim,
BRCMS_SROM_TXPID2GA1);
pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
(s8) wlapi_getintvar(shim, (s8) wlapi_getintvar(shim,
BRCMS_SROM_MAXP2GA0); BRCMS_SROM_MAXP2GA0);
@ -14486,12 +14481,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
break; break;
case 1: case 1:
pi->nphy_txpid5g[PHY_CORE_0] =
(u8) wlapi_getintvar(shim,
BRCMS_SROM_TXPID5GA0);
pi->nphy_txpid5g[PHY_CORE_1] =
(u8) wlapi_getintvar(shim,
BRCMS_SROM_TXPID5GA1);
pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
(s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0); (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0);
pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
@ -14551,12 +14540,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
break; break;
case 2: case 2:
pi->nphy_txpid5gl[0] =
(u8) wlapi_getintvar(shim,
BRCMS_SROM_TXPID5GLA0);
pi->nphy_txpid5gl[1] =
(u8) wlapi_getintvar(shim,
BRCMS_SROM_TXPID5GLA1);
pi->nphy_pwrctrl_info[0].max_pwr_5gl = pi->nphy_pwrctrl_info[0].max_pwr_5gl =
(s8) wlapi_getintvar(shim, (s8) wlapi_getintvar(shim,
BRCMS_SROM_MAXP5GLA0); BRCMS_SROM_MAXP5GLA0);
@ -14615,12 +14598,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
break; break;
case 3: case 3:
pi->nphy_txpid5gh[0] =
(u8) wlapi_getintvar(shim,
BRCMS_SROM_TXPID5GHA0);
pi->nphy_txpid5gh[1] =
(u8) wlapi_getintvar(shim,
BRCMS_SROM_TXPID5GHA1);
pi->nphy_pwrctrl_info[0].max_pwr_5gh = pi->nphy_pwrctrl_info[0].max_pwr_5gh =
(s8) wlapi_getintvar(shim, (s8) wlapi_getintvar(shim,
BRCMS_SROM_MAXP5GHA0); BRCMS_SROM_MAXP5GHA0);
@ -27994,20 +27971,11 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0); chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
switch (chan_freq_range) { switch (chan_freq_range) {
case WL_CHAN_FREQ_RANGE_2G: case WL_CHAN_FREQ_RANGE_2G:
txpi[0] = pi->nphy_txpid2g[0];
txpi[1] = pi->nphy_txpid2g[1];
break;
case WL_CHAN_FREQ_RANGE_5GL: case WL_CHAN_FREQ_RANGE_5GL:
txpi[0] = pi->nphy_txpid5gl[0];
txpi[1] = pi->nphy_txpid5gl[1];
break;
case WL_CHAN_FREQ_RANGE_5GM: case WL_CHAN_FREQ_RANGE_5GM:
txpi[0] = pi->nphy_txpid5g[0];
txpi[1] = pi->nphy_txpid5g[1];
break;
case WL_CHAN_FREQ_RANGE_5GH: case WL_CHAN_FREQ_RANGE_5GH:
txpi[0] = pi->nphy_txpid5gh[0]; txpi[0] = 0;
txpi[1] = pi->nphy_txpid5gh[1]; txpi[1] = 0;
break; break;
default: default:
txpi[0] = txpi[1] = 91; txpi[0] = txpi[1] = 91;

View File

@ -23,6 +23,7 @@
#include "pub.h" #include "pub.h"
#include "aiutils.h" #include "aiutils.h"
#include "pmu.h" #include "pmu.h"
#include "soc.h"
/* /*
* external LPO crystal frequency * external LPO crystal frequency

View File

@ -170,22 +170,6 @@ enum brcms_srom_id {
BRCMS_SROM_TSSIPOS2G, BRCMS_SROM_TSSIPOS2G,
BRCMS_SROM_TSSIPOS5G, BRCMS_SROM_TSSIPOS5G,
BRCMS_SROM_TXCHAIN, BRCMS_SROM_TXCHAIN,
BRCMS_SROM_TXPID2GA0,
BRCMS_SROM_TXPID2GA1,
BRCMS_SROM_TXPID2GA2,
BRCMS_SROM_TXPID2GA3,
BRCMS_SROM_TXPID5GA0,
BRCMS_SROM_TXPID5GA1,
BRCMS_SROM_TXPID5GA2,
BRCMS_SROM_TXPID5GA3,
BRCMS_SROM_TXPID5GHA0,
BRCMS_SROM_TXPID5GHA1,
BRCMS_SROM_TXPID5GHA2,
BRCMS_SROM_TXPID5GHA3,
BRCMS_SROM_TXPID5GLA0,
BRCMS_SROM_TXPID5GLA1,
BRCMS_SROM_TXPID5GLA2,
BRCMS_SROM_TXPID5GLA3,
/* /*
* per-path identifiers (see srom.c) * per-path identifiers (see srom.c)
*/ */
@ -225,10 +209,6 @@ enum brcms_srom_id {
BRCMS_SROM_PA2GW2A1, BRCMS_SROM_PA2GW2A1,
BRCMS_SROM_PA2GW2A2, BRCMS_SROM_PA2GW2A2,
BRCMS_SROM_PA2GW2A3, BRCMS_SROM_PA2GW2A3,
BRCMS_SROM_PA2GW3A0,
BRCMS_SROM_PA2GW3A1,
BRCMS_SROM_PA2GW3A2,
BRCMS_SROM_PA2GW3A3,
BRCMS_SROM_PA5GHW0A0, BRCMS_SROM_PA5GHW0A0,
BRCMS_SROM_PA5GHW0A1, BRCMS_SROM_PA5GHW0A1,
BRCMS_SROM_PA5GHW0A2, BRCMS_SROM_PA5GHW0A2,
@ -241,10 +221,6 @@ enum brcms_srom_id {
BRCMS_SROM_PA5GHW2A1, BRCMS_SROM_PA5GHW2A1,
BRCMS_SROM_PA5GHW2A2, BRCMS_SROM_PA5GHW2A2,
BRCMS_SROM_PA5GHW2A3, BRCMS_SROM_PA5GHW2A3,
BRCMS_SROM_PA5GHW3A0,
BRCMS_SROM_PA5GHW3A1,
BRCMS_SROM_PA5GHW3A2,
BRCMS_SROM_PA5GHW3A3,
BRCMS_SROM_PA5GLW0A0, BRCMS_SROM_PA5GLW0A0,
BRCMS_SROM_PA5GLW0A1, BRCMS_SROM_PA5GLW0A1,
BRCMS_SROM_PA5GLW0A2, BRCMS_SROM_PA5GLW0A2,
@ -257,10 +233,6 @@ enum brcms_srom_id {
BRCMS_SROM_PA5GLW2A1, BRCMS_SROM_PA5GLW2A1,
BRCMS_SROM_PA5GLW2A2, BRCMS_SROM_PA5GLW2A2,
BRCMS_SROM_PA5GLW2A3, BRCMS_SROM_PA5GLW2A3,
BRCMS_SROM_PA5GLW3A0,
BRCMS_SROM_PA5GLW3A1,
BRCMS_SROM_PA5GLW3A2,
BRCMS_SROM_PA5GLW3A3,
BRCMS_SROM_PA5GW0A0, BRCMS_SROM_PA5GW0A0,
BRCMS_SROM_PA5GW0A1, BRCMS_SROM_PA5GW0A1,
BRCMS_SROM_PA5GW0A2, BRCMS_SROM_PA5GW0A2,
@ -273,14 +245,9 @@ enum brcms_srom_id {
BRCMS_SROM_PA5GW2A1, BRCMS_SROM_PA5GW2A1,
BRCMS_SROM_PA5GW2A2, BRCMS_SROM_PA5GW2A2,
BRCMS_SROM_PA5GW2A3, BRCMS_SROM_PA5GW2A3,
BRCMS_SROM_PA5GW3A0,
BRCMS_SROM_PA5GW3A1,
BRCMS_SROM_PA5GW3A2,
BRCMS_SROM_PA5GW3A3,
}; };
#define BRCMS_NUMRATES 16 /* max # of rates in a rateset */ #define BRCMS_NUMRATES 16 /* max # of rates in a rateset */
#define D11_PHY_HDR_LEN 6 /* Phy header length - 6 bytes */
/* phy types */ /* phy types */
#define PHY_TYPE_A 0 /* Phy type A */ #define PHY_TYPE_A 0 /* Phy type A */
@ -414,7 +381,6 @@ struct brcms_pub {
uint _nbands; /* # bands supported */ uint _nbands; /* # bands supported */
uint now; /* # elapsed seconds */ uint now; /* # elapsed seconds */
bool promisc; /* promiscuous destination address */
bool delayed_down; /* down delayed */ bool delayed_down; /* down delayed */
bool associated; /* true:part of [I]BSS, false: not */ bool associated; /* true:part of [I]BSS, false: not */
/* (union of stas_associated, aps_associated) */ /* (union of stas_associated, aps_associated) */
@ -572,7 +538,7 @@ extern int brcms_c_up(struct brcms_c_info *wlc);
extern uint brcms_c_down(struct brcms_c_info *wlc); extern uint brcms_c_down(struct brcms_c_info *wlc);
extern bool brcms_c_chipmatch(u16 vendor, u16 device); extern bool brcms_c_chipmatch(u16 vendor, u16 device);
extern void brcms_c_init(struct brcms_c_info *wlc); extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx);
extern void brcms_c_reset(struct brcms_c_info *wlc); extern void brcms_c_reset(struct brcms_c_info *wlc);
extern void brcms_c_intrson(struct brcms_c_info *wlc); extern void brcms_c_intrson(struct brcms_c_info *wlc);
@ -628,7 +594,7 @@ extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
u8 interval); u8 interval);
extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
extern void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc);
extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
#endif /* _BRCM_PUB_H_ */ #endif /* _BRCM_PUB_H_ */

View File

@ -19,6 +19,7 @@
#include "types.h" #include "types.h"
#include "d11.h" #include "d11.h"
#include "phy_hal.h"
extern const u8 rate_info[]; extern const u8 rate_info[];
extern const struct brcms_c_rateset cck_ofdm_mimo_rates; extern const struct brcms_c_rateset cck_ofdm_mimo_rates;
@ -198,11 +199,9 @@ static inline u8 cck_rspec(u8 cck)
/* Convert encoded rate value in plcp header to numerical rates in 500 KHz /* Convert encoded rate value in plcp header to numerical rates in 500 KHz
* increments */ * increments */
extern const u8 ofdm_rate_lookup[];
static inline u8 ofdm_phy2mac_rate(u8 rlpt) static inline u8 ofdm_phy2mac_rate(u8 rlpt)
{ {
return ofdm_rate_lookup[rlpt & 0x7]; return wlc_phy_get_ofdm_rate_lookup()[rlpt & 0x7];
} }
static inline u8 cck_phy2mac_rate(u8 signal) static inline u8 cck_phy2mac_rate(u8 signal)

View File

@ -28,6 +28,7 @@
#include "aiutils.h" #include "aiutils.h"
#include "otp.h" #include "otp.h"
#include "srom.h" #include "srom.h"
#include "soc.h"
/* /*
* SROM CRC8 polynomial value: * SROM CRC8 polynomial value:
@ -62,9 +63,6 @@
#define SROM_MACHI_ET1 42 #define SROM_MACHI_ET1 42
#define SROM_MACMID_ET1 43 #define SROM_MACMID_ET1 43
#define SROM_MACLO_ET1 44 #define SROM_MACLO_ET1 44
#define SROM3_MACHI 37
#define SROM3_MACMID 38
#define SROM3_MACLO 39
#define SROM_BXARSSI2G 40 #define SROM_BXARSSI2G 40
#define SROM_BXARSSI5G 41 #define SROM_BXARSSI5G 41
@ -101,7 +99,6 @@
#define SROM_BFL 57 #define SROM_BFL 57
#define SROM_BFL2 28 #define SROM_BFL2 28
#define SROM3_BFL2 61
#define SROM_AG10 58 #define SROM_AG10 58
@ -109,99 +106,16 @@
#define SROM_OPO 60 #define SROM_OPO 60
#define SROM3_LEDDC 62
#define SROM_CRCREV 63 #define SROM_CRCREV 63
/* SROM Rev 4: Reallocate the software part of the srom to accommodate
* MIMO features. It assumes up to two PCIE functions and 440 bytes
* of usable srom i.e. the usable storage in chips with OTP that
* implements hardware redundancy.
*/
#define SROM4_WORDS 220 #define SROM4_WORDS 220
#define SROM4_SIGN 32
#define SROM4_SIGNATURE 0x5372
#define SROM4_BREV 33
#define SROM4_BFL0 34
#define SROM4_BFL1 35
#define SROM4_BFL2 36
#define SROM4_BFL3 37
#define SROM5_BFL0 37
#define SROM5_BFL1 38
#define SROM5_BFL2 39
#define SROM5_BFL3 40
#define SROM4_MACHI 38
#define SROM4_MACMID 39
#define SROM4_MACLO 40
#define SROM5_MACHI 41
#define SROM5_MACMID 42
#define SROM5_MACLO 43
#define SROM4_CCODE 41
#define SROM4_REGREV 42
#define SROM5_CCODE 34
#define SROM5_REGREV 35
#define SROM4_LEDBH10 43
#define SROM4_LEDBH32 44
#define SROM5_LEDBH10 59
#define SROM5_LEDBH32 60
#define SROM4_LEDDC 45
#define SROM5_LEDDC 45
#define SROM4_AA 46
#define SROM4_AG10 47
#define SROM4_AG32 48
#define SROM4_TXPID2G 49
#define SROM4_TXPID5G 51
#define SROM4_TXPID5GL 53
#define SROM4_TXPID5GH 55
#define SROM4_TXRXC 61
#define SROM4_TXCHAIN_MASK 0x000f #define SROM4_TXCHAIN_MASK 0x000f
#define SROM4_TXCHAIN_SHIFT 0
#define SROM4_RXCHAIN_MASK 0x00f0 #define SROM4_RXCHAIN_MASK 0x00f0
#define SROM4_RXCHAIN_SHIFT 4
#define SROM4_SWITCH_MASK 0xff00 #define SROM4_SWITCH_MASK 0xff00
#define SROM4_SWITCH_SHIFT 8
/* Per-path fields */ /* Per-path fields */
#define MAX_PATH_SROM 4 #define MAX_PATH_SROM 4
#define SROM4_PATH0 64
#define SROM4_PATH1 87
#define SROM4_PATH2 110
#define SROM4_PATH3 133
#define SROM4_2G_ITT_MAXP 0
#define SROM4_2G_PA 1
#define SROM4_5G_ITT_MAXP 5
#define SROM4_5GLH_MAXP 6
#define SROM4_5G_PA 7
#define SROM4_5GL_PA 11
#define SROM4_5GH_PA 15
/* All the miriad power offsets */
#define SROM4_2G_CCKPO 156
#define SROM4_2G_OFDMPO 157
#define SROM4_5G_OFDMPO 159
#define SROM4_5GL_OFDMPO 161
#define SROM4_5GH_OFDMPO 163
#define SROM4_2G_MCSPO 165
#define SROM4_5G_MCSPO 173
#define SROM4_5GL_MCSPO 181
#define SROM4_5GH_MCSPO 189
#define SROM4_CDDPO 197
#define SROM4_STBCPO 198
#define SROM4_BW40PO 199
#define SROM4_BWDUPPO 200
#define SROM4_CRCREV 219 #define SROM4_CRCREV 219
@ -424,103 +338,32 @@ struct brcms_varbuf {
static const struct brcms_sromvar pci_sromvars[] = { static const struct brcms_sromvar pci_sromvars[] = {
{BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID,
0xffff}, 0xffff},
{BRCMS_SROM_BOARDREV, 0x0000000e, SRFL_PRHEX, SROM_AABREV,
SROM_BR_MASK},
{BRCMS_SROM_BOARDREV, 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
{BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
{BRCMS_SROM_BOARDFLAGS, 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
{BRCMS_SROM_BOARDFLAGS, 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM_BFL2, 0xffff},
{BRCMS_SROM_BOARDFLAGS, 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM3_BFL2, 0xffff},
{BRCMS_SROM_BOARDFLAGS, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0,
0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM4_BFL1, 0xffff},
{BRCMS_SROM_BOARDFLAGS, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0,
0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM5_BFL1, 0xffff},
{BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0,
0xffff}, 0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff}, {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff},
{BRCMS_SROM_BOARDFLAGS2, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2,
0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM4_BFL3, 0xffff},
{BRCMS_SROM_BOARDFLAGS2, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2,
0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM5_BFL3, 0xffff},
{BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2,
0xffff}, 0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff}, {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff},
{BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
{BRCMS_SROM_BOARDNUM, 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
{BRCMS_SROM_BOARDNUM, 0x00000008, 0, SROM3_MACLO, 0xffff},
{BRCMS_SROM_BOARDNUM, 0x00000010, 0, SROM4_MACLO, 0xffff},
{BRCMS_SROM_BOARDNUM, 0x000000e0, 0, SROM5_MACLO, 0xffff},
{BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff}, {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff},
{BRCMS_SROM_CC, 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
{BRCMS_SROM_REGREV, 0x00000008, 0, SROM_OPO, 0xff00},
{BRCMS_SROM_REGREV, 0x00000010, 0, SROM4_REGREV, 0x00ff},
{BRCMS_SROM_REGREV, 0x000000e0, 0, SROM5_REGREV, 0x00ff},
{BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff}, {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff},
{BRCMS_SROM_LEDBH0, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
{BRCMS_SROM_LEDBH1, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
{BRCMS_SROM_LEDBH2, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
{BRCMS_SROM_LEDBH3, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
{BRCMS_SROM_LEDBH0, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
{BRCMS_SROM_LEDBH1, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
{BRCMS_SROM_LEDBH2, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
{BRCMS_SROM_LEDBH3, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
{BRCMS_SROM_LEDBH0, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
{BRCMS_SROM_LEDBH1, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
{BRCMS_SROM_LEDBH2, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
{BRCMS_SROM_LEDBH3, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
{BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
{BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
{BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
{BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
{BRCMS_SROM_PA0B0, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
{BRCMS_SROM_PA0B1, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
{BRCMS_SROM_PA0B2, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
{BRCMS_SROM_PA0ITSSIT, 0x0000000e, 0, SROM_ITT, 0x00ff},
{BRCMS_SROM_PA0MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
{BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
{BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
{BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
{BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
{BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff}, {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
{BRCMS_SROM_OPO, 0x0000000c, 0, SROM_OPO, 0x00ff},
{BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff}, {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
{BRCMS_SROM_AA2G, 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
{BRCMS_SROM_AA2G, 0x000000f0, 0, SROM4_AA, 0x00ff},
{BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff}, {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff},
{BRCMS_SROM_AA5G, 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
{BRCMS_SROM_AA5G, 0x000000f0, 0, SROM4_AA, 0xff00},
{BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00}, {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00},
{BRCMS_SROM_AG0, 0x0000000e, 0, SROM_AG10, 0x00ff},
{BRCMS_SROM_AG1, 0x0000000e, 0, SROM_AG10, 0xff00},
{BRCMS_SROM_AG0, 0x000000f0, 0, SROM4_AG10, 0x00ff},
{BRCMS_SROM_AG1, 0x000000f0, 0, SROM4_AG10, 0xff00},
{BRCMS_SROM_AG2, 0x000000f0, 0, SROM4_AG32, 0x00ff},
{BRCMS_SROM_AG3, 0x000000f0, 0, SROM4_AG32, 0xff00},
{BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff}, {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff},
{BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00}, {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00},
{BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff}, {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff},
{BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00}, {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00},
{BRCMS_SROM_PA1B0, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
{BRCMS_SROM_PA1B1, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
{BRCMS_SROM_PA1B2, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
{BRCMS_SROM_PA1LOB0, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
{BRCMS_SROM_PA1LOB1, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
{BRCMS_SROM_PA1LOB2, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
{BRCMS_SROM_PA1HIB0, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
{BRCMS_SROM_PA1HIB1, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
{BRCMS_SROM_PA1HIB2, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
{BRCMS_SROM_PA1ITSSIT, 0x0000000e, 0, SROM_ITT, 0xff00},
{BRCMS_SROM_PA1MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
{BRCMS_SROM_PA1LOMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
{BRCMS_SROM_PA1HIMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
{BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
{BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
{BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
@ -534,40 +377,20 @@ static const struct brcms_sromvar pci_sromvars[] = {
{BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff}, {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
{BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
{BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
{BRCMS_SROM_BXA2G, 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
{BRCMS_SROM_RSSISAV2G, 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
{BRCMS_SROM_RSSISMC2G, 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
{BRCMS_SROM_RSSISMF2G, 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
{BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
{BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
{BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
{BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
{BRCMS_SROM_BXA5G, 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
{BRCMS_SROM_RSSISAV5G, 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
{BRCMS_SROM_RSSISMC5G, 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
{BRCMS_SROM_RSSISMF5G, 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
{BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
{BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
{BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
{BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
{BRCMS_SROM_TRI2G, 0x00000008, 0, SROM_TRI52G, 0x00ff},
{BRCMS_SROM_TRI5G, 0x00000008, 0, SROM_TRI52G, 0xff00},
{BRCMS_SROM_TRI5GL, 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
{BRCMS_SROM_TRI5GH, 0x00000008, 0, SROM_TRI5GHL, 0xff00},
{BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff}, {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
{BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00}, {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00},
{BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff}, {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
{BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
{BRCMS_SROM_RXPO2G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
{BRCMS_SROM_RXPO5G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
{BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
{BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
{BRCMS_SROM_TXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
SROM4_TXCHAIN_MASK},
{BRCMS_SROM_RXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
SROM4_RXCHAIN_MASK},
{BRCMS_SROM_ANTSWITCH, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
SROM4_SWITCH_MASK},
{BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
SROM4_TXCHAIN_MASK}, SROM4_TXCHAIN_MASK},
{BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
@ -594,43 +417,11 @@ static const struct brcms_sromvar pci_sromvars[] = {
SROM8_FEM_ANTSWLUT_MASK}, SROM8_FEM_ANTSWLUT_MASK},
{BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00}, {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00},
{BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff}, {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
{BRCMS_SROM_TXPID2GA0, 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
{BRCMS_SROM_TXPID2GA1, 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
{BRCMS_SROM_TXPID2GA2, 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
{BRCMS_SROM_TXPID2GA3, 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
{BRCMS_SROM_TXPID5GA0, 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
{BRCMS_SROM_TXPID5GA1, 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
{BRCMS_SROM_TXPID5GA2, 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
{BRCMS_SROM_TXPID5GA3, 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
{BRCMS_SROM_TXPID5GLA0, 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
{BRCMS_SROM_TXPID5GLA1, 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
{BRCMS_SROM_TXPID5GLA2, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
{BRCMS_SROM_TXPID5GLA3, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
{BRCMS_SROM_TXPID5GHA0, 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
{BRCMS_SROM_TXPID5GHA1, 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
{BRCMS_SROM_TXPID5GHA2, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
{BRCMS_SROM_TXPID5GHA3, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
{BRCMS_SROM_CCODE, 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
{BRCMS_SROM_CCODE, 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
{BRCMS_SROM_CCODE, 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
{BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
{BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
{BRCMS_SROM_MACADDR, 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
{BRCMS_SROM_MACADDR, 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
{BRCMS_SROM_MACADDR, 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
{BRCMS_SROM_IL0MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0,
0xffff},
{BRCMS_SROM_ET1MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1,
0xffff},
{BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC,
0xffff}, 0xffff},
{BRCMS_SROM_LEDDC, 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC,
0xffff},
{BRCMS_SROM_LEDDC, 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC,
0xffff},
{BRCMS_SROM_LEDDC, 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC,
0xffff},
{BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
0x01ff}, 0x01ff},
{BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
@ -650,16 +441,7 @@ static const struct brcms_sromvar pci_sromvars[] = {
{BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA,
0x00ff}, 0x00ff},
{BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
{BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
{BRCMS_SROM_OFDM2GPO, 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
{BRCMS_SROM_OFDM5GPO, 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
{BRCMS_SROM_OFDM5GLPO, 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
{BRCMS_SROM_OFDM5GHPO, 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
{BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
{BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
@ -668,38 +450,6 @@ static const struct brcms_sromvar pci_sromvars[] = {
{BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
{BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
{BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
{BRCMS_SROM_MCS2GPO0, 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
{BRCMS_SROM_MCS2GPO1, 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
{BRCMS_SROM_MCS2GPO2, 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
{BRCMS_SROM_MCS2GPO3, 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
{BRCMS_SROM_MCS2GPO4, 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
{BRCMS_SROM_MCS2GPO5, 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
{BRCMS_SROM_MCS2GPO6, 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
{BRCMS_SROM_MCS2GPO7, 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
{BRCMS_SROM_MCS5GPO0, 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
{BRCMS_SROM_MCS5GPO1, 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
{BRCMS_SROM_MCS5GPO2, 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
{BRCMS_SROM_MCS5GPO3, 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
{BRCMS_SROM_MCS5GPO4, 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
{BRCMS_SROM_MCS5GPO5, 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
{BRCMS_SROM_MCS5GPO6, 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
{BRCMS_SROM_MCS5GPO7, 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
{BRCMS_SROM_MCS5GLPO0, 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
{BRCMS_SROM_MCS5GLPO1, 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
{BRCMS_SROM_MCS5GLPO2, 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
{BRCMS_SROM_MCS5GLPO3, 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
{BRCMS_SROM_MCS5GLPO4, 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
{BRCMS_SROM_MCS5GLPO5, 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
{BRCMS_SROM_MCS5GLPO6, 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
{BRCMS_SROM_MCS5GLPO7, 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
{BRCMS_SROM_MCS5GHPO0, 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
{BRCMS_SROM_MCS5GHPO1, 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
{BRCMS_SROM_MCS5GHPO2, 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
{BRCMS_SROM_MCS5GHPO3, 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
{BRCMS_SROM_MCS5GHPO4, 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
{BRCMS_SROM_MCS5GHPO5, 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
{BRCMS_SROM_MCS5GHPO6, 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
{BRCMS_SROM_MCS5GHPO7, 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
{BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
{BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
{BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
@ -732,10 +482,6 @@ static const struct brcms_sromvar pci_sromvars[] = {
{BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
{BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
{BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
{BRCMS_SROM_CDDPO, 0x000000f0, 0, SROM4_CDDPO, 0xffff},
{BRCMS_SROM_STBCPO, 0x000000f0, 0, SROM4_STBCPO, 0xffff},
{BRCMS_SROM_BW40PO, 0x000000f0, 0, SROM4_BW40PO, 0xffff},
{BRCMS_SROM_BWDUPPO, 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
{BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff}, {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff},
{BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff}, {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff},
{BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff}, {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff},
@ -811,34 +557,6 @@ static const struct brcms_sromvar pci_sromvars[] = {
}; };
static const struct brcms_sromvar perpath_pci_sromvars[] = { static const struct brcms_sromvar perpath_pci_sromvars[] = {
{BRCMS_SROM_MAXP2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
{BRCMS_SROM_ITT2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
{BRCMS_SROM_ITT5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
{BRCMS_SROM_PA2GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
{BRCMS_SROM_PA2GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
{BRCMS_SROM_PA2GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
{BRCMS_SROM_PA2GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
{BRCMS_SROM_MAXP5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
{BRCMS_SROM_MAXP5GHA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
{BRCMS_SROM_MAXP5GLA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
{BRCMS_SROM_PA5GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
{BRCMS_SROM_PA5GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
{BRCMS_SROM_PA5GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
{BRCMS_SROM_PA5GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
{BRCMS_SROM_PA5GLW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
{BRCMS_SROM_PA5GLW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1,
0xffff},
{BRCMS_SROM_PA5GLW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2,
0xffff},
{BRCMS_SROM_PA5GLW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3,
0xffff},
{BRCMS_SROM_PA5GHW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
{BRCMS_SROM_PA5GHW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1,
0xffff},
{BRCMS_SROM_PA5GHW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2,
0xffff},
{BRCMS_SROM_PA5GHW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3,
0xffff},
{BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff}, {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
{BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
{BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
@ -868,24 +586,17 @@ static const struct brcms_sromvar perpath_pci_sromvars[] = {
* shared between devices. */ * shared between devices. */
static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE]; static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
static u16 __iomem * static u8 __iomem *
srom_window_address(struct si_pub *sih, u8 __iomem *curmap) srom_window_address(struct si_pub *sih, u8 __iomem *curmap)
{ {
if (sih->ccrev < 32) if (sih->ccrev < 32)
return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET); return curmap + PCI_BAR0_SPROM_OFFSET;
if (sih->cccaps & CC_CAP_SROM) if (sih->cccaps & CC_CAP_SROM)
return (u16 __iomem *) return curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP;
(curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP);
return NULL; return NULL;
} }
/* Parse SROM and create name=value pairs. 'srom' points to
* the SROM word array. 'off' specifies the offset of the
* first word 'srom' points to, which should be either 0 or
* SROM3_SWRG_OFF (full SROM or software region).
*/
static uint mask_shift(u16 mask) static uint mask_shift(u16 mask)
{ {
uint i; uint i;
@ -906,18 +617,16 @@ static uint mask_width(u16 mask)
return 0; return 0;
} }
static inline void ltoh16_buf(u16 *buf, unsigned int size) static inline void le16_to_cpu_buf(u16 *buf, uint nwords)
{ {
size /= 2; while (nwords--)
while (size--) *(buf + nwords) = le16_to_cpu(*(__le16 *)(buf + nwords));
*(buf + size) = le16_to_cpu(*(__le16 *)(buf + size));
} }
static inline void htol16_buf(u16 *buf, unsigned int size) static inline void cpu_to_le16_buf(u16 *buf, uint nwords)
{ {
size /= 2; while (nwords--)
while (size--) *(__le16 *)(buf + nwords) = cpu_to_le16(*(buf + nwords));
*(__le16 *)(buf + size) = cpu_to_le16(*(buf + size));
} }
/* /*
@ -929,11 +638,14 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
struct brcms_srom_list_head *entry; struct brcms_srom_list_head *entry;
enum brcms_srom_id id; enum brcms_srom_id id;
u16 w; u16 w;
u32 val; u32 val = 0;
const struct brcms_sromvar *srv; const struct brcms_sromvar *srv;
uint width; uint width;
uint flags; uint flags;
u32 sr = (1 << sromrev); u32 sr = (1 << sromrev);
uint p;
uint pb = SROM8_PATH0;
const uint psz = SROM8_PATH1 - SROM8_PATH0;
/* first store the srom revision */ /* first store the srom revision */
entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL);
@ -1031,47 +743,34 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
list_add(&entry->var_list, var_list); list_add(&entry->var_list, var_list);
} }
if (sromrev >= 4) { for (p = 0; p < MAX_PATH_SROM; p++) {
/* Do per-path variables */ for (srv = perpath_pci_sromvars;
uint p, pb, psz; srv->varid != BRCMS_SROM_NULL; srv++) {
if ((srv->revmask & sr) == 0)
continue;
if (sromrev >= 8) { if (srv->flags & SRFL_NOVAR)
pb = SROM8_PATH0; continue;
psz = SROM8_PATH1 - SROM8_PATH0;
} else { w = srom[pb + srv->off];
pb = SROM4_PATH0; val = (w & srv->mask) >> mask_shift(srv->mask);
psz = SROM4_PATH1 - SROM4_PATH0; width = mask_width(srv->mask);
}
/* Cheating: no per-path var is more than
for (p = 0; p < MAX_PATH_SROM; p++) { * 1 word */
for (srv = perpath_pci_sromvars; if ((srv->flags & SRFL_NOFFS)
srv->varid != BRCMS_SROM_NULL; srv++) { && ((int)val == (1 << width) - 1))
if ((srv->revmask & sr) == 0) continue;
continue;
entry =
if (srv->flags & SRFL_NOVAR) kzalloc(sizeof(struct brcms_srom_list_head),
continue; GFP_KERNEL);
entry->varid = srv->varid+p;
w = srom[pb + srv->off]; entry->var_type = BRCMS_SROM_UNUMBER;
val = (w & srv->mask) >> mask_shift(srv->mask); entry->uval = val;
width = mask_width(srv->mask); list_add(&entry->var_list, var_list);
/* Cheating: no per-path var is more than
* 1 word */
if ((srv->flags & SRFL_NOFFS)
&& ((int)val == (1 << width) - 1))
continue;
entry =
kzalloc(sizeof(struct brcms_srom_list_head),
GFP_KERNEL);
entry->varid = srv->varid+p;
entry->var_type = BRCMS_SROM_UNUMBER;
entry->uval = val;
list_add(&entry->var_list, var_list);
}
pb += psz;
} }
pb += psz;
} }
} }
@ -1080,41 +779,38 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
* Return 0 on success, nonzero on error. * Return 0 on success, nonzero on error.
*/ */
static int static int
sprom_read_pci(struct si_pub *sih, u16 __iomem *sprom, uint wordoff, sprom_read_pci(struct si_pub *sih, u8 __iomem *sprom, uint wordoff,
u16 *buf, uint nwords, bool check_crc) u16 *buf, uint nwords, bool check_crc)
{ {
int err = 0; int err = 0;
uint i; uint i;
u8 *bbuf = (u8 *)buf; /* byte buffer */
uint nbytes = nwords << 1;
/* read the sprom */ /* read the sprom in bytes */
for (i = 0; i < nwords; i++) for (i = 0; i < nbytes; i++)
buf[i] = R_REG(&sprom[wordoff + i]); bbuf[i] = readb(sprom+i);
if (check_crc) { if (buf[0] == 0xffff)
/*
if (buf[0] == 0xffff) * The hardware thinks that an srom that starts with
/* * 0xffff is blank, regardless of the rest of the
* The hardware thinks that an srom that starts with * content, so declare it bad.
* 0xffff is blank, regardless of the rest of the */
* content, so declare it bad. return -ENODATA;
*/
return -ENODATA;
/* fixup the endianness so crc8 will pass */
htol16_buf(buf, nwords * 2);
if (crc8(brcms_srom_crc8_table, (u8 *) buf, nwords * 2,
CRC8_INIT_VALUE) !=
CRC8_GOOD_VALUE(brcms_srom_crc8_table))
/* DBG only pci always read srom4 first, then srom8/9 */
err = -EIO;
if (check_crc &&
crc8(brcms_srom_crc8_table, bbuf, nbytes, CRC8_INIT_VALUE) !=
CRC8_GOOD_VALUE(brcms_srom_crc8_table))
err = -EIO;
else
/* now correct the endianness of the byte array */ /* now correct the endianness of the byte array */
ltoh16_buf(buf, nwords * 2); le16_to_cpu_buf(buf, nwords);
}
return err; return err;
} }
static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz) static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords)
{ {
u8 *otp; u8 *otp;
uint sz = OTP_SZ_MAX / 2; /* size in words */ uint sz = OTP_SZ_MAX / 2; /* size in words */
@ -1126,7 +822,8 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz); err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
memcpy(buf, otp, bufsz); sz = min_t(uint, sz, nwords);
memcpy(buf, otp, sz * 2);
kfree(otp); kfree(otp);
@ -1139,13 +836,13 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
return -ENODATA; return -ENODATA;
/* fixup the endianness so crc8 will pass */ /* fixup the endianness so crc8 will pass */
htol16_buf(buf, bufsz); cpu_to_le16_buf(buf, sz);
if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2, if (crc8(brcms_srom_crc8_table, (u8 *) buf, sz * 2,
CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table)) CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table))
err = -EIO; err = -EIO;
else
/* now correct the endianness of the byte array */ /* now correct the endianness of the byte array */
ltoh16_buf(buf, bufsz); le16_to_cpu_buf(buf, sz);
return err; return err;
} }
@ -1157,7 +854,7 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap) static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
{ {
u16 *srom; u16 *srom;
u16 __iomem *sromwindow; u8 __iomem *sromwindow;
u8 sromrev = 0; u8 sromrev = 0;
u32 sr; u32 sr;
int err = 0; int err = 0;
@ -1173,29 +870,16 @@ static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY); crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
if (ai_is_sprom_available(sih)) { if (ai_is_sprom_available(sih)) {
err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS, err = sprom_read_pci(sih, sromwindow, 0, srom,
true); SROM4_WORDS, true);
if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || if (err == 0)
(((sih->buscoretype == PCIE_CORE_ID) /* srom read and passed crc */
&& (sih->buscorerev >= 6))
|| ((sih->buscoretype == PCI_CORE_ID)
&& (sih->buscorerev >= 0xe)))) {
/* sromrev >= 4, read more */
err = sprom_read_pci(sih, sromwindow, 0, srom,
SROM4_WORDS, true);
sromrev = srom[SROM4_CRCREV] & 0xff;
} else if (err == 0) {
/* srom is good and is rev < 4 */
/* top word of sprom contains version and crc8 */ /* top word of sprom contains version and crc8 */
sromrev = srom[SROM_CRCREV] & 0xff; sromrev = srom[SROM4_CRCREV] & 0xff;
/* bcm4401 sroms misprogrammed */
if (sromrev == 0x10)
sromrev = 1;
}
} else { } else {
/* Use OTP if SPROM not available */ /* Use OTP if SPROM not available */
err = otp_read_pci(sih, srom, SROM_MAX); err = otp_read_pci(sih, srom, SROM4_WORDS);
if (err == 0) if (err == 0)
/* OTP only contain SROM rev8/rev9 for now */ /* OTP only contain SROM rev8/rev9 for now */
sromrev = srom[SROM4_CRCREV] & 0xff; sromrev = srom[SROM4_CRCREV] & 0xff;
@ -1208,10 +892,9 @@ static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
sr = 1 << sromrev; sr = 1 << sromrev;
/* /*
* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, * srom version check: Current valid versions: 8, 9
* 9
*/ */
if ((sr & 0x33e) == 0) { if ((sr & 0x300) == 0) {
err = -EINVAL; err = -EINVAL;
goto errout; goto errout;
} }

View File

@ -26,9 +26,4 @@ extern void srom_free_vars(struct si_pub *sih);
extern int srom_read(struct si_pub *sih, uint bus, void *curmap, extern int srom_read(struct si_pub *sih, uint bus, void *curmap,
uint byteoff, uint nbytes, u16 *buf, bool check_crc); uint byteoff, uint nbytes, u16 *buf, bool check_crc);
/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP
* and extract from it into name=value pairs
*/
extern int srom_parsecis(u8 **pcis, uint ciscnt,
char **vars, uint *count);
#endif /* _BRCM_SROM_H_ */ #endif /* _BRCM_SROM_H_ */

View File

@ -16,6 +16,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/module.h> #include <linux/module.h>
#include <brcmu_utils.h> #include <brcmu_utils.h>
MODULE_AUTHOR("Broadcom Corporation"); MODULE_AUTHOR("Broadcom Corporation");
@ -40,74 +41,20 @@ EXPORT_SYMBOL(brcmu_pkt_buf_get_skb);
/* Free the driver packet. Free the tag if present */ /* Free the driver packet. Free the tag if present */
void brcmu_pkt_buf_free_skb(struct sk_buff *skb) void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
{ {
struct sk_buff *nskb; WARN_ON(skb->next);
int nest = 0; if (skb->destructor)
/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
/* perversion: we use skb->next to chain multi-skb packets */ * destructor exists
while (skb) { */
nskb = skb->next; dev_kfree_skb_any(skb);
skb->next = NULL; else
/* can free immediately (even in_irq()) if destructor
if (skb->destructor) * does not exist
/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if */
* destructor exists dev_kfree_skb(skb);
*/
dev_kfree_skb_any(skb);
else
/* can free immediately (even in_irq()) if destructor
* does not exist
*/
dev_kfree_skb(skb);
nest++;
skb = nskb;
}
} }
EXPORT_SYMBOL(brcmu_pkt_buf_free_skb); EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
/* copy a buffer into a pkt buffer chain */
uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len,
unsigned char *buf)
{
uint n, ret = 0;
/* skip 'offset' bytes */
for (; p && offset; p = p->next) {
if (offset < (uint) (p->len))
break;
offset -= p->len;
}
if (!p)
return 0;
/* copy the data */
for (; p && len; p = p->next) {
n = min((uint) (p->len) - offset, (uint) len);
memcpy(p->data + offset, buf, n);
buf += n;
len -= n;
ret += n;
offset = 0;
}
return ret;
}
EXPORT_SYMBOL(brcmu_pktfrombuf);
/* return total length of buffer chain */
uint brcmu_pkttotlen(struct sk_buff *p)
{
uint total;
total = 0;
for (; p; p = p->next)
total += p->len;
return total;
}
EXPORT_SYMBOL(brcmu_pkttotlen);
/* /*
* osl multiple-precedence packet queue * osl multiple-precedence packet queue
* hi_prec is always >= the number of the highest non-empty precedence * hi_prec is always >= the number of the highest non-empty precedence
@ -115,21 +62,13 @@ EXPORT_SYMBOL(brcmu_pkttotlen);
struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
struct sk_buff *p) struct sk_buff *p)
{ {
struct pktq_prec *q; struct sk_buff_head *q;
if (pktq_full(pq) || pktq_pfull(pq, prec)) if (pktq_full(pq) || pktq_pfull(pq, prec))
return NULL; return NULL;
q = &pq->q[prec]; q = &pq->q[prec].skblist;
skb_queue_tail(q, p);
if (q->head)
q->tail->prev = p;
else
q->head = p;
q->tail = p;
q->len++;
pq->len++; pq->len++;
if (pq->hi_prec < prec) if (pq->hi_prec < prec)
@ -142,20 +81,13 @@ EXPORT_SYMBOL(brcmu_pktq_penq);
struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec, struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
struct sk_buff *p) struct sk_buff *p)
{ {
struct pktq_prec *q; struct sk_buff_head *q;
if (pktq_full(pq) || pktq_pfull(pq, prec)) if (pktq_full(pq) || pktq_pfull(pq, prec))
return NULL; return NULL;
q = &pq->q[prec]; q = &pq->q[prec].skblist;
skb_queue_head(q, p);
if (q->head == NULL)
q->tail = p;
p->prev = q->head;
q->head = p;
q->len++;
pq->len++; pq->len++;
if (pq->hi_prec < prec) if (pq->hi_prec < prec)
@ -167,53 +99,30 @@ EXPORT_SYMBOL(brcmu_pktq_penq_head);
struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec) struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec)
{ {
struct pktq_prec *q; struct sk_buff_head *q;
struct sk_buff *p; struct sk_buff *p;
q = &pq->q[prec]; q = &pq->q[prec].skblist;
p = skb_dequeue(q);
p = q->head;
if (p == NULL) if (p == NULL)
return NULL; return NULL;
q->head = p->prev;
if (q->head == NULL)
q->tail = NULL;
q->len--;
pq->len--; pq->len--;
p->prev = NULL;
return p; return p;
} }
EXPORT_SYMBOL(brcmu_pktq_pdeq); EXPORT_SYMBOL(brcmu_pktq_pdeq);
struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec) struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec)
{ {
struct pktq_prec *q; struct sk_buff_head *q;
struct sk_buff *p, *prev; struct sk_buff *p;
q = &pq->q[prec]; q = &pq->q[prec].skblist;
p = skb_dequeue_tail(q);
p = q->head;
if (p == NULL) if (p == NULL)
return NULL; return NULL;
for (prev = NULL; p != q->tail; p = p->prev)
prev = p;
if (prev)
prev->prev = NULL;
else
q->head = NULL;
q->tail = prev;
q->len--;
pq->len--; pq->len--;
return p; return p;
} }
EXPORT_SYMBOL(brcmu_pktq_pdeq_tail); EXPORT_SYMBOL(brcmu_pktq_pdeq_tail);
@ -222,31 +131,17 @@ void
brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir, brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
bool (*fn)(struct sk_buff *, void *), void *arg) bool (*fn)(struct sk_buff *, void *), void *arg)
{ {
struct pktq_prec *q; struct sk_buff_head *q;
struct sk_buff *p, *prev = NULL; struct sk_buff *p, *next;
q = &pq->q[prec]; q = &pq->q[prec].skblist;
p = q->head; skb_queue_walk_safe(q, p, next) {
while (p) {
if (fn == NULL || (*fn) (p, arg)) { if (fn == NULL || (*fn) (p, arg)) {
bool head = (p == q->head); skb_unlink(p, q);
if (head)
q->head = p->prev;
else
prev->prev = p->prev;
p->prev = NULL;
brcmu_pkt_buf_free_skb(p); brcmu_pkt_buf_free_skb(p);
q->len--;
pq->len--; pq->len--;
p = (head ? q->head : prev->prev);
} else {
prev = p;
p = p->prev;
} }
} }
if (q->head == NULL)
q->tail = NULL;
} }
EXPORT_SYMBOL(brcmu_pktq_pflush); EXPORT_SYMBOL(brcmu_pktq_pflush);
@ -271,8 +166,10 @@ void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len)
pq->max = (u16) max_len; pq->max = (u16) max_len;
for (prec = 0; prec < num_prec; prec++) for (prec = 0; prec < num_prec; prec++) {
pq->q[prec].max = pq->max; pq->q[prec].max = pq->max;
skb_queue_head_init(&pq->q[prec].skblist);
}
} }
EXPORT_SYMBOL(brcmu_pktq_init); EXPORT_SYMBOL(brcmu_pktq_init);
@ -284,13 +181,13 @@ struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out)
return NULL; return NULL;
for (prec = 0; prec < pq->hi_prec; prec++) for (prec = 0; prec < pq->hi_prec; prec++)
if (pq->q[prec].head) if (!skb_queue_empty(&pq->q[prec].skblist))
break; break;
if (prec_out) if (prec_out)
*prec_out = prec; *prec_out = prec;
return pq->q[prec].tail; return skb_peek_tail(&pq->q[prec].skblist);
} }
EXPORT_SYMBOL(brcmu_pktq_peek_tail); EXPORT_SYMBOL(brcmu_pktq_peek_tail);
@ -303,7 +200,7 @@ int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp)
for (prec = 0; prec <= pq->hi_prec; prec++) for (prec = 0; prec <= pq->hi_prec; prec++)
if (prec_bmp & (1 << prec)) if (prec_bmp & (1 << prec))
len += pq->q[prec].len; len += pq->q[prec].skblist.qlen;
return len; return len;
} }
@ -313,39 +210,32 @@ EXPORT_SYMBOL(brcmu_pktq_mlen);
struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
int *prec_out) int *prec_out)
{ {
struct pktq_prec *q; struct sk_buff_head *q;
struct sk_buff *p; struct sk_buff *p;
int prec; int prec;
if (pq->len == 0) if (pq->len == 0)
return NULL; return NULL;
while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) while ((prec = pq->hi_prec) > 0 &&
skb_queue_empty(&pq->q[prec].skblist))
pq->hi_prec--; pq->hi_prec--;
while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) while ((prec_bmp & (1 << prec)) == 0 ||
skb_queue_empty(&pq->q[prec].skblist))
if (prec-- == 0) if (prec-- == 0)
return NULL; return NULL;
q = &pq->q[prec]; q = &pq->q[prec].skblist;
p = skb_dequeue(q);
p = q->head;
if (p == NULL) if (p == NULL)
return NULL; return NULL;
q->head = p->prev; pq->len--;
if (q->head == NULL)
q->tail = NULL;
q->len--;
if (prec_out) if (prec_out)
*prec_out = prec; *prec_out = prec;
pq->len--;
p->prev = NULL;
return p; return p;
} }
EXPORT_SYMBOL(brcmu_pktq_mdeq); EXPORT_SYMBOL(brcmu_pktq_mdeq);
@ -364,23 +254,3 @@ void brcmu_prpkt(const char *msg, struct sk_buff *p0)
} }
EXPORT_SYMBOL(brcmu_prpkt); EXPORT_SYMBOL(brcmu_prpkt);
#endif /* defined(BCMDBG) */ #endif /* defined(BCMDBG) */
#if defined(BCMDBG)
/*
* print bytes formatted as hex to a string. return the resulting
* string length
*/
int brcmu_format_hex(char *str, const void *bytes, int len)
{
int i;
char *p = str;
const u8 *src = (const u8 *)bytes;
for (i = 0; i < len; i++) {
p += snprintf(p, 3, "%02X", *src);
src++;
}
return (int)(p - str);
}
EXPORT_SYMBOL(brcmu_format_hex);
#endif /* defined(BCMDBG) */

View File

@ -65,9 +65,7 @@
#define ETHER_ADDR_STR_LEN 18 #define ETHER_ADDR_STR_LEN 18
struct pktq_prec { struct pktq_prec {
struct sk_buff *head; /* first packet to dequeue */ struct sk_buff_head skblist;
struct sk_buff *tail; /* last packet to dequeue */
u16 len; /* number of queued packets */
u16 max; /* maximum number of queued packets */ u16 max; /* maximum number of queued packets */
}; };
@ -88,32 +86,32 @@ struct pktq {
static inline int pktq_plen(struct pktq *pq, int prec) static inline int pktq_plen(struct pktq *pq, int prec)
{ {
return pq->q[prec].len; return pq->q[prec].skblist.qlen;
} }
static inline int pktq_pavail(struct pktq *pq, int prec) static inline int pktq_pavail(struct pktq *pq, int prec)
{ {
return pq->q[prec].max - pq->q[prec].len; return pq->q[prec].max - pq->q[prec].skblist.qlen;
} }
static inline bool pktq_pfull(struct pktq *pq, int prec) static inline bool pktq_pfull(struct pktq *pq, int prec)
{ {
return pq->q[prec].len >= pq->q[prec].max; return pq->q[prec].skblist.qlen >= pq->q[prec].max;
} }
static inline bool pktq_pempty(struct pktq *pq, int prec) static inline bool pktq_pempty(struct pktq *pq, int prec)
{ {
return pq->q[prec].len == 0; return skb_queue_empty(&pq->q[prec].skblist);
} }
static inline struct sk_buff *pktq_ppeek(struct pktq *pq, int prec) static inline struct sk_buff *pktq_ppeek(struct pktq *pq, int prec)
{ {
return pq->q[prec].head; return skb_peek(&pq->q[prec].skblist);
} }
static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec) static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec)
{ {
return pq->q[prec].tail; return skb_peek_tail(&pq->q[prec].skblist);
} }
extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
@ -172,24 +170,16 @@ extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
bool (*fn)(struct sk_buff *, void *), void *arg); bool (*fn)(struct sk_buff *, void *), void *arg);
/* externs */ /* externs */
/* packet */
extern uint brcmu_pktfrombuf(struct sk_buff *p,
uint offset, int len, unsigned char *buf);
extern uint brcmu_pkttotlen(struct sk_buff *p);
/* ip address */ /* ip address */
struct ipv4_addr; struct ipv4_addr;
/* externs */
/* format/print */
#ifdef BCMDBG #ifdef BCMDBG
extern void brcmu_prpkt(const char *msg, struct sk_buff *p0); extern void brcmu_prpkt(const char *msg, struct sk_buff *p0);
#else #else
#define brcmu_prpkt(a, b) #define brcmu_prpkt(a, b)
#endif /* BCMDBG */ #endif /* BCMDBG */
/* externs */
/* format/print */
#if defined(BCMDBG)
extern int brcmu_format_hex(char *str, const void *bytes, int len);
#endif
#endif /* _BRCMU_UTILS_H_ */ #endif /* _BRCMU_UTILS_H_ */

View File

@ -62,7 +62,6 @@
#define WL_RADIO_SW_DISABLE (1<<0) #define WL_RADIO_SW_DISABLE (1<<0)
#define WL_RADIO_HW_DISABLE (1<<1) #define WL_RADIO_HW_DISABLE (1<<1)
#define WL_RADIO_MPC_DISABLE (1<<2)
/* some countries don't support any channel */ /* some countries don't support any channel */
#define WL_RADIO_COUNTRY_DISABLE (1<<3) #define WL_RADIO_COUNTRY_DISABLE (1<<3)

View File

@ -77,8 +77,9 @@
#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ #define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */
#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ #define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */
#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ #define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */
/* Default component, in ai chips it maps all unused address ranges */ #define DEF_AI_COMP 0xfff /* Default component, in ai chips it
#define DEF_AI_COMP 0xfff * maps all unused address ranges
*/
/* Common core control flags */ /* Common core control flags */
#define SICF_BIST_EN 0x8000 #define SICF_BIST_EN 0x8000
@ -87,4 +88,11 @@
#define SICF_FGC 0x0002 #define SICF_FGC 0x0002
#define SICF_CLOCK_EN 0x0001 #define SICF_CLOCK_EN 0x0001
/* Common core status flags */
#define SISF_BIST_DONE 0x8000
#define SISF_BIST_ERROR 0x4000
#define SISF_GATED_CLK 0x2000
#define SISF_DMA64 0x1000
#define SISF_CORE_BITS 0x0fff
#endif /* _BRCM_SOC_H */ #endif /* _BRCM_SOC_H */

View File

@ -131,6 +131,14 @@ static struct ieee80211_rate ipw2200_rates[] = {
#define ipw2200_bg_rates (ipw2200_rates + 0) #define ipw2200_bg_rates (ipw2200_rates + 0)
#define ipw2200_num_bg_rates 12 #define ipw2200_num_bg_rates 12
/* Ugly macro to convert literal channel numbers into their mhz equivalents
* There are certianly some conditions that will break this (like feeding it '30')
* but they shouldn't arise since nothing talks on channel 30. */
#define ieee80211chan2mhz(x) \
(((x) <= 14) ? \
(((x) == 14) ? 2484 : ((x) * 5) + 2407) : \
((x) + 1000) * 5)
#ifdef CONFIG_IPW2200_QOS #ifdef CONFIG_IPW2200_QOS
static int qos_enable = 0; static int qos_enable = 0;
static int qos_burst_enable = 0; static int qos_burst_enable = 0;

View File

@ -66,16 +66,8 @@ extern u32 libipw_debug_level;
do { if (libipw_debug_level & (level)) \ do { if (libipw_debug_level & (level)) \
printk(KERN_DEBUG "libipw: %c %s " fmt, \ printk(KERN_DEBUG "libipw: %c %s " fmt, \
in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
static inline bool libipw_ratelimit_debug(u32 level)
{
return (libipw_debug_level & level) && net_ratelimit();
}
#else #else
#define LIBIPW_DEBUG(level, fmt, args...) do {} while (0) #define LIBIPW_DEBUG(level, fmt, args...) do {} while (0)
static inline bool libipw_ratelimit_debug(u32 level)
{
return false;
}
#endif /* CONFIG_LIBIPW_DEBUG */ #endif /* CONFIG_LIBIPW_DEBUG */
/* /*

View File

@ -1,6 +1,6 @@
# WIFI # WIFI
obj-$(CONFIG_IWLWIFI) += iwlwifi.o obj-$(CONFIG_IWLWIFI) += iwlwifi.o
iwlwifi-objs := iwl-agn.o iwl-agn-rs.o iwlwifi-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o
iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o
iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o

View File

@ -270,11 +270,6 @@ struct iwl_cfg iwl2000_2bgn_cfg = {
.ht_params = &iwl2000_ht_params, .ht_params = &iwl2000_ht_params,
}; };
struct iwl_cfg iwl2000_2bg_cfg = {
.name = "2000 Series 2x2 BG",
IWL_DEVICE_2000,
};
struct iwl_cfg iwl2000_2bgn_d_cfg = { struct iwl_cfg iwl2000_2bgn_d_cfg = {
.name = "2000D Series 2x2 BGN", .name = "2000D Series 2x2 BGN",
IWL_DEVICE_2000, IWL_DEVICE_2000,
@ -304,11 +299,6 @@ struct iwl_cfg iwl2030_2bgn_cfg = {
.ht_params = &iwl2000_ht_params, .ht_params = &iwl2000_ht_params,
}; };
struct iwl_cfg iwl2030_2bg_cfg = {
.name = "2000 Series 2x2 BG/BT",
IWL_DEVICE_2030,
};
#define IWL_DEVICE_105 \ #define IWL_DEVICE_105 \
.fw_name_pre = IWL105_FW_PRE, \ .fw_name_pre = IWL105_FW_PRE, \
.ucode_api_max = IWL105_UCODE_API_MAX, \ .ucode_api_max = IWL105_UCODE_API_MAX, \
@ -326,11 +316,6 @@ struct iwl_cfg iwl2030_2bg_cfg = {
.rx_with_siso_diversity = true, \ .rx_with_siso_diversity = true, \
.iq_invert = true \ .iq_invert = true \
struct iwl_cfg iwl105_bg_cfg = {
.name = "105 Series 1x1 BG",
IWL_DEVICE_105,
};
struct iwl_cfg iwl105_bgn_cfg = { struct iwl_cfg iwl105_bgn_cfg = {
.name = "105 Series 1x1 BGN", .name = "105 Series 1x1 BGN",
IWL_DEVICE_105, IWL_DEVICE_105,
@ -361,11 +346,6 @@ struct iwl_cfg iwl105_bgn_d_cfg = {
.rx_with_siso_diversity = true, \ .rx_with_siso_diversity = true, \
.iq_invert = true \ .iq_invert = true \
struct iwl_cfg iwl135_bg_cfg = {
.name = "135 Series 1x1 BG/BT",
IWL_DEVICE_135,
};
struct iwl_cfg iwl135_bgn_cfg = { struct iwl_cfg iwl135_bgn_cfg = {
.name = "135 Series 1x1 BGN/BT", .name = "135 Series 1x1 BGN/BT",
IWL_DEVICE_135, IWL_DEVICE_135,

View File

@ -439,16 +439,6 @@ struct iwl_cfg iwl6035_2agn_cfg = {
.ht_params = &iwl6000_ht_params, .ht_params = &iwl6000_ht_params,
}; };
struct iwl_cfg iwl6035_2abg_cfg = {
.name = "6035 Series 2x2 ABG/BT",
IWL_DEVICE_6030,
};
struct iwl_cfg iwl6035_2bg_cfg = {
.name = "6035 Series 2x2 BG/BT",
IWL_DEVICE_6030,
};
struct iwl_cfg iwl1030_bgn_cfg = { struct iwl_cfg iwl1030_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN", .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
IWL_DEVICE_6030, IWL_DEVICE_6030,

View File

@ -827,6 +827,7 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
case IEEE80211_SMPS_STATIC: case IEEE80211_SMPS_STATIC:
case IEEE80211_SMPS_DYNAMIC: case IEEE80211_SMPS_DYNAMIC:
return IWL_NUM_IDLE_CHAINS_SINGLE; return IWL_NUM_IDLE_CHAINS_SINGLE;
case IEEE80211_SMPS_AUTOMATIC:
case IEEE80211_SMPS_OFF: case IEEE80211_SMPS_OFF:
return active_cnt; return active_cnt;
default: default:
@ -983,3 +984,360 @@ void iwlagn_remove_notification(struct iwl_priv *priv,
list_del(&wait_entry->list); list_del(&wait_entry->list);
spin_unlock_bh(&priv->notif_wait_lock); spin_unlock_bh(&priv->notif_wait_lock);
} }
#ifdef CONFIG_PM_SLEEP
static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
{
int i;
for (i = 0; i < IWLAGN_P1K_SIZE; i++)
out[i] = cpu_to_le16(p1k[i]);
}
struct wowlan_key_data {
struct iwl_rxon_context *ctx;
struct iwlagn_wowlan_rsc_tsc_params_cmd *rsc_tsc;
struct iwlagn_wowlan_tkip_params_cmd *tkip;
const u8 *bssid;
bool error, use_rsc_tsc, use_tkip;
};
static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
void *_data)
{
struct iwl_priv *priv = hw->priv;
struct wowlan_key_data *data = _data;
struct iwl_rxon_context *ctx = data->ctx;
struct aes_sc *aes_sc, *aes_tx_sc = NULL;
struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;
struct iwlagn_p1k_cache *rx_p1ks;
u8 *rx_mic_key;
struct ieee80211_key_seq seq;
u32 cur_rx_iv32 = 0;
u16 p1k[IWLAGN_P1K_SIZE];
int ret, i;
mutex_lock(&priv->shrd->mutex);
if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
!sta && !ctx->key_mapping_keys)
ret = iwl_set_default_wep_key(priv, ctx, key);
else
ret = iwl_set_dynamic_key(priv, ctx, key, sta);
if (ret) {
IWL_ERR(priv, "Error setting key during suspend!\n");
data->error = true;
}
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
if (sta) {
tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
rx_p1ks = data->tkip->rx_uni;
ieee80211_get_key_tx_seq(key, &seq);
tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16);
tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32);
ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
iwlagn_convert_p1k(p1k, data->tkip->tx.p1k);
memcpy(data->tkip->mic_keys.tx,
&key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
IWLAGN_MIC_KEY_SIZE);
rx_mic_key = data->tkip->mic_keys.rx_unicast;
} else {
tkip_sc =
data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc;
rx_p1ks = data->tkip->rx_multi;
rx_mic_key = data->tkip->mic_keys.rx_mcast;
}
/*
* For non-QoS this relies on the fact that both the uCode and
* mac80211 use TID 0 (as they need to to avoid replay attacks)
* for checking the IV in the frames.
*/
for (i = 0; i < IWLAGN_NUM_RSC; i++) {
ieee80211_get_key_rx_seq(key, i, &seq);
tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16);
tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32);
/* wrapping isn't allowed, AP must rekey */
if (seq.tkip.iv32 > cur_rx_iv32)
cur_rx_iv32 = seq.tkip.iv32;
}
ieee80211_get_tkip_rx_p1k(key, data->bssid, cur_rx_iv32, p1k);
iwlagn_convert_p1k(p1k, rx_p1ks[0].p1k);
ieee80211_get_tkip_rx_p1k(key, data->bssid,
cur_rx_iv32 + 1, p1k);
iwlagn_convert_p1k(p1k, rx_p1ks[1].p1k);
memcpy(rx_mic_key,
&key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
IWLAGN_MIC_KEY_SIZE);
data->use_tkip = true;
data->use_rsc_tsc = true;
break;
case WLAN_CIPHER_SUITE_CCMP:
if (sta) {
u8 *pn = seq.ccmp.pn;
aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
ieee80211_get_key_tx_seq(key, &seq);
aes_tx_sc->pn = cpu_to_le64(
(u64)pn[5] |
((u64)pn[4] << 8) |
((u64)pn[3] << 16) |
((u64)pn[2] << 24) |
((u64)pn[1] << 32) |
((u64)pn[0] << 40));
} else
aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
/*
* For non-QoS this relies on the fact that both the uCode and
* mac80211 use TID 0 for checking the IV in the frames.
*/
for (i = 0; i < IWLAGN_NUM_RSC; i++) {
u8 *pn = seq.ccmp.pn;
ieee80211_get_key_rx_seq(key, i, &seq);
aes_sc->pn = cpu_to_le64(
(u64)pn[5] |
((u64)pn[4] << 8) |
((u64)pn[3] << 16) |
((u64)pn[2] << 24) |
((u64)pn[1] << 32) |
((u64)pn[0] << 40));
}
data->use_rsc_tsc = true;
break;
}
mutex_unlock(&priv->shrd->mutex);
}
int iwlagn_send_patterns(struct iwl_priv *priv,
struct cfg80211_wowlan *wowlan)
{
struct iwlagn_wowlan_patterns_cmd *pattern_cmd;
struct iwl_host_cmd cmd = {
.id = REPLY_WOWLAN_PATTERNS,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
.flags = CMD_SYNC,
};
int i, err;
if (!wowlan->n_patterns)
return 0;
cmd.len[0] = sizeof(*pattern_cmd) +
wowlan->n_patterns * sizeof(struct iwlagn_wowlan_pattern);
pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);
if (!pattern_cmd)
return -ENOMEM;
pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);
for (i = 0; i < wowlan->n_patterns; i++) {
int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
memcpy(&pattern_cmd->patterns[i].mask,
wowlan->patterns[i].mask, mask_len);
memcpy(&pattern_cmd->patterns[i].pattern,
wowlan->patterns[i].pattern,
wowlan->patterns[i].pattern_len);
pattern_cmd->patterns[i].mask_size = mask_len;
pattern_cmd->patterns[i].pattern_size =
wowlan->patterns[i].pattern_len;
}
cmd.data[0] = pattern_cmd;
err = iwl_trans_send_cmd(trans(priv), &cmd);
kfree(pattern_cmd);
return err;
}
int iwlagn_suspend(struct iwl_priv *priv,
struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{
struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
struct iwl_rxon_cmd rxon;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd;
struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {};
struct iwlagn_d3_config_cmd d3_cfg_cmd = {};
struct wowlan_key_data key_data = {
.ctx = ctx,
.bssid = ctx->active.bssid_addr,
.use_rsc_tsc = false,
.tkip = &tkip_cmd,
.use_tkip = false,
};
int ret, i;
u16 seq;
key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
if (!key_data.rsc_tsc)
return -ENOMEM;
memset(&wakeup_filter_cmd, 0, sizeof(wakeup_filter_cmd));
/*
* We know the last used seqno, and the uCode expects to know that
* one, it will increment before TX.
*/
seq = le16_to_cpu(priv->last_seq_ctl) & IEEE80211_SCTL_SEQ;
wakeup_filter_cmd.non_qos_seq = cpu_to_le16(seq);
/*
* For QoS counters, we store the one to use next, so subtract 0x10
* since the uCode will add 0x10 before using the value.
*/
for (i = 0; i < 8; i++) {
seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number;
seq -= 0x10;
wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
}
if (wowlan->disconnect)
wakeup_filter_cmd.enabled |=
cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_BEACON_MISS |
IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE);
if (wowlan->magic_pkt)
wakeup_filter_cmd.enabled |=
cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_MAGIC_PACKET);
if (wowlan->gtk_rekey_failure)
wakeup_filter_cmd.enabled |=
cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
if (wowlan->eap_identity_req)
wakeup_filter_cmd.enabled |=
cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ);
if (wowlan->four_way_handshake)
wakeup_filter_cmd.enabled |=
cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
if (wowlan->n_patterns)
wakeup_filter_cmd.enabled |=
cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH);
if (wowlan->rfkill_release)
d3_cfg_cmd.wakeup_flags |=
cpu_to_le32(IWLAGN_D3_WAKEUP_RFKILL);
iwl_scan_cancel_timeout(priv, 200);
memcpy(&rxon, &ctx->active, sizeof(rxon));
iwl_trans_stop_device(trans(priv));
priv->shrd->wowlan = true;
ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
if (ret)
goto out;
/* now configure WoWLAN ucode */
ret = iwl_alive_start(priv);
if (ret)
goto out;
memcpy(&ctx->staging, &rxon, sizeof(rxon));
ret = iwlagn_commit_rxon(priv, ctx);
if (ret)
goto out;
ret = iwl_power_update_mode(priv, true);
if (ret)
goto out;
if (!iwlagn_mod_params.sw_crypto) {
/* mark all keys clear */
priv->ucode_key_table = 0;
ctx->key_mapping_keys = 0;
/*
* This needs to be unlocked due to lock ordering
* constraints. Since we're in the suspend path
* that isn't really a problem though.
*/
mutex_unlock(&priv->shrd->mutex);
ieee80211_iter_keys(priv->hw, ctx->vif,
iwlagn_wowlan_program_keys,
&key_data);
mutex_lock(&priv->shrd->mutex);
if (key_data.error) {
ret = -EIO;
goto out;
}
if (key_data.use_rsc_tsc) {
struct iwl_host_cmd rsc_tsc_cmd = {
.id = REPLY_WOWLAN_TSC_RSC_PARAMS,
.flags = CMD_SYNC,
.data[0] = key_data.rsc_tsc,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
.len[0] = sizeof(key_data.rsc_tsc),
};
ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd);
if (ret)
goto out;
}
if (key_data.use_tkip) {
ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_WOWLAN_TKIP_PARAMS,
CMD_SYNC, sizeof(tkip_cmd),
&tkip_cmd);
if (ret)
goto out;
}
if (priv->have_rekey_data) {
memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
memcpy(kek_kck_cmd.kck, priv->kck, NL80211_KCK_LEN);
kek_kck_cmd.kck_len = cpu_to_le16(NL80211_KCK_LEN);
memcpy(kek_kck_cmd.kek, priv->kek, NL80211_KEK_LEN);
kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
kek_kck_cmd.replay_ctr = priv->replay_ctr;
ret = iwl_trans_send_cmd_pdu(trans(priv),
REPLY_WOWLAN_KEK_KCK_MATERIAL,
CMD_SYNC, sizeof(kek_kck_cmd),
&kek_kck_cmd);
if (ret)
goto out;
}
}
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_D3_CONFIG, CMD_SYNC,
sizeof(d3_cfg_cmd), &d3_cfg_cmd);
if (ret)
goto out;
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER,
CMD_SYNC, sizeof(wakeup_filter_cmd),
&wakeup_filter_cmd);
if (ret)
goto out;
ret = iwlagn_send_patterns(priv, wowlan);
out:
kfree(key_data.rsc_tsc);
return ret;
}
#endif

View File

@ -1458,10 +1458,8 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
break; break;
case IWL_BT_COEX_TRAFFIC_LOAD_LOW: case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
/* avoid antenna B unless MIMO */ /* avoid antenna B unless MIMO */
valid_tx_ant =
first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2) if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2)
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; tbl->action = IWL_LEGACY_SWITCH_SISO;
break; break;
case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
@ -1636,10 +1634,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
break; break;
case IWL_BT_COEX_TRAFFIC_LOAD_LOW: case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
/* avoid antenna B unless MIMO */ /* avoid antenna B unless MIMO */
valid_tx_ant =
first_antenna(hw_params(priv).valid_tx_ant);
if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) if (tbl->action == IWL_SISO_SWITCH_ANTENNA2)
tbl->action = IWL_SISO_SWITCH_ANTENNA1; tbl->action = IWL_SISO_SWITCH_MIMO2_AB;
break; break;
case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:

View File

@ -800,7 +800,8 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
ctx->active.bssid_addr)) ctx->active.bssid_addr))
continue; continue;
ctx->last_tx_rejected = false; ctx->last_tx_rejected = false;
iwl_trans_wake_any_queue(trans(priv), ctx->ctxid); iwl_trans_wake_any_queue(trans(priv), ctx->ctxid,
"channel got active");
} }
} }
@ -1032,6 +1033,50 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
return 0; return 0;
} }
static int iwlagn_rx_noa_notification(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_wipan_noa_data *new_data, *old_data;
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->u.raw;
/* no condition -- we're in softirq */
old_data = rcu_dereference_protected(priv->noa_data, true);
if (noa_notif->noa_active) {
u32 len = le16_to_cpu(noa_notif->noa_attribute.length);
u32 copylen = len;
/* EID, len, OUI, subtype */
len += 1 + 1 + 3 + 1;
/* P2P id, P2P length */
len += 1 + 2;
copylen += 1 + 2;
new_data = kmalloc(sizeof(*new_data) + len, GFP_ATOMIC);
if (new_data) {
new_data->length = len;
new_data->data[0] = WLAN_EID_VENDOR_SPECIFIC;
new_data->data[1] = len - 2; /* not counting EID, len */
new_data->data[2] = (WLAN_OUI_WFA >> 16) & 0xff;
new_data->data[3] = (WLAN_OUI_WFA >> 8) & 0xff;
new_data->data[4] = (WLAN_OUI_WFA >> 0) & 0xff;
new_data->data[5] = WLAN_OUI_TYPE_WFA_P2P;
memcpy(&new_data->data[6], &noa_notif->noa_attribute,
copylen);
}
} else
new_data = NULL;
rcu_assign_pointer(priv->noa_data, new_data);
if (old_data)
kfree_rcu(old_data, rcu_head);
return 0;
}
/** /**
* iwl_setup_rx_handlers - Initialize Rx handler callbacks * iwl_setup_rx_handlers - Initialize Rx handler callbacks
* *
@ -1055,6 +1100,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif; handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif;
handlers[REPLY_ADD_STA] = iwl_add_sta_callback; handlers[REPLY_ADD_STA] = iwl_add_sta_callback;
handlers[REPLY_WIPAN_NOA_NOTIFICATION] = iwlagn_rx_noa_notification;
/* /*
* The same handler is used for both the REPLY to a discrete * The same handler is used for both the REPLY to a discrete
* statistics request from the host as well as for the periodic * statistics request from the host as well as for the periodic

View File

@ -45,7 +45,8 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
send->filter_flags = old_filter; send->filter_flags = old_filter;
if (ret) if (ret)
IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret); IWL_DEBUG_QUIET_RFKILL(priv,
"Error clearing ASSOC_MSK on BSS (%d)\n", ret);
return ret; return ret;
} }
@ -116,7 +117,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
if (ctx->ht.enabled) if (ctx->ht.enabled)
ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", IWL_DEBUG_INFO(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
ctx->qos_data.qos_active, ctx->qos_data.qos_active,
ctx->qos_data.def_qos_parm.qos_flags); ctx->qos_data.def_qos_parm.qos_flags);
@ -124,7 +125,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
sizeof(struct iwl_qosparam_cmd), sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm); &ctx->qos_data.def_qos_parm);
if (ret) if (ret)
IWL_ERR(priv, "Failed to update QoS\n"); IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n");
} }
static int iwlagn_update_beacon(struct iwl_priv *priv, static int iwlagn_update_beacon(struct iwl_priv *priv,
@ -541,6 +542,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->shrd->mutex);
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
goto out;
if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) { if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) {
IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
goto out; goto out;
@ -840,7 +844,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
if (ctx->last_tx_rejected) { if (ctx->last_tx_rejected) {
ctx->last_tx_rejected = false; ctx->last_tx_rejected = false;
iwl_trans_wake_any_queue(trans(priv), iwl_trans_wake_any_queue(trans(priv),
ctx->ctxid); ctx->ctxid,
"Disassoc: flush queue");
} }
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;

View File

@ -647,7 +647,7 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
int ret; int ret;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
struct iwl_link_quality_cmd lq; struct iwl_link_quality_cmd lq;
bool active; bool active, have_lq = false;
spin_lock_irqsave(&priv->shrd->sta_lock, flags); spin_lock_irqsave(&priv->shrd->sta_lock, flags);
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
@ -657,7 +657,10 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd)); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
sta_cmd.mode = 0; sta_cmd.mode = 0;
memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq)); if (priv->stations[sta_id].lq) {
memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
have_lq = true;
}
active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE; active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
@ -679,7 +682,8 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
if (ret) if (ret)
IWL_ERR(priv, "failed to re-add STA %pM (%d)\n", IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
priv->stations[sta_id].sta.sta.addr, ret); priv->stations[sta_id].sta.sta.addr, ret);
iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true); if (have_lq)
iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
} }
int iwl_get_free_ucode_key_offset(struct iwl_priv *priv) int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
@ -825,28 +829,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
return ret; return ret;
} }
int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
struct iwl_priv *priv = hw->priv;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
int ret;
IWL_DEBUG_MAC80211(priv, "enter: received request to remove "
"station %pM\n", sta->addr);
mutex_lock(&priv->shrd->mutex);
IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
sta->addr);
ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
if (ret)
IWL_ERR(priv, "Error removing station %pM\n",
sta->addr);
mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return ret;
}
void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
u8 sta_id, struct iwl_link_quality_cmd *link_cmd) u8 sta_id, struct iwl_link_quality_cmd *link_cmd)
@ -1464,20 +1446,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
} }
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
{
unsigned long flags;
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
priv->stations[sta_id].sta.sta.modify_mask = 0;
priv->stations[sta_id].sta.sleep_tx_count = 0;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
}
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
{ {
@ -1494,36 +1463,3 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
} }
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)
{
struct iwl_priv *priv = hw->priv;
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
int sta_id;
IWL_DEBUG_MAC80211(priv, "enter\n");
switch (cmd) {
case STA_NOTIFY_SLEEP:
WARN_ON(!sta_priv->client);
sta_priv->asleep = true;
if (atomic_read(&sta_priv->pending_frames) > 0)
ieee80211_sta_block_awake(hw, sta, true);
break;
case STA_NOTIFY_AWAKE:
WARN_ON(!sta_priv->client);
if (!sta_priv->asleep)
break;
sta_priv->asleep = false;
sta_id = iwl_sta_id(sta);
if (sta_id != IWL_INVALID_STATION)
iwl_sta_modify_ps_wake(priv, sta_id);
break;
default:
break;
}
IWL_DEBUG_MAC80211(priv, "leave\n");
}

View File

@ -283,6 +283,19 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
#endif #endif
if (unlikely(ieee80211_is_probe_resp(fc))) {
struct iwl_wipan_noa_data *noa_data =
rcu_dereference(priv->noa_data);
if (noa_data &&
pskb_expand_head(skb, 0, noa_data->length,
GFP_ATOMIC) == 0) {
memcpy(skb_put(skb, noa_data->length),
noa_data->data, noa_data->length);
hdr = (struct ieee80211_hdr *)skb->data;
}
}
hdr_len = ieee80211_hdrlen(fc); hdr_len = ieee80211_hdrlen(fc);
/* For management frames use broadcast id to do not break aggregation */ /* For management frames use broadcast id to do not break aggregation */
@ -800,7 +813,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
iwl_is_associated_ctx(ctx) && ctx->vif && iwl_is_associated_ctx(ctx) && ctx->vif &&
ctx->vif->type == NL80211_IFTYPE_STATION) { ctx->vif->type == NL80211_IFTYPE_STATION) {
ctx->last_tx_rejected = true; ctx->last_tx_rejected = true;
iwl_trans_stop_queue(trans(priv), txq_id); iwl_trans_stop_queue(trans(priv), txq_id,
"Tx on passive channel");
IWL_DEBUG_TX_REPLY(priv, IWL_DEBUG_TX_REPLY(priv,
"TXQ %d status %s (0x%08x) " "TXQ %d status %s (0x%08x) "

View File

@ -31,6 +31,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/dma-mapping.h>
#include "iwl-dev.h" #include "iwl-dev.h"
#include "iwl-core.h" #include "iwl-core.h"
@ -72,51 +73,98 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS}
}; };
/******************************************************************************
*
* uCode download functions
*
******************************************************************************/
static void iwl_free_fw_desc(struct iwl_bus *bus, struct fw_desc *desc)
{
if (desc->v_addr)
dma_free_coherent(bus->dev, desc->len,
desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
desc->len = 0;
}
static void iwl_free_fw_img(struct iwl_bus *bus, struct fw_img *img)
{
iwl_free_fw_desc(bus, &img->code);
iwl_free_fw_desc(bus, &img->data);
}
void iwl_dealloc_ucode(struct iwl_trans *trans)
{
iwl_free_fw_img(bus(trans), &trans->ucode_rt);
iwl_free_fw_img(bus(trans), &trans->ucode_init);
iwl_free_fw_img(bus(trans), &trans->ucode_wowlan);
}
int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
const void *data, size_t len)
{
if (!len) {
desc->v_addr = NULL;
return -EINVAL;
}
desc->v_addr = dma_alloc_coherent(bus->dev, len,
&desc->p_addr, GFP_KERNEL);
if (!desc->v_addr)
return -ENOMEM;
desc->len = len;
memcpy(desc->v_addr, data, len);
return 0;
}
/* /*
* ucode * ucode
*/ */
static int iwlagn_load_section(struct iwl_priv *priv, const char *name, static int iwlagn_load_section(struct iwl_trans *trans, const char *name,
struct fw_desc *image, u32 dst_addr) struct fw_desc *image, u32 dst_addr)
{ {
struct iwl_bus *bus = bus(trans);
dma_addr_t phy_addr = image->p_addr; dma_addr_t phy_addr = image->p_addr;
u32 byte_cnt = image->len; u32 byte_cnt = image->len;
int ret; int ret;
priv->ucode_write_complete = 0; trans->ucode_write_complete = 0;
iwl_write_direct32(bus(priv), iwl_write_direct32(bus,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
iwl_write_direct32(bus(priv), iwl_write_direct32(bus,
FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr);
iwl_write_direct32(bus(priv), iwl_write_direct32(bus,
FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
iwl_write_direct32(bus(priv), iwl_write_direct32(bus,
FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
(iwl_get_dma_hi_addr(phy_addr) (iwl_get_dma_hi_addr(phy_addr)
<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
iwl_write_direct32(bus(priv), iwl_write_direct32(bus,
FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
iwl_write_direct32(bus(priv), iwl_write_direct32(bus,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name); IWL_DEBUG_FW(bus, "%s uCode section being loaded...\n", name);
ret = wait_event_timeout(priv->shrd->wait_command_queue, ret = wait_event_timeout(trans->shrd->wait_command_queue,
priv->ucode_write_complete, 5 * HZ); trans->ucode_write_complete, 5 * HZ);
if (!ret) { if (!ret) {
IWL_ERR(priv, "Could not load the %s uCode section\n", IWL_ERR(trans, "Could not load the %s uCode section\n",
name); name);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -124,17 +172,41 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
return 0; return 0;
} }
static int iwlagn_load_given_ucode(struct iwl_priv *priv, static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
struct fw_img *image) enum iwl_ucode_type ucode_type)
{
switch (ucode_type) {
case IWL_UCODE_INIT:
return &trans->ucode_init;
case IWL_UCODE_WOWLAN:
return &trans->ucode_wowlan;
case IWL_UCODE_REGULAR:
return &trans->ucode_rt;
case IWL_UCODE_NONE:
break;
}
return NULL;
}
static int iwlagn_load_given_ucode(struct iwl_trans *trans,
enum iwl_ucode_type ucode_type)
{ {
int ret = 0; int ret = 0;
struct fw_img *image = iwl_get_ucode_image(trans, ucode_type);
ret = iwlagn_load_section(priv, "INST", &image->code,
if (!image) {
IWL_ERR(trans, "Invalid ucode requested (%d)\n",
ucode_type);
return -EINVAL;
}
ret = iwlagn_load_section(trans, "INST", &image->code,
IWLAGN_RTC_INST_LOWER_BOUND); IWLAGN_RTC_INST_LOWER_BOUND);
if (ret) if (ret)
return ret; return ret;
return iwlagn_load_section(priv, "DATA", &image->data, return iwlagn_load_section(trans, "DATA", &image->data,
IWLAGN_RTC_DATA_LOWER_BOUND); IWLAGN_RTC_DATA_LOWER_BOUND);
} }
@ -418,7 +490,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
* using sample data 100 bytes apart. If these sample points are good, * using sample data 100 bytes apart. If these sample points are good,
* it's a pretty good bet that everything between them is good, too. * it's a pretty good bet that everything between them is good, too.
*/ */
static int iwl_verify_inst_sparse(struct iwl_priv *priv, static int iwl_verify_inst_sparse(struct iwl_bus *bus,
struct fw_desc *fw_desc) struct fw_desc *fw_desc)
{ {
__le32 *image = (__le32 *)fw_desc->v_addr; __le32 *image = (__le32 *)fw_desc->v_addr;
@ -426,15 +498,15 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv,
u32 val; u32 val;
u32 i; u32 i;
IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len);
for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
/* read data comes through single port, auto-incr addr */ /* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log /* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */ * if IWL_DL_IO is set */
iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR, iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR,
i + IWLAGN_RTC_INST_LOWER_BOUND); i + IWLAGN_RTC_INST_LOWER_BOUND);
val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); val = iwl_read32(bus, HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) if (val != le32_to_cpu(*image))
return -EIO; return -EIO;
} }
@ -442,7 +514,7 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv,
return 0; return 0;
} }
static void iwl_print_mismatch_inst(struct iwl_priv *priv, static void iwl_print_mismatch_inst(struct iwl_bus *bus,
struct fw_desc *fw_desc) struct fw_desc *fw_desc)
{ {
__le32 *image = (__le32 *)fw_desc->v_addr; __le32 *image = (__le32 *)fw_desc->v_addr;
@ -451,18 +523,18 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
u32 offs; u32 offs;
int errors = 0; int errors = 0;
IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); IWL_DEBUG_FW(bus, "ucode inst image size is %u\n", len);
iwl_write_direct32(bus(priv), HBUS_TARG_MEM_RADDR, iwl_write_direct32(bus, HBUS_TARG_MEM_RADDR,
IWLAGN_RTC_INST_LOWER_BOUND); IWLAGN_RTC_INST_LOWER_BOUND);
for (offs = 0; for (offs = 0;
offs < len && errors < 20; offs < len && errors < 20;
offs += sizeof(u32), image++) { offs += sizeof(u32), image++) {
/* read data comes through single port, auto-incr addr */ /* read data comes through single port, auto-incr addr */
val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT); val = iwl_read32(bus, HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) { if (val != le32_to_cpu(*image)) {
IWL_ERR(priv, "uCode INST section at " IWL_ERR(bus, "uCode INST section at "
"offset 0x%x, is 0x%x, s/b 0x%x\n", "offset 0x%x, is 0x%x, s/b 0x%x\n",
offs, val, le32_to_cpu(*image)); offs, val, le32_to_cpu(*image));
errors++; errors++;
@ -474,16 +546,24 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
* iwl_verify_ucode - determine which instruction image is in SRAM, * iwl_verify_ucode - determine which instruction image is in SRAM,
* and verify its contents * and verify its contents
*/ */
static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img) static int iwl_verify_ucode(struct iwl_trans *trans,
enum iwl_ucode_type ucode_type)
{ {
if (!iwl_verify_inst_sparse(priv, &img->code)) { struct fw_img *img = iwl_get_ucode_image(trans, ucode_type);
IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
if (!img) {
IWL_ERR(trans, "Invalid ucode requested (%d)\n", ucode_type);
return -EINVAL;
}
if (!iwl_verify_inst_sparse(bus(trans), &img->code)) {
IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n");
return 0; return 0;
} }
IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
iwl_print_mismatch_inst(priv, &img->code); iwl_print_mismatch_inst(bus(trans), &img->code);
return -EIO; return -EIO;
} }
@ -519,13 +599,12 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
#define UCODE_CALIB_TIMEOUT (2*HZ) #define UCODE_CALIB_TIMEOUT (2*HZ)
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
struct fw_img *image, enum iwl_ucode_type ucode_type)
enum iwlagn_ucode_type ucode_type)
{ {
struct iwl_notification_wait alive_wait; struct iwl_notification_wait alive_wait;
struct iwlagn_alive_data alive_data; struct iwlagn_alive_data alive_data;
int ret; int ret;
enum iwlagn_ucode_type old_type; enum iwl_ucode_type old_type;
ret = iwl_trans_start_device(trans(priv)); ret = iwl_trans_start_device(trans(priv));
if (ret) if (ret)
@ -537,7 +616,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
old_type = priv->ucode_type; old_type = priv->ucode_type;
priv->ucode_type = ucode_type; priv->ucode_type = ucode_type;
ret = iwlagn_load_given_ucode(priv, image); ret = iwlagn_load_given_ucode(trans(priv), ucode_type);
if (ret) { if (ret) {
priv->ucode_type = old_type; priv->ucode_type = old_type;
iwlagn_remove_notification(priv, &alive_wait); iwlagn_remove_notification(priv, &alive_wait);
@ -568,7 +647,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
* skip it for WoWLAN. * skip it for WoWLAN.
*/ */
if (ucode_type != IWL_UCODE_WOWLAN) { if (ucode_type != IWL_UCODE_WOWLAN) {
ret = iwl_verify_ucode(priv, image); ret = iwl_verify_ucode(trans(priv), ucode_type);
if (ret) { if (ret) {
priv->ucode_type = old_type; priv->ucode_type = old_type;
return ret; return ret;
@ -597,7 +676,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->shrd->mutex);
/* No init ucode required? Curious, but maybe ok */ /* No init ucode required? Curious, but maybe ok */
if (!priv->ucode_init.code.len) if (!trans(priv)->ucode_init.code.len)
return 0; return 0;
if (priv->ucode_type != IWL_UCODE_NONE) if (priv->ucode_type != IWL_UCODE_NONE)
@ -608,8 +687,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
NULL, NULL); NULL, NULL);
/* Will also start the device */ /* Will also start the device */
ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
IWL_UCODE_INIT);
if (ret) if (ret)
goto error; goto error;

File diff suppressed because it is too large Load Diff

View File

@ -65,6 +65,12 @@
#include "iwl-dev.h" #include "iwl-dev.h"
struct iwlagn_ucode_capabilities {
u32 max_probe_length;
u32 standard_phy_calibration_size;
u32 flags;
};
extern struct ieee80211_ops iwlagn_hw_ops; extern struct ieee80211_ops iwlagn_hw_ops;
int iwl_reset_ict(struct iwl_trans *trans); int iwl_reset_ict(struct iwl_trans *trans);
@ -77,6 +83,15 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
hdr->data_valid = 1; hdr->data_valid = 1;
} }
void __iwl_down(struct iwl_priv *priv);
void iwl_down(struct iwl_priv *priv);
void iwlagn_prepare_restart(struct iwl_priv *priv);
/* MAC80211 */
struct ieee80211_hw *iwl_alloc_all(void);
int iwlagn_mac_setup_register(struct iwl_priv *priv,
struct iwlagn_ucode_capabilities *capa);
/* RXON */ /* RXON */
int iwlagn_set_pan_params(struct iwl_priv *priv); int iwlagn_set_pan_params(struct iwl_priv *priv);
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@ -95,8 +110,7 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
void iwlagn_send_prio_tbl(struct iwl_priv *priv); void iwlagn_send_prio_tbl(struct iwl_priv *priv);
int iwlagn_run_init_ucode(struct iwl_priv *priv); int iwlagn_run_init_ucode(struct iwl_priv *priv);
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
struct fw_img *image, enum iwl_ucode_type ucode_type);
enum iwlagn_ucode_type ucode_type);
/* lib */ /* lib */
int iwlagn_send_tx_power(struct iwl_priv *priv); int iwlagn_send_tx_power(struct iwl_priv *priv);
@ -105,6 +119,12 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
int iwlagn_send_beacon_cmd(struct iwl_priv *priv); int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
#ifdef CONFIG_PM_SLEEP
int iwlagn_send_patterns(struct iwl_priv *priv,
struct cfg80211_wowlan *wowlan);
int iwlagn_suspend(struct iwl_priv *priv,
struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
#endif
/* rx */ /* rx */
int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
@ -196,9 +216,6 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct ieee80211_sta *sta, u8 *sta_id_r); struct ieee80211_sta *sta, u8 *sta_id_r);
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
const u8 *addr); const u8 *addr);
int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
const u8 *addr, bool is_ap, struct ieee80211_sta *sta); const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
@ -316,10 +333,6 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
int iwl_update_bcast_station(struct iwl_priv *priv, int iwl_update_bcast_station(struct iwl_priv *priv,
struct iwl_rxon_context *ctx); struct iwl_rxon_context *ctx);
int iwl_update_bcast_stations(struct iwl_priv *priv); int iwl_update_bcast_stations(struct iwl_priv *priv);
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta);
/* rate */ /* rate */
static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)

View File

@ -101,17 +101,11 @@ extern struct iwl_cfg iwl100_bg_cfg;
extern struct iwl_cfg iwl130_bgn_cfg; extern struct iwl_cfg iwl130_bgn_cfg;
extern struct iwl_cfg iwl130_bg_cfg; extern struct iwl_cfg iwl130_bg_cfg;
extern struct iwl_cfg iwl2000_2bgn_cfg; extern struct iwl_cfg iwl2000_2bgn_cfg;
extern struct iwl_cfg iwl2000_2bg_cfg;
extern struct iwl_cfg iwl2000_2bgn_d_cfg; extern struct iwl_cfg iwl2000_2bgn_d_cfg;
extern struct iwl_cfg iwl2030_2bgn_cfg; extern struct iwl_cfg iwl2030_2bgn_cfg;
extern struct iwl_cfg iwl2030_2bg_cfg;
extern struct iwl_cfg iwl6035_2agn_cfg; extern struct iwl_cfg iwl6035_2agn_cfg;
extern struct iwl_cfg iwl6035_2abg_cfg;
extern struct iwl_cfg iwl6035_2bg_cfg;
extern struct iwl_cfg iwl105_bg_cfg;
extern struct iwl_cfg iwl105_bgn_cfg; extern struct iwl_cfg iwl105_bgn_cfg;
extern struct iwl_cfg iwl105_bgn_d_cfg; extern struct iwl_cfg iwl105_bgn_d_cfg;
extern struct iwl_cfg iwl135_bg_cfg;
extern struct iwl_cfg iwl135_bgn_cfg; extern struct iwl_cfg iwl135_bgn_cfg;
#endif /* __iwl_pci_h__ */ #endif /* __iwl_pci_h__ */

View File

@ -198,6 +198,7 @@ enum {
REPLY_WOWLAN_TKIP_PARAMS = 0xe3, REPLY_WOWLAN_TKIP_PARAMS = 0xe3,
REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4, REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4,
REPLY_WOWLAN_GET_STATUS = 0xe5, REPLY_WOWLAN_GET_STATUS = 0xe5,
REPLY_D3_CONFIG = 0xd3,
REPLY_MAX = 0xff REPLY_MAX = 0xff
}; };
@ -3800,6 +3801,19 @@ struct iwl_bt_coex_prot_env_cmd {
u8 reserved[2]; u8 reserved[2];
} __attribute__((packed)); } __attribute__((packed));
/*
* REPLY_D3_CONFIG
*/
enum iwlagn_d3_wakeup_filters {
IWLAGN_D3_WAKEUP_RFKILL = BIT(0),
IWLAGN_D3_WAKEUP_SYSASSERT = BIT(1),
};
struct iwlagn_d3_config_cmd {
__le32 min_sleep_time;
__le32 wakeup_flags;
} __packed;
/* /*
* REPLY_WOWLAN_PATTERNS * REPLY_WOWLAN_PATTERNS
*/ */
@ -3830,19 +3844,16 @@ enum iwlagn_wowlan_wakeup_filters {
IWLAGN_WOWLAN_WAKEUP_BEACON_MISS = BIT(2), IWLAGN_WOWLAN_WAKEUP_BEACON_MISS = BIT(2),
IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3), IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3),
IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4), IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4),
IWLAGN_WOWLAN_WAKEUP_RFKILL = BIT(5), IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(5),
IWLAGN_WOWLAN_WAKEUP_UCODE_ERROR = BIT(6), IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(6),
IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(7), IWLAGN_WOWLAN_WAKEUP_ALWAYS = BIT(7),
IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(8), IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(8),
IWLAGN_WOWLAN_WAKEUP_ALWAYS = BIT(9),
IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(10),
}; };
struct iwlagn_wowlan_wakeup_filter_cmd { struct iwlagn_wowlan_wakeup_filter_cmd {
__le32 enabled; __le32 enabled;
__le16 non_qos_seq; __le16 non_qos_seq;
u8 min_sleep_seconds; __le16 reserved;
u8 reserved;
__le16 qos_seq[8]; __le16 qos_seq[8];
}; };

View File

@ -1120,229 +1120,8 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
&statistics_cmd); &statistics_cmd);
} }
int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx;
unsigned long flags;
int q;
IWL_DEBUG_MAC80211(priv, "enter\n");
if (!iwl_is_ready_rf(priv->shrd)) {
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
return -EIO;
}
if (queue >= AC_NUM) {
IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
return 0;
}
q = AC_NUM - 1 - queue;
spin_lock_irqsave(&priv->shrd->lock, flags);
/*
* MULTI-FIXME
* This may need to be done per interface in nl80211/cfg80211/mac80211.
*/
for_each_context(priv, ctx) {
ctx->qos_data.def_qos_parm.ac[q].cw_min =
cpu_to_le16(params->cw_min);
ctx->qos_data.def_qos_parm.ac[q].cw_max =
cpu_to_le16(params->cw_max);
ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
ctx->qos_data.def_qos_parm.ac[q].edca_txop =
cpu_to_le16((params->txop * 32));
ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
}
spin_unlock_irqrestore(&priv->shrd->lock, flags);
IWL_DEBUG_MAC80211(priv, "leave\n");
return 0;
}
int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
return priv->ibss_manager == IWL_IBSS_MANAGER;
}
static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
iwl_connection_init_rx_config(priv, ctx);
iwlagn_set_rxon_chain(priv, ctx);
return iwlagn_commit_rxon(priv, ctx);
}
static int iwl_setup_interface(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
struct ieee80211_vif *vif = ctx->vif;
int err;
lockdep_assert_held(&priv->shrd->mutex);
/*
* This variable will be correct only when there's just
* a single context, but all code using it is for hardware
* that supports only one context.
*/
priv->iw_mode = vif->type;
ctx->is_active = true;
err = iwl_set_mode(priv, ctx);
if (err) {
if (!ctx->always_active)
ctx->is_active = false;
return err;
}
if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
vif->type == NL80211_IFTYPE_ADHOC) {
/*
* pretend to have high BT traffic as long as we
* are operating in IBSS mode, as this will cause
* the rate scaling etc. to behave as intended.
*/
priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
}
return 0;
}
int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *tmp, *ctx = NULL;
int err;
enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif);
IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
viftype, vif->addr);
cancel_delayed_work_sync(&priv->hw_roc_disable_work);
mutex_lock(&priv->shrd->mutex);
iwlagn_disable_roc(priv);
if (!iwl_is_ready_rf(priv->shrd)) {
IWL_WARN(priv, "Try to add interface when device not ready\n");
err = -EINVAL;
goto out;
}
for_each_context(priv, tmp) {
u32 possible_modes =
tmp->interface_modes | tmp->exclusive_interface_modes;
if (tmp->vif) {
/* check if this busy context is exclusive */
if (tmp->exclusive_interface_modes &
BIT(tmp->vif->type)) {
err = -EINVAL;
goto out;
}
continue;
}
if (!(possible_modes & BIT(viftype)))
continue;
/* have maybe usable context w/o interface */
ctx = tmp;
break;
}
if (!ctx) {
err = -EOPNOTSUPP;
goto out;
}
vif_priv->ctx = ctx;
ctx->vif = vif;
err = iwl_setup_interface(priv, ctx);
if (!err)
goto out;
ctx->vif = NULL;
priv->iw_mode = NL80211_IFTYPE_STATION;
out:
mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return err;
}
static void iwl_teardown_interface(struct iwl_priv *priv,
struct ieee80211_vif *vif,
bool mode_change)
{
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
lockdep_assert_held(&priv->shrd->mutex);
if (priv->scan_vif == vif) {
iwl_scan_cancel_timeout(priv, 200);
iwl_force_scan_end(priv);
}
if (!mode_change) {
iwl_set_mode(priv, ctx);
if (!ctx->always_active)
ctx->is_active = false;
}
/*
* When removing the IBSS interface, overwrite the
* BT traffic load with the stored one from the last
* notification, if any. If this is a device that
* doesn't implement this, this has no effect since
* both values are the same and zero.
*/
if (vif->type == NL80211_IFTYPE_ADHOC)
priv->bt_traffic_load = priv->last_bt_traffic_load;
}
void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex);
if (WARN_ON(ctx->vif != vif)) {
struct iwl_rxon_context *tmp;
IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif);
for_each_context(priv, tmp)
IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n",
tmp->ctxid, tmp, tmp->vif);
}
ctx->vif = NULL;
iwl_teardown_interface(priv, vif, false);
mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
}
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
@ -1649,97 +1428,13 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
return 0; return 0;
} }
int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_rxon_context *tmp;
enum nl80211_iftype newviftype = newtype;
u32 interface_modes;
int err;
IWL_DEBUG_MAC80211(priv, "enter\n");
newtype = ieee80211_iftype_p2p(newtype, newp2p);
mutex_lock(&priv->shrd->mutex);
if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) {
/*
* Huh? But wait ... this can maybe happen when
* we're in the middle of a firmware restart!
*/
err = -EBUSY;
goto out;
}
interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
if (!(interface_modes & BIT(newtype))) {
err = -EBUSY;
goto out;
}
/*
* Refuse a change that should be done by moving from the PAN
* context to the BSS context instead, if the BSS context is
* available and can support the new interface type.
*/
if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif &&
(bss_ctx->interface_modes & BIT(newtype) ||
bss_ctx->exclusive_interface_modes & BIT(newtype))) {
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
err = -EBUSY;
goto out;
}
if (ctx->exclusive_interface_modes & BIT(newtype)) {
for_each_context(priv, tmp) {
if (ctx == tmp)
continue;
if (!tmp->vif)
continue;
/*
* The current mode switch would be exclusive, but
* another context is active ... refuse the switch.
*/
err = -EBUSY;
goto out;
}
}
/* success */
iwl_teardown_interface(priv, vif, true);
vif->type = newviftype;
vif->p2p = newp2p;
err = iwl_setup_interface(priv, ctx);
WARN_ON(err);
/*
* We've switched internally, but submitting to the
* device may have failed for some reason. Mask this
* error, because otherwise mac80211 will not switch
* (and set the interface type back) and we'll be
* out of sync with it.
*/
err = 0;
out:
mutex_unlock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n");
return err;
}
int iwl_cmd_echo_test(struct iwl_priv *priv) int iwl_cmd_echo_test(struct iwl_priv *priv)
{ {
int ret; int ret;
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = REPLY_ECHO, .id = REPLY_ECHO,
.len = { 0 },
.flags = CMD_SYNC, .flags = CMD_SYNC,
}; };

View File

@ -237,10 +237,6 @@ struct iwl_cfg {
* L i b * * L i b *
***************************/ ***************************/
int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params);
int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw);
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
int hw_decrypt); int hw_decrypt);
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@ -260,13 +256,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
void iwl_connection_init_rx_config(struct iwl_priv *priv, void iwl_connection_init_rx_config(struct iwl_priv *priv,
struct iwl_rxon_context *ctx); struct iwl_rxon_context *ctx);
void iwl_set_rate(struct iwl_priv *priv); void iwl_set_rate(struct iwl_priv *priv);
int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p);
int iwl_cmd_echo_test(struct iwl_priv *priv); int iwl_cmd_echo_test(struct iwl_priv *priv);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_alloc_traffic_mem(struct iwl_priv *priv); int iwl_alloc_traffic_mem(struct iwl_priv *priv);
@ -323,9 +312,6 @@ void iwl_init_scan_params(struct iwl_priv *priv);
int iwl_scan_cancel(struct iwl_priv *priv); int iwl_scan_cancel(struct iwl_priv *priv);
void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
void iwl_force_scan_end(struct iwl_priv *priv); void iwl_force_scan_end(struct iwl_priv *priv);
int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
void iwl_internal_short_hw_scan(struct iwl_priv *priv); void iwl_internal_short_hw_scan(struct iwl_priv *priv);
int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,

View File

@ -284,8 +284,8 @@
#define CSR_HW_REV_TYPE_6x35 CSR_HW_REV_TYPE_6x05 #define CSR_HW_REV_TYPE_6x35 CSR_HW_REV_TYPE_6x05
#define CSR_HW_REV_TYPE_2x30 (0x00000C0) #define CSR_HW_REV_TYPE_2x30 (0x00000C0)
#define CSR_HW_REV_TYPE_2x00 (0x0000100) #define CSR_HW_REV_TYPE_2x00 (0x0000100)
#define CSR_HW_REV_TYPE_200 (0x0000110) #define CSR_HW_REV_TYPE_105 (0x0000110)
#define CSR_HW_REV_TYPE_230 (0x0000120) #define CSR_HW_REV_TYPE_135 (0x0000120)
#define CSR_HW_REV_TYPE_NONE (0x00001F0) #define CSR_HW_REV_TYPE_NONE (0x00001F0)
/* EEPROM REG */ /* EEPROM REG */

View File

@ -70,10 +70,25 @@ do { \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0) } while (0)
#define IWL_DEBUG_QUIET_RFKILL(p, fmt, args...) \
do { \
if (!iwl_is_rfkill(p->shrd)) \
dev_printk(KERN_ERR, bus(p)->dev, "%c %s " fmt, \
(in_interrupt() ? 'I' : 'U'), __func__ , ##args); \
else if (iwl_get_debug_level(p->shrd) & IWL_DL_RADIO) \
dev_printk(KERN_ERR, bus(p)->dev, "(RFKILL) %c %s " fmt, \
(in_interrupt() ? 'I' : 'U'), __func__ , ##args); \
} while (0)
#else #else
#define IWL_DEBUG(m, level, fmt, args...) #define IWL_DEBUG(m, level, fmt, args...)
#define IWL_DEBUG_LIMIT(m, level, fmt, args...) #define IWL_DEBUG_LIMIT(m, level, fmt, args...)
#define iwl_print_hex_dump(m, level, p, len) #define iwl_print_hex_dump(m, level, p, len)
#define IWL_DEBUG_QUIET_RFKILL(p, fmt, args...) \
do { \
if (!iwl_is_rfkill(p->shrd)) \
IWL_ERR(p, fmt, ##args); \
} while (0)
#endif /* CONFIG_IWLWIFI_DEBUG */ #endif /* CONFIG_IWLWIFI_DEBUG */
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
@ -151,7 +166,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DL_11H (1 << 28) #define IWL_DL_11H (1 << 28)
#define IWL_DL_STATS (1 << 29) #define IWL_DL_STATS (1 << 29)
#define IWL_DL_TX_REPLY (1 << 30) #define IWL_DL_TX_REPLY (1 << 30)
#define IWL_DL_QOS (1 << 31) #define IWL_DL_TX_QUEUES (1 << 31)
#define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) #define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
#define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) #define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
@ -188,7 +203,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a) #define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a)
#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \ #define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \
IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a) IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a)
#define IWL_DEBUG_QOS(p, f, a...) IWL_DEBUG(p, IWL_DL_QOS, f, ## a) #define IWL_DEBUG_TX_QUEUES(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_QUEUES, f, ## a)
#define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a) #define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a)
#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
#define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a) #define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a)

Some files were not shown because too many files have changed in this diff Show More