mirror of https://gitee.com/openkylin/linux.git
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:
commit
e11c259f74
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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/
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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_ */
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
@ -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];
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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) */
|
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
|
|
|
@ -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) "
|
||||||
|
|
|
@ -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
|
@ -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)
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue