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_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
||||
* have to define SOCK_NONBLOCK to a different value here.
|
||||
*/
|
||||
|
|
|
@ -62,4 +62,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -62,4 +62,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* __ASM_AVR32_SOCKET_H */
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
||||
|
|
|
@ -62,5 +62,8 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
|
|
@ -62,4 +62,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -71,4 +71,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_IA64_SOCKET_H */
|
||||
|
|
|
@ -62,4 +62,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_M32R_SOCKET_H */
|
||||
|
|
|
@ -62,4 +62,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#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_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/** sock_type - Socket types
|
||||
|
|
|
@ -62,4 +62,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -61,6 +61,9 @@
|
|||
|
||||
#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
|
||||
* have to define SOCK_NONBLOCK to a different value here.
|
||||
*/
|
||||
|
|
|
@ -69,4 +69,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_POWERPC_SOCKET_H */
|
||||
|
|
|
@ -70,4 +70,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -58,6 +58,9 @@
|
|||
|
||||
#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 */
|
||||
#define SO_SECURITY_AUTHENTICATION 0x5001
|
||||
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
|
||||
|
|
|
@ -73,4 +73,7 @@
|
|||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#define SO_WIFI_STATUS 41
|
||||
#define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||
|
||||
#endif /* _XTENSA_SOCKET_H */
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <net/bluetooth/bluetooth.h>
|
||||
|
||||
#define VERSION "1.0"
|
||||
#define ATH3K_FIRMWARE "ath3k-1.fw"
|
||||
|
||||
#define ATH3K_DNLOAD 0x01
|
||||
#define ATH3K_GETSTATE 0x05
|
||||
|
@ -400,9 +401,15 @@ static int ath3k_probe(struct usb_interface *intf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) {
|
||||
BT_ERR("Error loading firmware");
|
||||
return -EIO;
|
||||
ret = request_firmware(&firmware, ATH3K_FIRMWARE, &udev->dev);
|
||||
if (ret < 0) {
|
||||
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);
|
||||
|
@ -441,4 +448,4 @@ MODULE_AUTHOR("Atheros Communications");
|
|||
MODULE_DESCRIPTION("Atheros AR30xx firmware driver");
|
||||
MODULE_VERSION(VERSION);
|
||||
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);
|
||||
|
||||
if (hci_unregister_dev(hdev) < 0)
|
||||
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -844,9 +844,7 @@ static int bluecard_close(bluecard_info_t *info)
|
|||
/* Turn FPGA off */
|
||||
outb(0x80, iobase + 0x30);
|
||||
|
||||
if (hci_unregister_dev(hdev) < 0)
|
||||
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -636,9 +636,7 @@ static int bt3c_close(bt3c_info_t *info)
|
|||
|
||||
bt3c_hci_close(hdev);
|
||||
|
||||
if (hci_unregister_dev(hdev) < 0)
|
||||
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -565,9 +565,7 @@ static int btuart_close(btuart_info_t *info)
|
|||
|
||||
spin_unlock_irqrestore(&(info->lock), flags);
|
||||
|
||||
if (hci_unregister_dev(hdev) < 0)
|
||||
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -100,6 +100,9 @@ static struct usb_device_id btusb_table[] = {
|
|||
/* Canyon CN-BTU1 with HID interfaces */
|
||||
{ USB_DEVICE(0x0c10, 0x0000) },
|
||||
|
||||
/* Broadcom BCM20702A0 */
|
||||
{ USB_DEVICE(0x413c, 0x8197) },
|
||||
|
||||
{ } /* 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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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,
|
||||
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++;
|
||||
break;
|
||||
|
||||
|
@ -767,7 +776,9 @@ static int btusb_send_frame(struct sk_buff *skb)
|
|||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
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);
|
||||
usb_unanchor_urb(urb);
|
||||
} else {
|
||||
|
|
|
@ -551,9 +551,7 @@ static int dtl1_close(dtl1_info_t *info)
|
|||
|
||||
spin_unlock_irqrestore(&(info->lock), flags);
|
||||
|
||||
if (hci_unregister_dev(hdev) < 0)
|
||||
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -264,10 +264,7 @@ static int vhci_release(struct inode *inode, struct file *file)
|
|||
struct vhci_data *data = file->private_data;
|
||||
struct hci_dev *hdev = data->hdev;
|
||||
|
||||
if (hci_unregister_dev(hdev) < 0) {
|
||||
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||
}
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
hci_free_dev(hdev);
|
||||
|
||||
file->private_data = NULL;
|
||||
|
|
|
@ -58,6 +58,6 @@ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/
|
|||
obj-$(CONFIG_IWM) += iwmc3200wifi/
|
||||
|
||||
obj-$(CONFIG_MWIFIEX) += mwifiex/
|
||||
obj-$(CONFIG_BRCMFMAC) += brcm80211/
|
||||
obj-$(CONFIG_BRCMUMAC) += brcm80211/
|
||||
obj-$(CONFIG_BRCMSMAC) += brcm80211/
|
||||
|
||||
obj-$(CONFIG_BRCMFMAC) += brcm80211/
|
||||
obj-$(CONFIG_BRCMSMAC) += brcm80211/
|
||||
|
|
|
@ -239,6 +239,7 @@ enum ATH_DEBUG {
|
|||
ATH_DBG_BTCOEX = 0x00002000,
|
||||
ATH_DBG_WMI = 0x00004000,
|
||||
ATH_DBG_BSTUCK = 0x00008000,
|
||||
ATH_DBG_MCI = 0x00010000,
|
||||
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,
|
||||
enum nl80211_channel_type channel_type,
|
||||
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);
|
||||
u32 id;
|
||||
|
|
|
@ -1548,7 +1548,8 @@ static int ath6kl_init(struct net_device *dev)
|
|||
ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
|
||||
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);
|
||||
if (!status)
|
||||
|
|
|
@ -25,6 +25,7 @@ config ATH9K
|
|||
|
||||
config ATH9K_PCI
|
||||
bool "Atheros ath9k PCI/PCIe bus support"
|
||||
default y
|
||||
depends on ATH9K && PCI
|
||||
---help---
|
||||
This option enables the PCI bus support in ath9k.
|
||||
|
|
|
@ -4,6 +4,7 @@ ath9k-y += beacon.o \
|
|||
main.o \
|
||||
recv.o \
|
||||
xmit.o \
|
||||
mci.o \
|
||||
|
||||
ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
|
||||
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
|
||||
|
|
|
@ -121,10 +121,8 @@ static const struct ar9300_eeprom ar9300_default = {
|
|||
* if the register is per chain
|
||||
*/
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {1, 1, 1},/* 3 chain */
|
||||
.db_stage2 = {1, 1, 1}, /* 3 chain */
|
||||
.db_stage3 = {0, 0, 0},
|
||||
.db_stage4 = {0, 0, 0},
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -144,7 +142,7 @@ static const struct ar9300_eeprom ar9300_default = {
|
|||
},
|
||||
.base_ext1 = {
|
||||
.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 = {
|
||||
FREQ2FBIN(2412, 1),
|
||||
|
@ -323,10 +321,8 @@ static const struct ar9300_eeprom ar9300_default = {
|
|||
.spurChans = {0, 0, 0, 0, 0},
|
||||
/* noiseFloorThreshCh Check if the register is per chain */
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage2 = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
|
||||
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -698,10 +694,8 @@ static const struct ar9300_eeprom ar9300_x113 = {
|
|||
* if the register is per chain
|
||||
*/
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {1, 1, 1},/* 3 chain */
|
||||
.db_stage2 = {1, 1, 1}, /* 3 chain */
|
||||
.db_stage3 = {0, 0, 0},
|
||||
.db_stage4 = {0, 0, 0},
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -721,7 +715,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
|
|||
},
|
||||
.base_ext1 = {
|
||||
.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 = {
|
||||
FREQ2FBIN(2412, 1),
|
||||
|
@ -900,10 +894,8 @@ static const struct ar9300_eeprom ar9300_x113 = {
|
|||
.spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0},
|
||||
/* noiseFloorThreshCh Check if the register is per chain */
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage2 = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
|
||||
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0xf,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -1276,10 +1268,8 @@ static const struct ar9300_eeprom ar9300_h112 = {
|
|||
* if the register is per chain
|
||||
*/
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {1, 1, 1},/* 3 chain */
|
||||
.db_stage2 = {1, 1, 1}, /* 3 chain */
|
||||
.db_stage3 = {0, 0, 0},
|
||||
.db_stage4 = {0, 0, 0},
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -1291,20 +1281,20 @@ static const struct ar9300_eeprom ar9300_h112 = {
|
|||
.txEndToRxOn = 0x2,
|
||||
.txFrameToXpaOn = 0xe,
|
||||
.thresh62 = 28,
|
||||
.papdRateMaskHt20 = LE32(0x80c080),
|
||||
.papdRateMaskHt40 = LE32(0x80c080),
|
||||
.papdRateMaskHt20 = LE32(0x0c80c080),
|
||||
.papdRateMaskHt40 = LE32(0x0080c080),
|
||||
.futureModal = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
},
|
||||
},
|
||||
.base_ext1 = {
|
||||
.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 = {
|
||||
FREQ2FBIN(2412, 1),
|
||||
FREQ2FBIN(2437, 1),
|
||||
FREQ2FBIN(2472, 1),
|
||||
FREQ2FBIN(2462, 1),
|
||||
},
|
||||
/* ar9300_cal_data_per_freq_op_loop 2g */
|
||||
.calPierData2G = {
|
||||
|
@ -1314,7 +1304,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
|
|||
},
|
||||
.calTarget_freqbin_Cck = {
|
||||
FREQ2FBIN(2412, 1),
|
||||
FREQ2FBIN(2484, 1),
|
||||
FREQ2FBIN(2472, 1),
|
||||
},
|
||||
.calTarget_freqbin_2G = {
|
||||
FREQ2FBIN(2412, 1),
|
||||
|
@ -1478,10 +1468,8 @@ static const struct ar9300_eeprom ar9300_h112 = {
|
|||
.spurChans = {0, 0, 0, 0, 0},
|
||||
/* noiseFloorThreshCh Check if the register is per chain */
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage2 = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
|
||||
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -1515,7 +1503,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
|
|||
FREQ2FBIN(5500, 0),
|
||||
FREQ2FBIN(5600, 0),
|
||||
FREQ2FBIN(5700, 0),
|
||||
FREQ2FBIN(5825, 0)
|
||||
FREQ2FBIN(5785, 0)
|
||||
},
|
||||
.calPierData5G = {
|
||||
{
|
||||
|
@ -1854,10 +1842,8 @@ static const struct ar9300_eeprom ar9300_x112 = {
|
|||
* if the register is per chain
|
||||
*/
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {1, 1, 1},/* 3 chain */
|
||||
.db_stage2 = {1, 1, 1}, /* 3 chain */
|
||||
.db_stage3 = {0, 0, 0},
|
||||
.db_stage4 = {0, 0, 0},
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -1877,7 +1863,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
|
|||
},
|
||||
.base_ext1 = {
|
||||
.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 = {
|
||||
FREQ2FBIN(2412, 1),
|
||||
|
@ -2056,10 +2042,8 @@ static const struct ar9300_eeprom ar9300_x112 = {
|
|||
.spurChans = {0, 0, 0, 0, 0},
|
||||
/* noiseFloorThreshch check if the register is per chain */
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage2 = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
|
||||
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -2431,10 +2415,8 @@ static const struct ar9300_eeprom ar9300_h116 = {
|
|||
* if the register is per chain
|
||||
*/
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {1, 1, 1},/* 3 chain */
|
||||
.db_stage2 = {1, 1, 1}, /* 3 chain */
|
||||
.db_stage3 = {0, 0, 0},
|
||||
.db_stage4 = {0, 0, 0},
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -2454,12 +2436,12 @@ static const struct ar9300_eeprom ar9300_h116 = {
|
|||
},
|
||||
.base_ext1 = {
|
||||
.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 = {
|
||||
FREQ2FBIN(2412, 1),
|
||||
FREQ2FBIN(2437, 1),
|
||||
FREQ2FBIN(2472, 1),
|
||||
FREQ2FBIN(2462, 1),
|
||||
},
|
||||
/* ar9300_cal_data_per_freq_op_loop 2g */
|
||||
.calPierData2G = {
|
||||
|
@ -2633,10 +2615,8 @@ static const struct ar9300_eeprom ar9300_h116 = {
|
|||
.spurChans = {0, 0, 0, 0, 0},
|
||||
/* noiseFloorThreshCh Check if the register is per chain */
|
||||
.noiseFloorThreshCh = {-1, 0, 0},
|
||||
.ob = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage2 = {3, 3, 3}, /* 3 chain */
|
||||
.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
|
||||
.db_stage4 = {3, 3, 3}, /* don't exist for 2G */
|
||||
.reserved = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.quick_drop = 0,
|
||||
.xpaBiasLvl = 0,
|
||||
.txFrameToDataStart = 0x0e,
|
||||
.txFrameToPaOn = 0x0e,
|
||||
|
@ -2663,7 +2643,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
|
|||
.xatten1MarginHigh = {0, 0, 0}
|
||||
},
|
||||
.calFreqPier5G = {
|
||||
FREQ2FBIN(5180, 0),
|
||||
FREQ2FBIN(5160, 0),
|
||||
FREQ2FBIN(5220, 0),
|
||||
FREQ2FBIN(5320, 0),
|
||||
FREQ2FBIN(5400, 0),
|
||||
|
@ -3023,6 +3003,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
|
|||
return eep->modalHeader5G.antennaGain;
|
||||
case EEP_ANTENNA_GAIN_2G:
|
||||
return eep->modalHeader2G.antennaGain;
|
||||
case EEP_QUICK_DROP:
|
||||
return pBase->miscConfiguration & BIT(1);
|
||||
default:
|
||||
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("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
|
||||
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("txFrameToDataStart", modal_hdr->txFrameToDataStart);
|
||||
PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
|
||||
PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
|
||||
PR_EEP("txClip", modal_hdr->txClip);
|
||||
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;
|
||||
}
|
||||
|
@ -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("Enable Paprd", !!(pBase->featureEnable & BIT(5)));
|
||||
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("Write enable Gpio", pBase->eepromWriteEnableGpio);
|
||||
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,
|
||||
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_drive_strength_apply(ah);
|
||||
ar9003_hw_atten_apply(ah, chan);
|
||||
ar9003_hw_quick_drop_apply(ah, chan->channel);
|
||||
if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
|
||||
ar9003_hw_internal_regulator_apply(ah);
|
||||
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(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,
|
||||
|
@ -5051,6 +5059,8 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
|
|||
regulatory->max_power_level = targetPowerValT2[i];
|
||||
}
|
||||
|
||||
ath9k_hw_update_regulatory_maxpower(ah);
|
||||
|
||||
if (test)
|
||||
return;
|
||||
|
||||
|
|
|
@ -216,10 +216,8 @@ struct ar9300_modal_eep_header {
|
|||
u8 spurChans[AR_EEPROM_MODAL_SPURS];
|
||||
/* 3 Check if the register is per chain */
|
||||
int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS];
|
||||
u8 ob[AR9300_MAX_CHAINS];
|
||||
u8 db_stage2[AR9300_MAX_CHAINS];
|
||||
u8 db_stage3[AR9300_MAX_CHAINS];
|
||||
u8 db_stage4[AR9300_MAX_CHAINS];
|
||||
u8 reserved[11];
|
||||
int8_t quick_drop;
|
||||
u8 xpaBiasLvl;
|
||||
u8 txFrameToDataStart;
|
||||
u8 txFrameToPaOn;
|
||||
|
@ -269,7 +267,9 @@ struct cal_ctl_data_5g {
|
|||
|
||||
struct ar9300_BaseExtension_1 {
|
||||
u8 ant_div_control;
|
||||
u8 future[13];
|
||||
u8 future[11];
|
||||
int8_t quick_drop_low;
|
||||
int8_t quick_drop_high;
|
||||
} __packed;
|
||||
|
||||
struct ar9300_BaseExtension_2 {
|
||||
|
|
|
@ -199,12 +199,14 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
|
|||
synth_freq = chan->channel;
|
||||
}
|
||||
} else {
|
||||
range = 10;
|
||||
range = AR_SREV_9462(ah) ? 5 : 10;
|
||||
max_spur_cnts = 4;
|
||||
synth_freq = chan->channel;
|
||||
}
|
||||
|
||||
for (i = 0; i < max_spur_cnts; i++) {
|
||||
if (AR_SREV_9462(ah) && (i == 0 || i == 3))
|
||||
continue;
|
||||
negative = 0;
|
||||
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
|
||||
cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
|
||||
|
|
|
@ -389,6 +389,8 @@
|
|||
#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
|
||||
|
||||
#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_S 7
|
||||
#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 */
|
||||
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
|
||||
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
|
||||
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
|
||||
{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
|
||||
{0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x5ac640de},
|
||||
{0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x0796be89},
|
||||
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
|
||||
{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
|
||||
{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
|
||||
{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
|
||||
{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
|
||||
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3039605e, 0x33795d5e},
|
||||
{0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x92c84d2e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
|
||||
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
|
||||
{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] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
|
||||
{0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
|
||||
{0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
|
||||
{0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
|
||||
{0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
|
||||
};
|
||||
|
||||
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] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
|
||||
{0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
|
||||
{0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
|
||||
{0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
|
||||
{0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
|
||||
};
|
||||
|
||||
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] = {
|
||||
/* 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] = {
|
||||
|
@ -1257,8 +1257,8 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
|
|||
{0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
|
||||
{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
|
||||
{0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
|
||||
{0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
|
||||
{0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
|
||||
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
|
||||
{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},
|
||||
{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
|
||||
{0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
|
||||
{0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
|
||||
{0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
|
||||
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "mci.h"
|
||||
|
||||
/*
|
||||
* 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
|
||||
struct list_head list; /* for sc->nodes */
|
||||
struct ieee80211_sta *sta; /* station struct we're part of */
|
||||
struct ieee80211_vif *vif; /* interface with which we're associated */
|
||||
#endif
|
||||
struct ath_atx_tid tid[WME_NUM_TID];
|
||||
struct ath_atx_ac ac[WME_NUM_AC];
|
||||
|
@ -443,7 +445,9 @@ struct ath_btcoex {
|
|||
u32 btcoex_no_stomp; /* in usec */
|
||||
u32 btcoex_period; /* 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_mci_profile mci;
|
||||
};
|
||||
|
||||
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,
|
||||
"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");
|
||||
|
||||
spin_lock(&sc->nodes_lock);
|
||||
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,
|
||||
"%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)
|
||||
goto done;
|
||||
|
||||
for (q = 0; q < WME_NUM_TID; q++) {
|
||||
struct ath_atx_tid *tid = &(an->tid[q]);
|
||||
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->paused ? "paused" : "running",
|
||||
skb_queue_empty(&tid->buf_q),
|
||||
tid->an, tid->ac);
|
||||
tid->an, tid->ac, tid->baw_size);
|
||||
if (len >= size)
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -249,7 +249,8 @@ enum eeprom_param {
|
|||
EEP_ANT_DIV_CTL1,
|
||||
EEP_CHAIN_MASK_REDUCE,
|
||||
EEP_ANTENNA_GAIN_2G,
|
||||
EEP_ANTENNA_GAIN_5G
|
||||
EEP_ANTENNA_GAIN_5G,
|
||||
EEP_QUICK_DROP
|
||||
};
|
||||
|
||||
enum ar5416_rates {
|
||||
|
|
|
@ -189,8 +189,8 @@ static void ath_btcoex_period_timer(unsigned long data)
|
|||
bool is_btscan;
|
||||
|
||||
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;
|
||||
|
||||
spin_lock_bh(&btcoex->btcoex_lock);
|
||||
|
@ -212,8 +212,9 @@ static void ath_btcoex_period_timer(unsigned long data)
|
|||
}
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
timer_period = btcoex->btcoex_period / 1000;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -2583,7 +2583,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
|
|||
struct ath9k_channel *chan = ah->curchan;
|
||||
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)
|
||||
channel->max_power = MAX_RATE_POWER / 2;
|
||||
|
||||
|
|
|
@ -203,6 +203,7 @@ enum ath9k_hw_caps {
|
|||
ATH9K_HW_CAP_5GHZ = BIT(14),
|
||||
ATH9K_HW_CAP_APM = BIT(15),
|
||||
ATH9K_HW_CAP_RTT = BIT(16),
|
||||
ATH9K_HW_CAP_MCI = BIT(17),
|
||||
};
|
||||
|
||||
struct ath9k_hw_capabilities {
|
||||
|
@ -419,6 +420,16 @@ enum ath9k_rx_qtype {
|
|||
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 {
|
||||
u32 bs_nexttbtt;
|
||||
u32 bs_nextdtim;
|
||||
|
|
|
@ -424,6 +424,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
|
|||
txq = sc->tx.txq_map[WME_AC_BE];
|
||||
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
|
||||
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;
|
||||
default:
|
||||
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_IBSS_RSN;
|
||||
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
|
||||
|
||||
hw->queues = 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;
|
||||
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);
|
||||
spin_unlock(&sc->nodes_lock);
|
||||
an->sta = sta;
|
||||
an->vif = vif;
|
||||
#endif
|
||||
if (sc->sc_flags & SC_OP_TXAGGR) {
|
||||
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) &&
|
||||
!ah->btcoex_hw.enabled) {
|
||||
ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
|
||||
AR_STOMP_LOW_WLAN_WGHT);
|
||||
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
|
||||
ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
|
||||
AR_STOMP_LOW_WLAN_WGHT);
|
||||
ath9k_hw_btcoex_enable(ah);
|
||||
|
||||
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);
|
||||
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
|
||||
ath9k_btcoex_timer_pause(sc);
|
||||
ath_mci_flush_profile(&sc->btcoex.mci);
|
||||
}
|
||||
|
||||
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 ieee80211_key_conf ps_key = { };
|
||||
|
||||
ath_node_attach(sc, sta);
|
||||
ath_node_attach(sc, sta, vif);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_AP &&
|
||||
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 ieee80211_tx_info *tx_info;
|
||||
struct ieee80211_tx_rate *rates;
|
||||
struct ath_mci_profile *mci = &sc->btcoex.mci;
|
||||
u32 max_4ms_framelen, frmlen;
|
||||
u16 aggr_limit, legacy = 0;
|
||||
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)
|
||||
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,
|
||||
(u32)ATH_AMPDU_LIMIT_MAX);
|
||||
else
|
||||
|
|
|
@ -254,6 +254,8 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
|
|||
int r;
|
||||
|
||||
sband = wiphy->bands[IEEE80211_BAND_2GHZ];
|
||||
if (!sband)
|
||||
return;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
const struct b43_phy *phy = &dev->phy;
|
||||
|
@ -256,6 +257,9 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
|||
unsigned int plcp_fragment_len;
|
||||
u32 mac_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;
|
||||
struct ieee80211_rate *txrate;
|
||||
struct ieee80211_tx_rate *rates;
|
||||
|
@ -531,7 +535,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
|||
extra_ft |= B43_TXH_EFT_RTSFB_CCK;
|
||||
|
||||
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(
|
||||
b43_generate_tx_phy_ctl1(dev, rts_rate));
|
||||
txhdr->phy_ctl1_rts_fb = cpu_to_le16(
|
||||
|
@ -552,7 +556,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
|||
break;
|
||||
}
|
||||
|
||||
if (phy->type == B43_PHYTYPE_N) {
|
||||
if (fill_phy_ctl1) {
|
||||
txhdr->phy_ctl1 =
|
||||
cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
|
||||
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 */
|
||||
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:
|
||||
/* Broadcom has code for min and avg, but always uses max */
|
||||
if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
|
||||
status.signal = max(rxhdr->power1, rxhdr->power2);
|
||||
else
|
||||
|
|
|
@ -249,6 +249,12 @@ struct b43_rxhdr_fw4 {
|
|||
} __packed;
|
||||
} __packed;
|
||||
union {
|
||||
/* HT-PHY */
|
||||
struct {
|
||||
PAD_BYTES(1);
|
||||
__s8 phy_ht_power0;
|
||||
} __packed;
|
||||
|
||||
/* RSSI for N-PHYs */
|
||||
struct {
|
||||
__s8 power2;
|
||||
|
@ -257,7 +263,15 @@ struct b43_rxhdr_fw4 {
|
|||
|
||||
__le16 phy_status2; /* PHY RX Status 2 */
|
||||
} __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 {
|
||||
/* Tested with 598.314, 644.1001 and 666.2 */
|
||||
struct {
|
||||
|
|
|
@ -26,7 +26,8 @@ DHDOFILES = \
|
|||
dhd_sdio.o \
|
||||
dhd_linux.o \
|
||||
bcmsdh.o \
|
||||
bcmsdh_sdmmc.o
|
||||
bcmsdh_sdmmc.o \
|
||||
sdio_chip.o
|
||||
|
||||
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
|
||||
brcmfmac-objs += $(DHDOFILES)
|
||||
|
|
|
@ -18,13 +18,6 @@
|
|||
#define _bcmchip_h_
|
||||
|
||||
/* 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 */
|
||||
#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin"
|
||||
#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt"
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
#define TOE_TX_CSUM_OL 0x00000001
|
||||
#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 */
|
||||
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
|
||||
|
@ -122,8 +122,6 @@
|
|||
|
||||
/* For supporting multiple interfaces */
|
||||
#define BRCMF_MAX_IFS 16
|
||||
#define BRCMF_DEL_IF -0xe
|
||||
#define BRCMF_BAD_IF -0xf
|
||||
|
||||
#define DOT11_BSSTYPE_ANY 2
|
||||
#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
|
||||
* 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 length; /* byte length of data in this record,
|
||||
* starting at version and including IEs
|
||||
|
@ -466,14 +464,13 @@ struct brcmf_scan_results {
|
|||
u32 buflen;
|
||||
u32 version;
|
||||
u32 count;
|
||||
struct brcmf_bss_info bss_info[1];
|
||||
struct brcmf_bss_info_le bss_info_le[];
|
||||
};
|
||||
|
||||
struct brcmf_scan_results_le {
|
||||
__le32 buflen;
|
||||
__le32 version;
|
||||
__le32 count;
|
||||
struct brcmf_bss_info bss_info[1];
|
||||
};
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
/* 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 */
|
||||
struct brcmf_iscan_results {
|
||||
union {
|
||||
|
@ -511,7 +504,7 @@ struct brcmf_iscan_results {
|
|||
|
||||
/* size of brcmf_iscan_results not including variable length array */
|
||||
#define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
|
||||
(BRCMF_SCAN_RESULTS_FIXED_SIZE + \
|
||||
(sizeof(struct brcmf_scan_results) + \
|
||||
offsetof(struct brcmf_iscan_results, results))
|
||||
|
||||
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 int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx,
|
||||
struct net_device *ndev, char *name, u8 *mac_addr,
|
||||
u32 flags, u8 bssidx);
|
||||
char *name, u8 *mac_addr);
|
||||
extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
|
||||
|
||||
/* 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->action == BRCMF_E_IF_ADD)
|
||||
brcmf_add_if(drvr_priv, ifevent->ifidx, NULL,
|
||||
brcmf_add_if(drvr_priv, ifevent->ifidx,
|
||||
event->ifname,
|
||||
pvt_data->eth.h_dest,
|
||||
ifevent->flags, ifevent->bssidx);
|
||||
pvt_data->eth.h_dest);
|
||||
else
|
||||
brcmf_del_if(drvr_priv, ifevent->ifidx);
|
||||
} else {
|
||||
|
|
|
@ -58,7 +58,6 @@ struct brcmf_if {
|
|||
struct net_device *ndev;
|
||||
struct net_device_stats stats;
|
||||
int idx; /* iface idx in dongle */
|
||||
int state; /* interface state */
|
||||
u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
|
||||
};
|
||||
|
||||
|
@ -80,20 +79,6 @@ struct brcmf_info {
|
|||
/* Error bits */
|
||||
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 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)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
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)
|
||||
{
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
int ifidx;
|
||||
|
||||
ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
if (ifidx == BRCMF_BAD_IF)
|
||||
return;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
int ifidx;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
if (ifidx == BRCMF_BAD_IF) {
|
||||
brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx);
|
||||
if (!drvr_priv->iflist[ifp->idx]) {
|
||||
brcmf_dbg(ERROR, "bad ifidx %d\n", ifp->idx);
|
||||
netif_stop_queue(ndev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -367,20 +340,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
struct sk_buff *skb2;
|
||||
|
||||
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++;
|
||||
skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
|
||||
dev_kfree_skb(skb);
|
||||
skb = skb2;
|
||||
if (skb == NULL) {
|
||||
brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
|
||||
brcmf_ifname(&drvr_priv->pub, ifidx));
|
||||
brcmf_ifname(&drvr_priv->pub, ifp->idx));
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
|
||||
ret = brcmf_sendpkt(&drvr_priv->pub, ifp->idx, skb);
|
||||
|
||||
done:
|
||||
if (ret)
|
||||
|
@ -482,12 +455,10 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
|
|||
skb_mac_header(skb),
|
||||
&event, &data);
|
||||
|
||||
if (drvr_priv->iflist[ifidx] &&
|
||||
!drvr_priv->iflist[ifidx]->state)
|
||||
if (drvr_priv->iflist[ifidx]) {
|
||||
ifp = drvr_priv->iflist[ifidx];
|
||||
|
||||
if (ifp->ndev)
|
||||
ifp->ndev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
drvr->dstats.rx_bytes += skb->len;
|
||||
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)
|
||||
{
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
struct brcmf_if *ifp;
|
||||
int ifidx;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
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)
|
||||
/* Use the protocol to get dongle stats */
|
||||
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,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
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;
|
||||
|
||||
sprintf(info->driver, KBUILD_MODNAME);
|
||||
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,
|
||||
int cmd)
|
||||
{
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
int ifidx;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
|
||||
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
|
||||
|
||||
if (ifidx == BRCMF_BAD_IF)
|
||||
if (!drvr_priv->iflist[ifp->idx])
|
||||
return -1;
|
||||
|
||||
if (cmd == SIOCETHTOOL)
|
||||
|
@ -788,17 +749,14 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
|
|||
s32 err = 0;
|
||||
int buflen = 0;
|
||||
bool is_set_key_cmd;
|
||||
struct brcmf_info *drvr_priv = *(struct brcmf_info **)
|
||||
netdev_priv(ndev);
|
||||
int ifidx;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_info *drvr_priv = ifp->info;
|
||||
|
||||
memset(&dcmd, 0, sizeof(dcmd));
|
||||
dcmd.cmd = cmd;
|
||||
dcmd.buf = arg;
|
||||
dcmd.len = len;
|
||||
|
||||
ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
|
||||
if (dcmd.buf != NULL)
|
||||
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)
|
||||
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:
|
||||
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)
|
||||
{
|
||||
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_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)
|
||||
{
|
||||
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;
|
||||
u32 toe_ol;
|
||||
int ifidx = brcmf_net2idx(drvr_priv, ndev);
|
||||
s32 ret = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
|
||||
|
||||
if (ifidx == 0) { /* do it only for primary eth0 */
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
|
||||
|
||||
if (ifp->idx == 0) { /* do it only for primary eth0 */
|
||||
/* try to bring up bus */
|
||||
ret = brcmf_bus_start(&drvr_priv->pub);
|
||||
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);
|
||||
|
||||
/* 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)
|
||||
drvr_priv->iflist[ifidx]->ndev->features |=
|
||||
drvr_priv->iflist[ifp->idx]->ndev->features |=
|
||||
NETIF_F_IP_CSUM;
|
||||
else
|
||||
drvr_priv->iflist[ifidx]->ndev->features &=
|
||||
drvr_priv->iflist[ifp->idx]->ndev->features &=
|
||||
~NETIF_F_IP_CSUM;
|
||||
}
|
||||
/* Allow transmit calls */
|
||||
|
@ -893,75 +850,62 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
|||
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
|
||||
brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev,
|
||||
char *name, u8 *mac_addr, u32 flags, u8 bssidx)
|
||||
brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
|
||||
{
|
||||
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];
|
||||
if (!ifp) {
|
||||
ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
|
||||
if (!ifp)
|
||||
return -ENOMEM;
|
||||
/*
|
||||
* Delete the existing interface before overwriting it
|
||||
* in case we missed the BRCMF_E_IF_DEL event.
|
||||
*/
|
||||
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;
|
||||
drvr_priv->iflist[ifidx] = ifp;
|
||||
ifp->idx = ifidx;
|
||||
if (mac_addr != NULL)
|
||||
memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
|
||||
|
||||
if (ndev == NULL) {
|
||||
ifp->state = BRCMF_E_IF_ADD;
|
||||
ifp->idx = ifidx;
|
||||
/*
|
||||
* Delete the existing interface before overwriting it
|
||||
* 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);
|
||||
}
|
||||
if (brcmf_net_attach(&drvr_priv->pub, ifp->idx)) {
|
||||
brcmf_dbg(ERROR, "brcmf_net_attach failed");
|
||||
free_netdev(ifp->ndev);
|
||||
drvr_priv->iflist[ifidx] = NULL;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Allocate netdev, including space for private structure */
|
||||
ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d",
|
||||
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;
|
||||
brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
|
||||
current->pid, ifp->ndev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -977,47 +921,36 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
|
|||
brcmf_dbg(ERROR, "Null interface\n");
|
||||
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);
|
||||
free_netdev(ifp->ndev);
|
||||
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_info *drvr_priv = NULL;
|
||||
struct net_device *ndev;
|
||||
|
||||
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 */
|
||||
drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
|
||||
if (!drvr_priv)
|
||||
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);
|
||||
|
||||
/* Link to info module */
|
||||
|
@ -1033,29 +966,12 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
|
|||
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->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;
|
||||
|
||||
fail:
|
||||
if (ndev)
|
||||
free_netdev(ndev);
|
||||
if (drvr_priv)
|
||||
brcmf_detach(&drvr_priv->pub);
|
||||
|
||||
|
@ -1123,16 +1039,6 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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) {
|
||||
brcmf_dbg(ERROR, "couldn't register the net device\n");
|
||||
goto fail;
|
||||
|
@ -1210,21 +1128,13 @@ void brcmf_detach(struct brcmf_pub *drvr)
|
|||
if (drvr) {
|
||||
drvr_priv = drvr->info;
|
||||
if (drvr_priv) {
|
||||
struct brcmf_if *ifp;
|
||||
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])
|
||||
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->multicast_work);
|
||||
|
||||
|
@ -1233,10 +1143,6 @@ void brcmf_detach(struct brcmf_pub *drvr)
|
|||
if (drvr->prot)
|
||||
brcmf_proto_detach(drvr);
|
||||
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
|
||||
free_netdev(ifp->ndev);
|
||||
kfree(ifp);
|
||||
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)
|
||||
{
|
||||
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 ntimes = MAX_WAIT_FOR_8021X_TX;
|
||||
int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/semaphore.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <defs.h>
|
||||
#include <brcmu_wifi.h>
|
||||
|
@ -35,6 +36,7 @@
|
|||
#include <brcm_hw_ids.h>
|
||||
#include <soc.h>
|
||||
#include "sdio_host.h"
|
||||
#include "sdio_chip.h"
|
||||
|
||||
#define DCMD_RESP_TIMEOUT 2000 /* In milli second */
|
||||
|
||||
|
@ -134,33 +136,6 @@ struct rte_console {
|
|||
/* Force no backplane reset */
|
||||
#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 */
|
||||
|
||||
/* MAPPED common CIS address */
|
||||
|
@ -335,50 +310,6 @@ struct rte_console {
|
|||
/* Flags for SDH calls */
|
||||
#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
|
||||
*/
|
||||
|
@ -388,17 +319,6 @@ static uint prio2prec(u32 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 */
|
||||
struct sdpcmd_regs {
|
||||
u32 corecontrol; /* 0x00, rev8 */
|
||||
|
@ -524,21 +444,6 @@ struct sdpcm_shared_le {
|
|||
|
||||
|
||||
/* 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 */
|
||||
struct brcmf_bus {
|
||||
struct brcmf_pub *drvr;
|
||||
|
@ -574,7 +479,7 @@ struct brcmf_bus {
|
|||
uint txminmax;
|
||||
|
||||
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 */
|
||||
|
||||
u8 *rxbuf; /* Buffer for receiving control packets */
|
||||
|
@ -663,46 +568,6 @@ struct brcmf_bus {
|
|||
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 */
|
||||
#define CLK_NONE 0
|
||||
#define CLK_SDONLY 1
|
||||
|
@ -750,10 +615,12 @@ static bool data_ok(struct brcmf_bus *bus)
|
|||
static void
|
||||
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;
|
||||
do {
|
||||
*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) &&
|
||||
(++(*retryvar) <= retry_limit));
|
||||
if (*retryvar) {
|
||||
|
@ -768,10 +635,11 @@ r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar)
|
|||
static void
|
||||
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;
|
||||
do {
|
||||
brcmf_sdcard_reg_write(bus->sdiodev,
|
||||
bus->ci->buscorebase + reg_offset,
|
||||
bus->ci->c_inf[idx].base + reg_offset,
|
||||
sizeof(u32), regval);
|
||||
} while (brcmf_sdcard_regfail(bus->sdiodev) &&
|
||||
(++(*retryvar) <= retry_limit));
|
||||
|
@ -812,10 +680,6 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
|
|||
clkreq =
|
||||
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,
|
||||
SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
|
||||
if (err) {
|
||||
|
@ -823,14 +687,6 @@ static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok)
|
|||
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 */
|
||||
clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1,
|
||||
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);
|
||||
|
||||
/* Isolate the bus */
|
||||
if (bus->ci->chip != BCM4329_CHIP_ID) {
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL,
|
||||
SBSDIO_DEVCTL_PADS_ISO, NULL);
|
||||
}
|
||||
brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
|
||||
SBSDIO_DEVICE_CTL,
|
||||
SBSDIO_DEVCTL_PADS_ISO, NULL);
|
||||
|
||||
/* Change state */
|
||||
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,
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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 */
|
||||
/* 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 (bus->glomd) {
|
||||
|
@ -1287,12 +1180,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
|
|||
num, sublen);
|
||||
break;
|
||||
}
|
||||
if (!pfirst) {
|
||||
pfirst = plast = pnext;
|
||||
} else {
|
||||
plast->next = pnext;
|
||||
plast = pnext;
|
||||
}
|
||||
skb_queue_tail(&bus->glom, pnext);
|
||||
|
||||
/* Adhere to start alignment requirements */
|
||||
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",
|
||||
bus->nextlen, totlen, rxseq);
|
||||
}
|
||||
bus->glom = pfirst;
|
||||
pfirst = pnext = NULL;
|
||||
} else {
|
||||
if (pfirst)
|
||||
brcmu_pkt_buf_free_skb(pfirst);
|
||||
bus->glom = NULL;
|
||||
brcmf_sdbrcm_free_glom(bus);
|
||||
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,
|
||||
or had one from before */
|
||||
if (bus->glom) {
|
||||
if (!skb_queue_empty(&bus->glom)) {
|
||||
if (BRCMF_GLOM_ON()) {
|
||||
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",
|
||||
pnext, (u8 *) (pnext->data),
|
||||
pnext->len, pnext->len);
|
||||
}
|
||||
}
|
||||
|
||||
pfirst = bus->glom;
|
||||
dlen = (u16) brcmu_pkttotlen(pfirst);
|
||||
pfirst = skb_peek(&bus->glom);
|
||||
dlen = (u16) brcmf_sdbrcm_glom_len(bus);
|
||||
|
||||
/* Do an SDIO read for the superframe. Configurable iovar to
|
||||
* 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,
|
||||
F2SYNC, bus->dataptr, dlen,
|
||||
NULL);
|
||||
sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen,
|
||||
bus->dataptr);
|
||||
sublen = (u16) brcmf_sdbrcm_glom_from_buf(bus, dlen);
|
||||
if (sublen != dlen) {
|
||||
brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n",
|
||||
dlen, sublen);
|
||||
|
@ -1380,9 +1264,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
|
|||
} else {
|
||||
bus->glomerr = 0;
|
||||
brcmf_sdbrcm_rxfail(bus, true, false);
|
||||
brcmu_pkt_buf_free_skb(bus->glom);
|
||||
bus->rxglomfail++;
|
||||
bus->glom = NULL;
|
||||
brcmf_sdbrcm_free_glom(bus);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1503,9 +1386,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
|
|||
} else {
|
||||
bus->glomerr = 0;
|
||||
brcmf_sdbrcm_rxfail(bus, true, false);
|
||||
brcmu_pkt_buf_free_skb(bus->glom);
|
||||
bus->rxglomfail++;
|
||||
bus->glom = NULL;
|
||||
brcmf_sdbrcm_free_glom(bus);
|
||||
}
|
||||
bus->nextlen = 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) */
|
||||
save_pfirst = pfirst;
|
||||
bus->glom = NULL;
|
||||
plast = NULL;
|
||||
|
||||
for (num = 0; pfirst; rxseq++, pfirst = pnext) {
|
||||
|
@ -1850,10 +1731,10 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
|
|||
rxseq++, rxleft--) {
|
||||
|
||||
/* Handle glomming separately */
|
||||
if (bus->glom || bus->glomd) {
|
||||
if (bus->glomd || !skb_queue_empty(&bus->glom)) {
|
||||
u8 cnt;
|
||||
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);
|
||||
brcmf_dbg(GLOM, "rxglom returned %d\n", cnt);
|
||||
rxseq += cnt - 1;
|
||||
|
@ -3210,135 +3091,11 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus)
|
|||
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)
|
||||
{
|
||||
uint retries;
|
||||
u32 regdata;
|
||||
int bcmerror = 0;
|
||||
struct chip_info *ci = bus->ci;
|
||||
|
||||
/* To enter download state, disable ARM and reset SOCRAM.
|
||||
* 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) {
|
||||
bus->alp_only = true;
|
||||
|
||||
brcmf_sdbrcm_chip_disablecore(bus->sdiodev,
|
||||
bus->ci->armcorebase);
|
||||
ci->coredisable(bus->sdiodev, ci, BCMA_CORE_ARM_CM3);
|
||||
|
||||
brcmf_sdbrcm_chip_resetcore(bus->sdiodev, bus->ci->ramcorebase);
|
||||
ci->resetcore(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM);
|
||||
|
||||
/* Clear the top bit of memory */
|
||||
if (bus->ramsize) {
|
||||
|
@ -3358,11 +3114,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
|
|||
(u8 *)&zeros, 4);
|
||||
}
|
||||
} else {
|
||||
regdata = brcmf_sdcard_reg_read(bus->sdiodev,
|
||||
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) {
|
||||
if (!ci->iscoreup(bus->sdiodev, ci, BCMA_CORE_INTERNAL_MEM)) {
|
||||
brcmf_dbg(ERROR, "SOCRAM core is down after reset?\n");
|
||||
bcmerror = -EBADE;
|
||||
goto fail;
|
||||
|
@ -3377,7 +3129,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter)
|
|||
w_sdreg32(bus, 0xFFFFFFFF,
|
||||
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. */
|
||||
bus->alp_only = false;
|
||||
|
@ -3661,11 +3413,7 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
|
|||
/* Clear any held glomming stuff */
|
||||
if (bus->glomd)
|
||||
brcmu_pkt_buf_free_skb(bus->glomd);
|
||||
|
||||
if (bus->glom)
|
||||
brcmu_pkt_buf_free_skb(bus->glom);
|
||||
|
||||
bus->glom = bus->glomd = NULL;
|
||||
brcmf_sdbrcm_free_glom(bus);
|
||||
|
||||
/* Clear rx control and wake any waiters */
|
||||
bus->rxlen = 0;
|
||||
|
@ -3950,269 +3698,6 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus)
|
|||
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
|
||||
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 reg_addr;
|
||||
u32 reg_val;
|
||||
u8 idx;
|
||||
|
||||
bus->alp_only = true;
|
||||
|
||||
|
@ -4234,7 +3720,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
|
|||
#endif /* BCMDBG */
|
||||
|
||||
/*
|
||||
* Force PLL off until brcmf_sdbrcm_chip_attach()
|
||||
* Force PLL off until brcmf_sdio_chip_attach()
|
||||
* programs PLL control regs
|
||||
*/
|
||||
|
||||
|
@ -4252,8 +3738,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (brcmf_sdbrcm_chip_attach(bus, regsva)) {
|
||||
brcmf_dbg(ERROR, "brcmf_sdbrcm_chip_attach failed!\n");
|
||||
if (brcmf_sdio_chip_attach(bus->sdiodev, &bus->ci, regsva)) {
|
||||
brcmf_dbg(ERROR, "brcmf_sdio_chip_attach failed!\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -4262,11 +3748,10 @@ brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva)
|
|||
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... */
|
||||
brcmf_sdcard_reg_read(bus->sdiodev,
|
||||
CORE_SB(bus->ci->armcorebase, sbidhigh), 4);
|
||||
/* Get info on the SOCRAM cores... */
|
||||
bus->ramsize = bus->ci->ramsize;
|
||||
if (!(bus->ramsize)) {
|
||||
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 */
|
||||
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);
|
||||
reg_val = brcmf_sdcard_reg_read(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)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
@ -4380,7 +3857,7 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus)
|
|||
if (bus->ci) {
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
|
||||
brcmf_sdbrcm_chip_detach(bus);
|
||||
brcmf_sdio_chip_detach(&bus->ci);
|
||||
if (bus->vars && bus->varsz)
|
||||
kfree(bus->vars);
|
||||
bus->vars = NULL;
|
||||
|
@ -4440,6 +3917,7 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
|
|||
|
||||
bus->sdiodev = sdiodev;
|
||||
sdiodev->bus = bus;
|
||||
skb_queue_head_init(&bus->glom);
|
||||
bus->txbound = BRCMF_TXBOUND;
|
||||
bus->rxbound = BRCMF_RXBOUND;
|
||||
bus->txminmax = BRCMF_TXMINMAX;
|
||||
|
@ -4521,9 +3999,10 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
/* Ok, have the per-port tell the stack we're open for business */
|
||||
if (brcmf_net_attach(bus->drvr, 0) != 0) {
|
||||
brcmf_dbg(ERROR, "Net attach failed!!\n");
|
||||
|
||||
/* add interface and open for business */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -4554,10 +4033,6 @@ struct device *brcmf_bus_get_device(struct brcmf_bus *bus)
|
|||
void
|
||||
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 */
|
||||
if (!wdtick && bus->wd_timer_valid == true) {
|
||||
del_timer_sync(&bus->timer);
|
||||
|
@ -4566,6 +4041,10 @@ brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
|
|||
return;
|
||||
}
|
||||
|
||||
/* don't start the wd until fw is loaded */
|
||||
if (bus->drvr->busstate == BRCMF_BUS_DOWN)
|
||||
return;
|
||||
|
||||
if (wdtick) {
|
||||
if (bus->save_ms != BRCMF_WD_POLL_MS) {
|
||||
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,
|
||||
struct brcmf_bss_info *bi)
|
||||
struct brcmf_bss_info_le *bi)
|
||||
{
|
||||
struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
|
||||
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_ielen, notify_signal, GFP_KERNEL);
|
||||
|
||||
if (!bss) {
|
||||
WL_ERR("cfg80211_inform_bss_frame error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!bss)
|
||||
return -ENOMEM;
|
||||
|
||||
cfg80211_put_bss(bss);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
if (err)
|
||||
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 ieee80211_channel *notify_channel;
|
||||
struct brcmf_bss_info *bi = NULL;
|
||||
struct brcmf_bss_info_le *bi = NULL;
|
||||
struct ieee80211_supported_band *band;
|
||||
struct cfg80211_bss *bss;
|
||||
u8 *buf = NULL;
|
||||
s32 err = 0;
|
||||
u16 channel;
|
||||
|
@ -2114,7 +2124,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
|
|||
goto CleanUp;
|
||||
}
|
||||
|
||||
bi = (struct brcmf_bss_info *)(buf + 4);
|
||||
bi = (struct brcmf_bss_info_le *)(buf + 4);
|
||||
|
||||
channel = bi->ctl_ch ? bi->ctl_ch :
|
||||
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("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_ie, notify_ielen, notify_signal, GFP_KERNEL);
|
||||
|
||||
if (!bss) {
|
||||
err = -ENOMEM;
|
||||
goto CleanUp;
|
||||
}
|
||||
|
||||
cfg80211_put_bss(bss);
|
||||
|
||||
CleanUp:
|
||||
|
||||
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)
|
||||
{
|
||||
struct brcmf_bss_info *bi;
|
||||
struct brcmf_bss_info_le *bi;
|
||||
struct brcmf_ssid *ssid;
|
||||
struct brcmf_tlv *tim;
|
||||
u16 beacon_interval;
|
||||
|
@ -2211,7 +2228,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
|
|||
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);
|
||||
if (err)
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
struct device *busdev,
|
||||
void *data);
|
||||
|
|
|
@ -38,88 +38,12 @@
|
|||
/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
|
||||
#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: */
|
||||
#define SI_CC_IDX 0
|
||||
|
||||
/* SOC Interconnect types (aka chip types) */
|
||||
#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
|
||||
* 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);
|
||||
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"
|
||||
" 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 ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
|
||||
((u8) (p->priority) == tid)) {
|
||||
|
||||
plen = brcmu_pkttotlen(p) +
|
||||
AMPDU_MAX_MPDU_OVERHEAD;
|
||||
plen = p->len + AMPDU_MAX_MPDU_OVERHEAD;
|
||||
plen = max(scb_ampdu->min_len, plen);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#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
|
||||
brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
|
||||
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];
|
||||
}
|
||||
|
||||
#ifdef POWER_DBG
|
||||
wlc_phy_txpower_limits_dump(txpwr);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <linux/slab.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
|
@ -22,6 +21,7 @@
|
|||
#include <aiutils.h>
|
||||
#include "types.h"
|
||||
#include "dma.h"
|
||||
#include "soc.h"
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
uint dmactrlflags = di->dma.dmactrlflags;
|
||||
uint dmactrlflags;
|
||||
|
||||
if (di == NULL) {
|
||||
DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
|
||||
DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
dmactrlflags = di->dma.dmactrlflags;
|
||||
dmactrlflags &= ~mask;
|
||||
dmactrlflags |= flags;
|
||||
|
||||
|
@ -900,7 +901,7 @@ static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)
|
|||
|
||||
/*
|
||||
* !! 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
|
||||
* supported with pkts chain
|
||||
* 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
|
||||
* 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 sk_buff *p, *head, *tail;
|
||||
struct sk_buff_head dma_frames;
|
||||
struct sk_buff *p, *next;
|
||||
uint len;
|
||||
uint pkt_len;
|
||||
int resid = 0;
|
||||
int pktcnt = 1;
|
||||
|
||||
skb_queue_head_init(&dma_frames);
|
||||
next_frame:
|
||||
head = _dma_getnextrxp(di, false);
|
||||
if (head == NULL)
|
||||
return NULL;
|
||||
p = _dma_getnextrxp(di, false);
|
||||
if (p == 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_spin_for_len(len, head);
|
||||
dma_spin_for_len(len, p);
|
||||
|
||||
/* set actual length */
|
||||
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);
|
||||
|
||||
/* check for single or multi-buffer rx */
|
||||
if (resid > 0) {
|
||||
tail = head;
|
||||
while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
|
||||
tail->next = p;
|
||||
pkt_len = min_t(uint, resid, di->rxbufsize);
|
||||
__skb_trim(p, pkt_len);
|
||||
|
||||
tail = p;
|
||||
skb_queue_tail(&dma_frames, p);
|
||||
resid -= di->rxbufsize;
|
||||
pktcnt++;
|
||||
}
|
||||
|
||||
#ifdef BCMDBG
|
||||
|
@ -958,13 +961,18 @@ struct sk_buff *dma_rx(struct dma_pub *pub)
|
|||
if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
|
||||
DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
|
||||
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++;
|
||||
pktcnt = 1;
|
||||
goto next_frame;
|
||||
}
|
||||
}
|
||||
|
||||
return head;
|
||||
skb_queue_splice_tail(&dma_frames, skb_list);
|
||||
return pktcnt;
|
||||
}
|
||||
|
||||
static bool dma64_rxidle(struct dma_info *di)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define _BRCM_DMA_H_
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include "types.h" /* forward structure declarations */
|
||||
|
||||
/* 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);
|
||||
|
||||
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_rxreset(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 = {
|
||||
/* from include/linux/ieee80211.h */
|
||||
.cap = IEEE80211_HT_CAP_GRN_FLD |
|
||||
IEEE80211_HT_CAP_SGI_20 |
|
||||
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
|
||||
IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40,
|
||||
.ht_supported = true,
|
||||
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
.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,
|
||||
.ht_cap = {
|
||||
.cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
|
||||
IEEE80211_HT_CAP_SGI_40 |
|
||||
IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */
|
||||
IEEE80211_HT_CAP_SGI_40,
|
||||
.ht_supported = true,
|
||||
.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
.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;
|
||||
bool blocked;
|
||||
int err;
|
||||
|
||||
ieee80211_wake_queues(hw);
|
||||
spin_lock_bh(&wl->lock);
|
||||
|
@ -295,33 +294,10 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
|
|||
if (!blocked)
|
||||
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);
|
||||
/* avoid acknowledging frames before a non-monitor device is added */
|
||||
wl->mute_tx = true;
|
||||
|
||||
if (!wl->pub->up)
|
||||
err = brcms_up(wl);
|
||||
else
|
||||
|
@ -331,16 +307,28 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
if (err != 0)
|
||||
wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
|
||||
err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
static void brcms_ops_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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->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
|
||||
* 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.
|
||||
*/
|
||||
static void brcms_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct brcms_info *wl;
|
||||
struct ieee80211_hw *hw;
|
||||
int status;
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct brcms_info *wl = hw->priv;
|
||||
|
||||
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) {
|
||||
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
|
||||
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
|
||||
ieee80211_unregister_hw(hw);
|
||||
spin_lock_bh(&wl->lock);
|
||||
brcms_down(wl);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
}
|
||||
pci_disable_device(pdev);
|
||||
|
||||
|
@ -1081,9 +1066,6 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
|
|||
|
||||
wl->pub->ieee_hw = hw;
|
||||
|
||||
/* disable mpc */
|
||||
brcms_c_set_radio_mpc(wl->wlc, false);
|
||||
|
||||
/* register our interrupt handler */
|
||||
if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
|
||||
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);
|
||||
brcms_reset(wl);
|
||||
|
||||
brcms_c_init(wl->wlc);
|
||||
brcms_c_init(wl->wlc, wl->mute_tx);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1337,6 +1318,14 @@ uint brcms_reset(struct brcms_info *wl)
|
|||
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
|
||||
* during interrupt state transition.
|
||||
|
|
|
@ -80,6 +80,7 @@ struct brcms_info {
|
|||
struct brcms_firmware fw;
|
||||
struct wiphy *wiphy;
|
||||
struct brcms_ucode ucode;
|
||||
bool mute_tx;
|
||||
};
|
||||
|
||||
/* 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_dpc(unsigned long data);
|
||||
extern void brcms_timer(struct brcms_timer *t);
|
||||
extern void brcms_fatal_error(struct brcms_info *wl);
|
||||
|
||||
#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 */
|
||||
#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
|
||||
|
||||
#define AC_COUNT 4
|
||||
|
||||
/* Macros for doing definition and get/set of bitfields
|
||||
* Usage example, e.g. a three-bit field (bits 4-6):
|
||||
* #define <NAME>_M BITFIELD_MASK(3)
|
||||
|
@ -427,11 +425,6 @@ struct brcms_txq_info {
|
|||
* bandinit_pending: track band init in auto band.
|
||||
* radio_monitor: radio timer is running.
|
||||
* 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.
|
||||
* radio_timer: timer for hw radio button monitor routine.
|
||||
* monitor: monitor (MPDU sniffing) mode.
|
||||
|
@ -441,7 +434,7 @@ struct brcms_txq_info {
|
|||
* bcn_li_dtim: beacon listen interval in # dtims.
|
||||
* WDarmed: watchdog timer is armed.
|
||||
* 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.
|
||||
* tx_prec_map: Precedence map based on HW FIFO space.
|
||||
* fifo2prec_map[NFIFO]: pointer to fifo2_prec map based on WME.
|
||||
|
@ -522,12 +515,6 @@ struct brcms_c_info {
|
|||
bool radio_monitor;
|
||||
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 *radio_timer;
|
||||
|
||||
|
@ -546,9 +533,9 @@ struct brcms_c_info {
|
|||
u32 WDlast;
|
||||
|
||||
/* 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 fifo2prec_map[NFIFO];
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ static const struct chan_info_basic chan_info_all[] = {
|
|||
{216, 50800}
|
||||
};
|
||||
|
||||
const u8 ofdm_rate_lookup[] = {
|
||||
static const u8 ofdm_rate_lookup[] = {
|
||||
|
||||
BRCM_RATE_48M,
|
||||
BRCM_RATE_24M,
|
||||
|
@ -190,15 +190,7 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
|
|||
data = R_REG(&pi->regs->radioregdata);
|
||||
} else {
|
||||
W_REG_FLUSH(&pi->regs->phy4waddr, addr);
|
||||
|
||||
#ifdef __ARM_ARCH_4T__
|
||||
__asm__(" .align 4 ");
|
||||
__asm__(" nop ");
|
||||
data = R_REG(&pi->regs->phy4wdatalo);
|
||||
#else
|
||||
data = R_REG(&pi->regs->phy4wdatalo);
|
||||
#endif
|
||||
|
||||
}
|
||||
pi->phy_wreg = 0;
|
||||
|
||||
|
|
|
@ -774,11 +774,6 @@ struct brcms_phy {
|
|||
s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
|
||||
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_elna_gain_config;
|
||||
u16 old_bphy_test;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "phy_radio.h"
|
||||
#include "phyreg_n.h"
|
||||
#include "phytbl_n.h"
|
||||
#include "soc.h"
|
||||
|
||||
#define READ_RADIO_REG2(pi, radio_type, jspace, core, 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) {
|
||||
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 =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP2GA0);
|
||||
|
@ -14486,12 +14481,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
|
|||
break;
|
||||
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 =
|
||||
(s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0);
|
||||
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;
|
||||
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 =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
BRCMS_SROM_MAXP5GLA0);
|
||||
|
@ -14615,12 +14598,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
|
|||
break;
|
||||
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 =
|
||||
(s8) wlapi_getintvar(shim,
|
||||
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);
|
||||
switch (chan_freq_range) {
|
||||
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:
|
||||
txpi[0] = pi->nphy_txpid5gl[0];
|
||||
txpi[1] = pi->nphy_txpid5gl[1];
|
||||
break;
|
||||
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:
|
||||
txpi[0] = pi->nphy_txpid5gh[0];
|
||||
txpi[1] = pi->nphy_txpid5gh[1];
|
||||
txpi[0] = 0;
|
||||
txpi[1] = 0;
|
||||
break;
|
||||
default:
|
||||
txpi[0] = txpi[1] = 91;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "pub.h"
|
||||
#include "aiutils.h"
|
||||
#include "pmu.h"
|
||||
#include "soc.h"
|
||||
|
||||
/*
|
||||
* external LPO crystal frequency
|
||||
|
|
|
@ -170,22 +170,6 @@ enum brcms_srom_id {
|
|||
BRCMS_SROM_TSSIPOS2G,
|
||||
BRCMS_SROM_TSSIPOS5G,
|
||||
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)
|
||||
*/
|
||||
|
@ -225,10 +209,6 @@ enum brcms_srom_id {
|
|||
BRCMS_SROM_PA2GW2A1,
|
||||
BRCMS_SROM_PA2GW2A2,
|
||||
BRCMS_SROM_PA2GW2A3,
|
||||
BRCMS_SROM_PA2GW3A0,
|
||||
BRCMS_SROM_PA2GW3A1,
|
||||
BRCMS_SROM_PA2GW3A2,
|
||||
BRCMS_SROM_PA2GW3A3,
|
||||
BRCMS_SROM_PA5GHW0A0,
|
||||
BRCMS_SROM_PA5GHW0A1,
|
||||
BRCMS_SROM_PA5GHW0A2,
|
||||
|
@ -241,10 +221,6 @@ enum brcms_srom_id {
|
|||
BRCMS_SROM_PA5GHW2A1,
|
||||
BRCMS_SROM_PA5GHW2A2,
|
||||
BRCMS_SROM_PA5GHW2A3,
|
||||
BRCMS_SROM_PA5GHW3A0,
|
||||
BRCMS_SROM_PA5GHW3A1,
|
||||
BRCMS_SROM_PA5GHW3A2,
|
||||
BRCMS_SROM_PA5GHW3A3,
|
||||
BRCMS_SROM_PA5GLW0A0,
|
||||
BRCMS_SROM_PA5GLW0A1,
|
||||
BRCMS_SROM_PA5GLW0A2,
|
||||
|
@ -257,10 +233,6 @@ enum brcms_srom_id {
|
|||
BRCMS_SROM_PA5GLW2A1,
|
||||
BRCMS_SROM_PA5GLW2A2,
|
||||
BRCMS_SROM_PA5GLW2A3,
|
||||
BRCMS_SROM_PA5GLW3A0,
|
||||
BRCMS_SROM_PA5GLW3A1,
|
||||
BRCMS_SROM_PA5GLW3A2,
|
||||
BRCMS_SROM_PA5GLW3A3,
|
||||
BRCMS_SROM_PA5GW0A0,
|
||||
BRCMS_SROM_PA5GW0A1,
|
||||
BRCMS_SROM_PA5GW0A2,
|
||||
|
@ -273,14 +245,9 @@ enum brcms_srom_id {
|
|||
BRCMS_SROM_PA5GW2A1,
|
||||
BRCMS_SROM_PA5GW2A2,
|
||||
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 D11_PHY_HDR_LEN 6 /* Phy header length - 6 bytes */
|
||||
|
||||
/* phy types */
|
||||
#define PHY_TYPE_A 0 /* Phy type A */
|
||||
|
@ -414,7 +381,6 @@ struct brcms_pub {
|
|||
uint _nbands; /* # bands supported */
|
||||
uint now; /* # elapsed seconds */
|
||||
|
||||
bool promisc; /* promiscuous destination address */
|
||||
bool delayed_down; /* down delayed */
|
||||
bool associated; /* true:part of [I]BSS, false: not */
|
||||
/* (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 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_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);
|
||||
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 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 void brcms_c_mute(struct brcms_c_info *wlc, bool on);
|
||||
|
||||
#endif /* _BRCM_PUB_H_ */
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "types.h"
|
||||
#include "d11.h"
|
||||
#include "phy_hal.h"
|
||||
|
||||
extern const u8 rate_info[];
|
||||
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
|
||||
* increments */
|
||||
extern const u8 ofdm_rate_lookup[];
|
||||
|
||||
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)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "aiutils.h"
|
||||
#include "otp.h"
|
||||
#include "srom.h"
|
||||
#include "soc.h"
|
||||
|
||||
/*
|
||||
* SROM CRC8 polynomial value:
|
||||
|
@ -62,9 +63,6 @@
|
|||
#define SROM_MACHI_ET1 42
|
||||
#define SROM_MACMID_ET1 43
|
||||
#define SROM_MACLO_ET1 44
|
||||
#define SROM3_MACHI 37
|
||||
#define SROM3_MACMID 38
|
||||
#define SROM3_MACLO 39
|
||||
|
||||
#define SROM_BXARSSI2G 40
|
||||
#define SROM_BXARSSI5G 41
|
||||
|
@ -101,7 +99,6 @@
|
|||
|
||||
#define SROM_BFL 57
|
||||
#define SROM_BFL2 28
|
||||
#define SROM3_BFL2 61
|
||||
|
||||
#define SROM_AG10 58
|
||||
|
||||
|
@ -109,99 +106,16 @@
|
|||
|
||||
#define SROM_OPO 60
|
||||
|
||||
#define SROM3_LEDDC 62
|
||||
|
||||
#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_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_SHIFT 0
|
||||
#define SROM4_RXCHAIN_MASK 0x00f0
|
||||
#define SROM4_RXCHAIN_SHIFT 4
|
||||
#define SROM4_SWITCH_MASK 0xff00
|
||||
#define SROM4_SWITCH_SHIFT 8
|
||||
|
||||
/* Per-path fields */
|
||||
#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
|
||||
|
||||
|
@ -424,103 +338,32 @@ struct brcms_varbuf {
|
|||
static const struct brcms_sromvar pci_sromvars[] = {
|
||||
{BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID,
|
||||
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_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,
|
||||
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,
|
||||
0xffff},
|
||||
{BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 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_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_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_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
|
||||
{BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
|
||||
{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_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
|
||||
{BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
|
||||
{BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
|
||||
{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_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_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_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_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00},
|
||||
{BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff},
|
||||
{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_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 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_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
|
||||
{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_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
|
||||
{BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
|
||||
{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_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
|
||||
{BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
|
||||
{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_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00},
|
||||
{BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
|
||||
{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_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,
|
||||
SROM4_TXCHAIN_MASK},
|
||||
{BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
|
||||
|
@ -594,43 +417,11 @@ static const struct brcms_sromvar pci_sromvars[] = {
|
|||
SROM8_FEM_ANTSWLUT_MASK},
|
||||
{BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00},
|
||||
{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_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,
|
||||
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,
|
||||
0x01ff},
|
||||
{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,
|
||||
0x00ff},
|
||||
|
||||
{BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_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_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 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_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 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_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 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_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 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_STBCPO, 0x00000100, 0, SROM8_STBCPO, 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[] = {
|
||||
{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_ITT2GA0, 0xffffff00, 0, SROM8_2G_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. */
|
||||
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)
|
||||
{
|
||||
if (sih->ccrev < 32)
|
||||
return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET);
|
||||
return curmap + PCI_BAR0_SPROM_OFFSET;
|
||||
if (sih->cccaps & CC_CAP_SROM)
|
||||
return (u16 __iomem *)
|
||||
(curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP);
|
||||
return curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP;
|
||||
|
||||
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)
|
||||
{
|
||||
uint i;
|
||||
|
@ -906,18 +617,16 @@ static uint mask_width(u16 mask)
|
|||
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 (size--)
|
||||
*(buf + size) = le16_to_cpu(*(__le16 *)(buf + size));
|
||||
while (nwords--)
|
||||
*(buf + nwords) = le16_to_cpu(*(__le16 *)(buf + nwords));
|
||||
}
|
||||
|
||||
static inline void htol16_buf(u16 *buf, unsigned int size)
|
||||
static inline void cpu_to_le16_buf(u16 *buf, uint nwords)
|
||||
{
|
||||
size /= 2;
|
||||
while (size--)
|
||||
*(__le16 *)(buf + size) = cpu_to_le16(*(buf + size));
|
||||
while (nwords--)
|
||||
*(__le16 *)(buf + nwords) = cpu_to_le16(*(buf + nwords));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -929,11 +638,14 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
|
|||
struct brcms_srom_list_head *entry;
|
||||
enum brcms_srom_id id;
|
||||
u16 w;
|
||||
u32 val;
|
||||
u32 val = 0;
|
||||
const struct brcms_sromvar *srv;
|
||||
uint width;
|
||||
uint flags;
|
||||
u32 sr = (1 << sromrev);
|
||||
uint p;
|
||||
uint pb = SROM8_PATH0;
|
||||
const uint psz = SROM8_PATH1 - SROM8_PATH0;
|
||||
|
||||
/* first store the srom revision */
|
||||
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);
|
||||
}
|
||||
|
||||
if (sromrev >= 4) {
|
||||
/* Do per-path variables */
|
||||
uint p, pb, psz;
|
||||
for (p = 0; p < MAX_PATH_SROM; p++) {
|
||||
for (srv = perpath_pci_sromvars;
|
||||
srv->varid != BRCMS_SROM_NULL; srv++) {
|
||||
if ((srv->revmask & sr) == 0)
|
||||
continue;
|
||||
|
||||
if (sromrev >= 8) {
|
||||
pb = SROM8_PATH0;
|
||||
psz = SROM8_PATH1 - SROM8_PATH0;
|
||||
} else {
|
||||
pb = SROM4_PATH0;
|
||||
psz = SROM4_PATH1 - SROM4_PATH0;
|
||||
}
|
||||
|
||||
for (p = 0; p < MAX_PATH_SROM; p++) {
|
||||
for (srv = perpath_pci_sromvars;
|
||||
srv->varid != BRCMS_SROM_NULL; srv++) {
|
||||
if ((srv->revmask & sr) == 0)
|
||||
continue;
|
||||
|
||||
if (srv->flags & SRFL_NOVAR)
|
||||
continue;
|
||||
|
||||
w = srom[pb + srv->off];
|
||||
val = (w & srv->mask) >> mask_shift(srv->mask);
|
||||
width = mask_width(srv->mask);
|
||||
|
||||
/* 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;
|
||||
if (srv->flags & SRFL_NOVAR)
|
||||
continue;
|
||||
|
||||
w = srom[pb + srv->off];
|
||||
val = (w & srv->mask) >> mask_shift(srv->mask);
|
||||
width = mask_width(srv->mask);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1080,41 +779,38 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
|
|||
* Return 0 on success, nonzero on error.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
int err = 0;
|
||||
uint i;
|
||||
u8 *bbuf = (u8 *)buf; /* byte buffer */
|
||||
uint nbytes = nwords << 1;
|
||||
|
||||
/* read the sprom */
|
||||
for (i = 0; i < nwords; i++)
|
||||
buf[i] = R_REG(&sprom[wordoff + i]);
|
||||
/* read the sprom in bytes */
|
||||
for (i = 0; i < nbytes; i++)
|
||||
bbuf[i] = readb(sprom+i);
|
||||
|
||||
if (check_crc) {
|
||||
|
||||
if (buf[0] == 0xffff)
|
||||
/*
|
||||
* The hardware thinks that an srom that starts with
|
||||
* 0xffff is blank, regardless of the rest of the
|
||||
* content, so declare it bad.
|
||||
*/
|
||||
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 (buf[0] == 0xffff)
|
||||
/*
|
||||
* The hardware thinks that an srom that starts with
|
||||
* 0xffff is blank, regardless of the rest of the
|
||||
* content, so declare it bad.
|
||||
*/
|
||||
return -ENODATA;
|
||||
|
||||
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 */
|
||||
ltoh16_buf(buf, nwords * 2);
|
||||
}
|
||||
le16_to_cpu_buf(buf, nwords);
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
memcpy(buf, otp, bufsz);
|
||||
sz = min_t(uint, sz, nwords);
|
||||
memcpy(buf, otp, sz * 2);
|
||||
|
||||
kfree(otp);
|
||||
|
||||
|
@ -1139,13 +836,13 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
|
|||
return -ENODATA;
|
||||
|
||||
/* fixup the endianness so crc8 will pass */
|
||||
htol16_buf(buf, bufsz);
|
||||
if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2,
|
||||
cpu_to_le16_buf(buf, sz);
|
||||
if (crc8(brcms_srom_crc8_table, (u8 *) buf, sz * 2,
|
||||
CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table))
|
||||
err = -EIO;
|
||||
|
||||
/* now correct the endianness of the byte array */
|
||||
ltoh16_buf(buf, bufsz);
|
||||
else
|
||||
/* now correct the endianness of the byte array */
|
||||
le16_to_cpu_buf(buf, sz);
|
||||
|
||||
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)
|
||||
{
|
||||
u16 *srom;
|
||||
u16 __iomem *sromwindow;
|
||||
u8 __iomem *sromwindow;
|
||||
u8 sromrev = 0;
|
||||
u32 sr;
|
||||
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);
|
||||
if (ai_is_sprom_available(sih)) {
|
||||
err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
|
||||
true);
|
||||
err = sprom_read_pci(sih, sromwindow, 0, srom,
|
||||
SROM4_WORDS, true);
|
||||
|
||||
if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
|
||||
(((sih->buscoretype == PCIE_CORE_ID)
|
||||
&& (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 */
|
||||
if (err == 0)
|
||||
/* srom read and passed crc */
|
||||
/* top word of sprom contains version and crc8 */
|
||||
sromrev = srom[SROM_CRCREV] & 0xff;
|
||||
/* bcm4401 sroms misprogrammed */
|
||||
if (sromrev == 0x10)
|
||||
sromrev = 1;
|
||||
}
|
||||
sromrev = srom[SROM4_CRCREV] & 0xff;
|
||||
} else {
|
||||
/* 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)
|
||||
/* OTP only contain SROM rev8/rev9 for now */
|
||||
sromrev = srom[SROM4_CRCREV] & 0xff;
|
||||
|
@ -1208,10 +892,9 @@ static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
|
|||
sr = 1 << sromrev;
|
||||
|
||||
/*
|
||||
* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8,
|
||||
* 9
|
||||
* srom version check: Current valid versions: 8, 9
|
||||
*/
|
||||
if ((sr & 0x33e) == 0) {
|
||||
if ((sr & 0x300) == 0) {
|
||||
err = -EINVAL;
|
||||
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,
|
||||
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_ */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <brcmu_utils.h>
|
||||
|
||||
MODULE_AUTHOR("Broadcom Corporation");
|
||||
|
@ -40,74 +41,20 @@ EXPORT_SYMBOL(brcmu_pkt_buf_get_skb);
|
|||
/* Free the driver packet. Free the tag if present */
|
||||
void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
int nest = 0;
|
||||
|
||||
/* perversion: we use skb->next to chain multi-skb packets */
|
||||
while (skb) {
|
||||
nskb = skb->next;
|
||||
skb->next = NULL;
|
||||
|
||||
if (skb->destructor)
|
||||
/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
|
||||
* destructor exists
|
||||
*/
|
||||
dev_kfree_skb_any(skb);
|
||||
else
|
||||
/* can free immediately (even in_irq()) if destructor
|
||||
* does not exist
|
||||
*/
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
nest++;
|
||||
skb = nskb;
|
||||
}
|
||||
WARN_ON(skb->next);
|
||||
if (skb->destructor)
|
||||
/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
|
||||
* destructor exists
|
||||
*/
|
||||
dev_kfree_skb_any(skb);
|
||||
else
|
||||
/* can free immediately (even in_irq()) if destructor
|
||||
* does not exist
|
||||
*/
|
||||
dev_kfree_skb(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
|
||||
* 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 *p)
|
||||
{
|
||||
struct pktq_prec *q;
|
||||
struct sk_buff_head *q;
|
||||
|
||||
if (pktq_full(pq) || pktq_pfull(pq, prec))
|
||||
return NULL;
|
||||
|
||||
q = &pq->q[prec];
|
||||
|
||||
if (q->head)
|
||||
q->tail->prev = p;
|
||||
else
|
||||
q->head = p;
|
||||
|
||||
q->tail = p;
|
||||
q->len++;
|
||||
|
||||
q = &pq->q[prec].skblist;
|
||||
skb_queue_tail(q, p);
|
||||
pq->len++;
|
||||
|
||||
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 *p)
|
||||
{
|
||||
struct pktq_prec *q;
|
||||
struct sk_buff_head *q;
|
||||
|
||||
if (pktq_full(pq) || pktq_pfull(pq, prec))
|
||||
return NULL;
|
||||
|
||||
q = &pq->q[prec];
|
||||
|
||||
if (q->head == NULL)
|
||||
q->tail = p;
|
||||
|
||||
p->prev = q->head;
|
||||
q->head = p;
|
||||
q->len++;
|
||||
|
||||
q = &pq->q[prec].skblist;
|
||||
skb_queue_head(q, p);
|
||||
pq->len++;
|
||||
|
||||
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 pktq_prec *q;
|
||||
struct sk_buff_head *q;
|
||||
struct sk_buff *p;
|
||||
|
||||
q = &pq->q[prec];
|
||||
|
||||
p = q->head;
|
||||
q = &pq->q[prec].skblist;
|
||||
p = skb_dequeue(q);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
q->head = p->prev;
|
||||
if (q->head == NULL)
|
||||
q->tail = NULL;
|
||||
|
||||
q->len--;
|
||||
|
||||
pq->len--;
|
||||
|
||||
p->prev = NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(brcmu_pktq_pdeq);
|
||||
|
||||
struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec)
|
||||
{
|
||||
struct pktq_prec *q;
|
||||
struct sk_buff *p, *prev;
|
||||
struct sk_buff_head *q;
|
||||
struct sk_buff *p;
|
||||
|
||||
q = &pq->q[prec];
|
||||
|
||||
p = q->head;
|
||||
q = &pq->q[prec].skblist;
|
||||
p = skb_dequeue_tail(q);
|
||||
if (p == 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--;
|
||||
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(brcmu_pktq_pdeq_tail);
|
||||
|
@ -222,31 +131,17 @@ void
|
|||
brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
|
||||
bool (*fn)(struct sk_buff *, void *), void *arg)
|
||||
{
|
||||
struct pktq_prec *q;
|
||||
struct sk_buff *p, *prev = NULL;
|
||||
struct sk_buff_head *q;
|
||||
struct sk_buff *p, *next;
|
||||
|
||||
q = &pq->q[prec];
|
||||
p = q->head;
|
||||
while (p) {
|
||||
q = &pq->q[prec].skblist;
|
||||
skb_queue_walk_safe(q, p, next) {
|
||||
if (fn == NULL || (*fn) (p, arg)) {
|
||||
bool head = (p == q->head);
|
||||
if (head)
|
||||
q->head = p->prev;
|
||||
else
|
||||
prev->prev = p->prev;
|
||||
p->prev = NULL;
|
||||
skb_unlink(p, q);
|
||||
brcmu_pkt_buf_free_skb(p);
|
||||
q->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);
|
||||
|
||||
|
@ -271,8 +166,10 @@ void brcmu_pktq_init(struct pktq *pq, int num_prec, int 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;
|
||||
skb_queue_head_init(&pq->q[prec].skblist);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(brcmu_pktq_init);
|
||||
|
||||
|
@ -284,13 +181,13 @@ struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out)
|
|||
return NULL;
|
||||
|
||||
for (prec = 0; prec < pq->hi_prec; prec++)
|
||||
if (pq->q[prec].head)
|
||||
if (!skb_queue_empty(&pq->q[prec].skblist))
|
||||
break;
|
||||
|
||||
if (prec_out)
|
||||
*prec_out = prec;
|
||||
|
||||
return pq->q[prec].tail;
|
||||
return skb_peek_tail(&pq->q[prec].skblist);
|
||||
}
|
||||
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++)
|
||||
if (prec_bmp & (1 << prec))
|
||||
len += pq->q[prec].len;
|
||||
len += pq->q[prec].skblist.qlen;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
@ -313,39 +210,32 @@ EXPORT_SYMBOL(brcmu_pktq_mlen);
|
|||
struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
|
||||
int *prec_out)
|
||||
{
|
||||
struct pktq_prec *q;
|
||||
struct sk_buff_head *q;
|
||||
struct sk_buff *p;
|
||||
int prec;
|
||||
|
||||
if (pq->len == 0)
|
||||
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--;
|
||||
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
q = &pq->q[prec];
|
||||
|
||||
p = q->head;
|
||||
q = &pq->q[prec].skblist;
|
||||
p = skb_dequeue(q);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
q->head = p->prev;
|
||||
if (q->head == NULL)
|
||||
q->tail = NULL;
|
||||
|
||||
q->len--;
|
||||
pq->len--;
|
||||
|
||||
if (prec_out)
|
||||
*prec_out = prec;
|
||||
|
||||
pq->len--;
|
||||
|
||||
p->prev = NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(brcmu_pktq_mdeq);
|
||||
|
@ -364,23 +254,3 @@ void brcmu_prpkt(const char *msg, struct sk_buff *p0)
|
|||
}
|
||||
EXPORT_SYMBOL(brcmu_prpkt);
|
||||
#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
|
||||
|
||||
struct pktq_prec {
|
||||
struct sk_buff *head; /* first packet to dequeue */
|
||||
struct sk_buff *tail; /* last packet to dequeue */
|
||||
u16 len; /* number of queued packets */
|
||||
struct sk_buff_head skblist;
|
||||
u16 max; /* maximum number of queued packets */
|
||||
};
|
||||
|
||||
|
@ -88,32 +86,32 @@ struct pktq {
|
|||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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,
|
||||
|
@ -172,24 +170,16 @@ extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
|
|||
bool (*fn)(struct sk_buff *, void *), void *arg);
|
||||
|
||||
/* 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 */
|
||||
struct ipv4_addr;
|
||||
|
||||
|
||||
/* externs */
|
||||
/* format/print */
|
||||
#ifdef BCMDBG
|
||||
extern void brcmu_prpkt(const char *msg, struct sk_buff *p0);
|
||||
#else
|
||||
#define brcmu_prpkt(a, b)
|
||||
#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_ */
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
|
||||
#define WL_RADIO_SW_DISABLE (1<<0)
|
||||
#define WL_RADIO_HW_DISABLE (1<<1)
|
||||
#define WL_RADIO_MPC_DISABLE (1<<2)
|
||||
/* some countries don't support any channel */
|
||||
#define WL_RADIO_COUNTRY_DISABLE (1<<3)
|
||||
|
||||
|
|
|
@ -77,8 +77,9 @@
|
|||
#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 */
|
||||
/* Default component, in ai chips it maps all unused address ranges */
|
||||
#define DEF_AI_COMP 0xfff
|
||||
#define DEF_AI_COMP 0xfff /* Default component, in ai chips it
|
||||
* maps all unused address ranges
|
||||
*/
|
||||
|
||||
/* Common core control flags */
|
||||
#define SICF_BIST_EN 0x8000
|
||||
|
@ -87,4 +88,11 @@
|
|||
#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
|
||||
|
||||
#endif /* _BRCM_SOC_H */
|
||||
|
|
|
@ -131,6 +131,14 @@ static struct ieee80211_rate ipw2200_rates[] = {
|
|||
#define ipw2200_bg_rates (ipw2200_rates + 0)
|
||||
#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
|
||||
static int qos_enable = 0;
|
||||
static int qos_burst_enable = 0;
|
||||
|
|
|
@ -66,16 +66,8 @@ extern u32 libipw_debug_level;
|
|||
do { if (libipw_debug_level & (level)) \
|
||||
printk(KERN_DEBUG "libipw: %c %s " fmt, \
|
||||
in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
|
||||
static inline bool libipw_ratelimit_debug(u32 level)
|
||||
{
|
||||
return (libipw_debug_level & level) && net_ratelimit();
|
||||
}
|
||||
#else
|
||||
#define LIBIPW_DEBUG(level, fmt, args...) do {} while (0)
|
||||
static inline bool libipw_ratelimit_debug(u32 level)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_LIBIPW_DEBUG */
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# WIFI
|
||||
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-lib.o iwl-agn-calib.o iwl-io.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,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl2000_2bg_cfg = {
|
||||
.name = "2000 Series 2x2 BG",
|
||||
IWL_DEVICE_2000,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
||||
.name = "2000D Series 2x2 BGN",
|
||||
IWL_DEVICE_2000,
|
||||
|
@ -304,11 +299,6 @@ struct iwl_cfg iwl2030_2bgn_cfg = {
|
|||
.ht_params = &iwl2000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl2030_2bg_cfg = {
|
||||
.name = "2000 Series 2x2 BG/BT",
|
||||
IWL_DEVICE_2030,
|
||||
};
|
||||
|
||||
#define IWL_DEVICE_105 \
|
||||
.fw_name_pre = IWL105_FW_PRE, \
|
||||
.ucode_api_max = IWL105_UCODE_API_MAX, \
|
||||
|
@ -326,11 +316,6 @@ struct iwl_cfg iwl2030_2bg_cfg = {
|
|||
.rx_with_siso_diversity = true, \
|
||||
.iq_invert = true \
|
||||
|
||||
struct iwl_cfg iwl105_bg_cfg = {
|
||||
.name = "105 Series 1x1 BG",
|
||||
IWL_DEVICE_105,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl105_bgn_cfg = {
|
||||
.name = "105 Series 1x1 BGN",
|
||||
IWL_DEVICE_105,
|
||||
|
@ -361,11 +346,6 @@ struct iwl_cfg iwl105_bgn_d_cfg = {
|
|||
.rx_with_siso_diversity = 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 = {
|
||||
.name = "135 Series 1x1 BGN/BT",
|
||||
IWL_DEVICE_135,
|
||||
|
|
|
@ -439,16 +439,6 @@ struct iwl_cfg iwl6035_2agn_cfg = {
|
|||
.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 = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
|
||||
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_DYNAMIC:
|
||||
return IWL_NUM_IDLE_CHAINS_SINGLE;
|
||||
case IEEE80211_SMPS_AUTOMATIC:
|
||||
case IEEE80211_SMPS_OFF:
|
||||
return active_cnt;
|
||||
default:
|
||||
|
@ -983,3 +984,360 @@ void iwlagn_remove_notification(struct iwl_priv *priv,
|
|||
list_del(&wait_entry->list);
|
||||
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;
|
||||
case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
|
||||
/* avoid antenna B unless MIMO */
|
||||
valid_tx_ant =
|
||||
first_antenna(hw_params(priv).valid_tx_ant);
|
||||
if (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2)
|
||||
tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
|
||||
tbl->action = IWL_LEGACY_SWITCH_SISO;
|
||||
break;
|
||||
case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
|
||||
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
|
||||
|
@ -1636,10 +1634,8 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
|
|||
break;
|
||||
case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
|
||||
/* avoid antenna B unless MIMO */
|
||||
valid_tx_ant =
|
||||
first_antenna(hw_params(priv).valid_tx_ant);
|
||||
if (tbl->action == IWL_SISO_SWITCH_ANTENNA2)
|
||||
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
|
||||
tbl->action = IWL_SISO_SWITCH_MIMO2_AB;
|
||||
break;
|
||||
case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
|
||||
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))
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
|
@ -1055,6 +1100,8 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
|||
handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif;
|
||||
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
|
||||
* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -116,7 +117,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
|
|||
if (ctx->ht.enabled)
|
||||
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.def_qos_parm.qos_flags);
|
||||
|
||||
|
@ -124,7 +125,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
|
|||
sizeof(struct iwl_qosparam_cmd),
|
||||
&ctx->qos_data.def_qos_parm);
|
||||
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,
|
||||
|
@ -541,6 +542,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
|||
|
||||
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))) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
|
||||
goto out;
|
||||
|
@ -840,7 +844,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
|||
if (ctx->last_tx_rejected) {
|
||||
ctx->last_tx_rejected = false;
|
||||
iwl_trans_wake_any_queue(trans(priv),
|
||||
ctx->ctxid);
|
||||
ctx->ctxid,
|
||||
"Disassoc: flush queue");
|
||||
}
|
||||
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;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
struct iwl_link_quality_cmd lq;
|
||||
bool active;
|
||||
bool active, have_lq = false;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
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));
|
||||
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;
|
||||
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)
|
||||
IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
|
||||
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)
|
||||
|
@ -825,28 +829,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
|||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
#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);
|
||||
|
||||
/* 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 &&
|
||||
ctx->vif->type == NL80211_IFTYPE_STATION) {
|
||||
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,
|
||||
"TXQ %d status %s (0x%08x) "
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "iwl-dev.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}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
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 iwl_bus *bus = bus(trans);
|
||||
dma_addr_t phy_addr = image->p_addr;
|
||||
u32 byte_cnt = image->len;
|
||||
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_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);
|
||||
|
||||
iwl_write_direct32(bus(priv),
|
||||
iwl_write_direct32(bus,
|
||||
FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
|
||||
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),
|
||||
(iwl_get_dma_hi_addr(phy_addr)
|
||||
<< 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),
|
||||
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
|
||||
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
|
||||
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_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
|
||||
|
||||
IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
|
||||
ret = wait_event_timeout(priv->shrd->wait_command_queue,
|
||||
priv->ucode_write_complete, 5 * HZ);
|
||||
IWL_DEBUG_FW(bus, "%s uCode section being loaded...\n", name);
|
||||
ret = wait_event_timeout(trans->shrd->wait_command_queue,
|
||||
trans->ucode_write_complete, 5 * HZ);
|
||||
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);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -124,17 +172,41 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_load_given_ucode(struct iwl_priv *priv,
|
||||
struct fw_img *image)
|
||||
static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
|
||||
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;
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return iwlagn_load_section(priv, "DATA", &image->data,
|
||||
return iwlagn_load_section(trans, "DATA", &image->data,
|
||||
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,
|
||||
* 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)
|
||||
{
|
||||
__le32 *image = (__le32 *)fw_desc->v_addr;
|
||||
|
@ -426,15 +498,15 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv,
|
|||
u32 val;
|
||||
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)) {
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
/* NOTE: Use the debugless read so we don't flood kernel log
|
||||
* 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);
|
||||
val = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
|
||||
val = iwl_read32(bus, HBUS_TARG_MEM_RDAT);
|
||||
if (val != le32_to_cpu(*image))
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -442,7 +514,7 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv,
|
|||
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)
|
||||
{
|
||||
__le32 *image = (__le32 *)fw_desc->v_addr;
|
||||
|
@ -451,18 +523,18 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
|
|||
u32 offs;
|
||||
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);
|
||||
|
||||
for (offs = 0;
|
||||
offs < len && errors < 20;
|
||||
offs += sizeof(u32), image++) {
|
||||
/* 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)) {
|
||||
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",
|
||||
offs, val, le32_to_cpu(*image));
|
||||
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,
|
||||
* 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)) {
|
||||
IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
|
||||
struct fw_img *img = iwl_get_ucode_image(trans, ucode_type);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -519,13 +599,12 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
|
|||
#define UCODE_CALIB_TIMEOUT (2*HZ)
|
||||
|
||||
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
||||
struct fw_img *image,
|
||||
enum iwlagn_ucode_type ucode_type)
|
||||
enum iwl_ucode_type ucode_type)
|
||||
{
|
||||
struct iwl_notification_wait alive_wait;
|
||||
struct iwlagn_alive_data alive_data;
|
||||
int ret;
|
||||
enum iwlagn_ucode_type old_type;
|
||||
enum iwl_ucode_type old_type;
|
||||
|
||||
ret = iwl_trans_start_device(trans(priv));
|
||||
if (ret)
|
||||
|
@ -537,7 +616,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
|||
old_type = priv->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) {
|
||||
priv->ucode_type = old_type;
|
||||
iwlagn_remove_notification(priv, &alive_wait);
|
||||
|
@ -568,7 +647,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
|||
* skip it for WoWLAN.
|
||||
*/
|
||||
if (ucode_type != IWL_UCODE_WOWLAN) {
|
||||
ret = iwl_verify_ucode(priv, image);
|
||||
ret = iwl_verify_ucode(trans(priv), ucode_type);
|
||||
if (ret) {
|
||||
priv->ucode_type = old_type;
|
||||
return ret;
|
||||
|
@ -597,7 +676,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
|
|||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
|
||||
/* No init ucode required? Curious, but maybe ok */
|
||||
if (!priv->ucode_init.code.len)
|
||||
if (!trans(priv)->ucode_init.code.len)
|
||||
return 0;
|
||||
|
||||
if (priv->ucode_type != IWL_UCODE_NONE)
|
||||
|
@ -608,8 +687,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
|
|||
NULL, NULL);
|
||||
|
||||
/* Will also start the device */
|
||||
ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
|
||||
IWL_UCODE_INIT);
|
||||
ret = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,6 +65,12 @@
|
|||
|
||||
#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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
int iwlagn_set_pan_params(struct iwl_priv *priv);
|
||||
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);
|
||||
int iwlagn_run_init_ucode(struct iwl_priv *priv);
|
||||
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
|
||||
struct fw_img *image,
|
||||
enum iwlagn_ucode_type ucode_type);
|
||||
enum iwl_ucode_type ucode_type);
|
||||
|
||||
/* lib */
|
||||
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);
|
||||
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
|
||||
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 */
|
||||
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);
|
||||
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
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,
|
||||
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,
|
||||
struct iwl_rxon_context *ctx);
|
||||
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 */
|
||||
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_bg_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 iwl2030_2bgn_cfg;
|
||||
extern struct iwl_cfg iwl2030_2bg_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_d_cfg;
|
||||
extern struct iwl_cfg iwl135_bg_cfg;
|
||||
extern struct iwl_cfg iwl135_bgn_cfg;
|
||||
|
||||
#endif /* __iwl_pci_h__ */
|
||||
|
|
|
@ -198,6 +198,7 @@ enum {
|
|||
REPLY_WOWLAN_TKIP_PARAMS = 0xe3,
|
||||
REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4,
|
||||
REPLY_WOWLAN_GET_STATUS = 0xe5,
|
||||
REPLY_D3_CONFIG = 0xd3,
|
||||
|
||||
REPLY_MAX = 0xff
|
||||
};
|
||||
|
@ -3800,6 +3801,19 @@ struct iwl_bt_coex_prot_env_cmd {
|
|||
u8 reserved[2];
|
||||
} __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
|
||||
*/
|
||||
|
@ -3830,19 +3844,16 @@ enum iwlagn_wowlan_wakeup_filters {
|
|||
IWLAGN_WOWLAN_WAKEUP_BEACON_MISS = BIT(2),
|
||||
IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE = BIT(3),
|
||||
IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL = BIT(4),
|
||||
IWLAGN_WOWLAN_WAKEUP_RFKILL = BIT(5),
|
||||
IWLAGN_WOWLAN_WAKEUP_UCODE_ERROR = BIT(6),
|
||||
IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(7),
|
||||
IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(8),
|
||||
IWLAGN_WOWLAN_WAKEUP_ALWAYS = BIT(9),
|
||||
IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(10),
|
||||
IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ = BIT(5),
|
||||
IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE = BIT(6),
|
||||
IWLAGN_WOWLAN_WAKEUP_ALWAYS = BIT(7),
|
||||
IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT = BIT(8),
|
||||
};
|
||||
|
||||
struct iwlagn_wowlan_wakeup_filter_cmd {
|
||||
__le32 enabled;
|
||||
__le16 non_qos_seq;
|
||||
u8 min_sleep_seconds;
|
||||
u8 reserved;
|
||||
__le16 reserved;
|
||||
__le16 qos_seq[8];
|
||||
};
|
||||
|
||||
|
|
|
@ -1120,229 +1120,8 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
|
|||
&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
|
||||
|
||||
|
@ -1649,97 +1428,13 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
|
|||
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 ret;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_ECHO,
|
||||
.len = { 0 },
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
|
|
|
@ -237,10 +237,6 @@ struct iwl_cfg {
|
|||
* 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,
|
||||
int hw_decrypt);
|
||||
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,
|
||||
struct iwl_rxon_context *ctx);
|
||||
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);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
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);
|
||||
void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
|
||||
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);
|
||||
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,
|
||||
|
|
|
@ -284,8 +284,8 @@
|
|||
#define CSR_HW_REV_TYPE_6x35 CSR_HW_REV_TYPE_6x05
|
||||
#define CSR_HW_REV_TYPE_2x30 (0x00000C0)
|
||||
#define CSR_HW_REV_TYPE_2x00 (0x0000100)
|
||||
#define CSR_HW_REV_TYPE_200 (0x0000110)
|
||||
#define CSR_HW_REV_TYPE_230 (0x0000120)
|
||||
#define CSR_HW_REV_TYPE_105 (0x0000110)
|
||||
#define CSR_HW_REV_TYPE_135 (0x0000120)
|
||||
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
|
||||
|
||||
/* EEPROM REG */
|
||||
|
|
|
@ -70,10 +70,25 @@ do { \
|
|||
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
|
||||
} 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
|
||||
#define IWL_DEBUG(m, level, fmt, args...)
|
||||
#define IWL_DEBUG_LIMIT(m, level, fmt, args...)
|
||||
#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 */
|
||||
|
||||
#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_STATS (1 << 29)
|
||||
#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_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_LIMIT(p, 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_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)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue