Merge remote-tracking branch 'wireless-next/master' into mac80211-next
This commit is contained in:
commit
b1fbd46976
237 changed files with 12886 additions and 9384 deletions
13
MAINTAINERS
13
MAINTAINERS
|
@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com>
|
|||
M: Franky (Zhenhui) Lin <frankyl@broadcom.com>
|
||||
M: Kan Yan <kanyan@broadcom.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: brcm80211-dev-list@broadcom.com
|
||||
S: Supported
|
||||
F: drivers/net/wireless/brcm80211/
|
||||
|
||||
|
@ -1800,6 +1801,9 @@ F: include/linux/cfag12864b.h
|
|||
CFG80211 and NL80211
|
||||
M: Johannes Berg <johannes@sipsolutions.net>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
|
||||
S: Maintained
|
||||
F: include/linux/nl80211.h
|
||||
F: include/net/cfg80211.h
|
||||
|
@ -4340,7 +4344,8 @@ MAC80211
|
|||
M: Johannes Berg <johannes@sipsolutions.net>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
|
||||
S: Maintained
|
||||
F: Documentation/networking/mac80211-injection.txt
|
||||
F: include/net/mac80211.h
|
||||
|
@ -4351,7 +4356,8 @@ M: Stefano Brivio <stefano.brivio@polimi.it>
|
|||
M: Mattias Nissler <mattias.nissler@gmx.de>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
|
||||
S: Maintained
|
||||
F: net/mac80211/rc80211_pid*
|
||||
|
||||
|
@ -5695,6 +5701,9 @@ F: include/linux/remoteproc.h
|
|||
RFKILL
|
||||
M: Johannes Berg <johannes@sipsolutions.net>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
|
||||
S: Maintained
|
||||
F: Documentation/rfkill.txt
|
||||
F: net/rfkill/
|
||||
|
|
|
@ -232,17 +232,19 @@ void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
|
|||
int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
|
||||
bool enable)
|
||||
{
|
||||
struct pci_dev *pdev = pc->core->bus->host_pci;
|
||||
struct pci_dev *pdev;
|
||||
u32 coremask, tmp;
|
||||
int err = 0;
|
||||
|
||||
if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
|
||||
if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
|
||||
/* This bcma device is not on a PCI host-bus. So the IRQs are
|
||||
* not routed through the PCI core.
|
||||
* So we must not enable routing through the PCI core. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
pdev = pc->core->bus->host_pci;
|
||||
|
||||
err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
|
@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = {
|
|||
|
||||
static const struct bcma_device_id_name bcma_bcm_device_names[] = {
|
||||
{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
|
||||
{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
|
||||
{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
|
||||
{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
|
||||
{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
|
||||
{ BCMA_CORE_ALTA, "ALTA (I2S)" },
|
||||
{ BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
|
||||
{ BCMA_CORE_INVALID, "Invalid" },
|
||||
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
|
||||
{ BCMA_CORE_ILINE20, "ILine 20" },
|
||||
|
|
|
@ -231,12 +231,12 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
|
|||
}
|
||||
|
||||
do {
|
||||
register unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
register unsigned int offset;
|
||||
register unsigned char command;
|
||||
register unsigned long ready_bit;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
unsigned int offset;
|
||||
unsigned char command;
|
||||
unsigned long ready_bit;
|
||||
register struct sk_buff *skb;
|
||||
register int len;
|
||||
int len;
|
||||
|
||||
clear_bit(XMIT_WAKEUP, &(info->tx_state));
|
||||
|
||||
|
|
|
@ -470,7 +470,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
|||
hdev->flush = bpa10x_flush;
|
||||
hdev->send = bpa10x_send_frame;
|
||||
|
||||
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
|
|
|
@ -186,9 +186,9 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
|
|||
return;
|
||||
|
||||
do {
|
||||
register unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
register struct sk_buff *skb;
|
||||
register int len;
|
||||
int len;
|
||||
|
||||
if (!pcmcia_dev_present(info->p_dev))
|
||||
break;
|
||||
|
|
|
@ -110,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
|
|||
/* Marvell SD8787 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
|
||||
/* Marvell SD8787 Bluetooth AMP device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
|
||||
/* Marvell SD8797 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
|
||||
|
|
|
@ -140,9 +140,9 @@ static void btuart_write_wakeup(btuart_info_t *info)
|
|||
}
|
||||
|
||||
do {
|
||||
register unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
register struct sk_buff *skb;
|
||||
register int len;
|
||||
int len;
|
||||
|
||||
clear_bit(XMIT_WAKEUP, &(info->tx_state));
|
||||
|
||||
|
|
|
@ -21,15 +21,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
@ -1026,7 +1018,7 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
||||
|
||||
if (!reset)
|
||||
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
|
||||
if (!disable_scofix)
|
||||
|
@ -1038,7 +1030,7 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
|
||||
if (id->driver_info & BTUSB_DIGIANSWER) {
|
||||
data->cmdreq_type = USB_TYPE_VENDOR;
|
||||
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_CSR) {
|
||||
|
@ -1046,7 +1038,7 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
|
||||
/* Old firmware would otherwise execute USB reset */
|
||||
if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117)
|
||||
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_SNIFFER) {
|
||||
|
|
|
@ -144,9 +144,9 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
|
|||
}
|
||||
|
||||
do {
|
||||
register unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
register struct sk_buff *skb;
|
||||
register int len;
|
||||
int len;
|
||||
|
||||
clear_bit(XMIT_WAKEUP, &(info->tx_state));
|
||||
|
||||
|
|
|
@ -552,7 +552,7 @@ static u16 bscp_get_crc(struct bcsp_struct *bcsp)
|
|||
static int bcsp_recv(struct hci_uart *hu, void *data, int count)
|
||||
{
|
||||
struct bcsp_struct *bcsp = hu->priv;
|
||||
register unsigned char *ptr;
|
||||
unsigned char *ptr;
|
||||
|
||||
BT_DBG("hu %p count %d rx_state %d rx_count %ld",
|
||||
hu, count, bcsp->rx_state, bcsp->rx_count);
|
||||
|
|
|
@ -126,7 +126,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
|||
|
||||
static inline int h4_check_data_len(struct h4_struct *h4, int len)
|
||||
{
|
||||
register int room = skb_tailroom(h4->rx_skb);
|
||||
int room = skb_tailroom(h4->rx_skb);
|
||||
|
||||
BT_DBG("len %d room %d", len, room);
|
||||
|
||||
|
|
|
@ -394,7 +394,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
|||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||
|
||||
if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
|
||||
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
|
||||
hdev->dev_type = HCI_AMP;
|
||||
|
|
|
@ -348,7 +348,7 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
|||
|
||||
static inline int ll_check_data_len(struct ll_struct *ll, int len)
|
||||
{
|
||||
register int room = skb_tailroom(ll->rx_skb);
|
||||
int room = skb_tailroom(ll->rx_skb);
|
||||
|
||||
BT_DBG("len %d room %d", len, room);
|
||||
|
||||
|
@ -374,11 +374,11 @@ static inline int ll_check_data_len(struct ll_struct *ll, int len)
|
|||
static int ll_recv(struct hci_uart *hu, void *data, int count)
|
||||
{
|
||||
struct ll_struct *ll = hu->priv;
|
||||
register char *ptr;
|
||||
char *ptr;
|
||||
struct hci_event_hdr *eh;
|
||||
struct hci_acl_hdr *ah;
|
||||
struct hci_sco_hdr *sh;
|
||||
register int len, type, dlen;
|
||||
int len, type, dlen;
|
||||
|
||||
BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count);
|
||||
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
|
||||
#define DEFAULT_BG_SCAN_PERIOD 60
|
||||
|
||||
struct ath6kl_cfg80211_match_probe_ssid {
|
||||
struct cfg80211_ssid ssid;
|
||||
u8 flag;
|
||||
};
|
||||
|
||||
static struct ieee80211_rate ath6kl_rates[] = {
|
||||
RATETAB_ENT(10, 0x1, 0),
|
||||
RATETAB_ENT(20, 0x2, 0),
|
||||
|
@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
vif->nw_type = vif->next_mode;
|
||||
|
||||
/* enable enhanced bmiss detection if applicable */
|
||||
ath6kl_cfg80211_sta_bmiss_enhance(vif, true);
|
||||
|
||||
if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
|
||||
nw_subtype = SUBTYPE_P2PCLIENT;
|
||||
|
||||
|
@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a disconnect command to target when a disconnect event is
|
||||
* received with reason code other than 3 (DISCONNECT_CMD - disconnect
|
||||
* request from host) to make the firmware stop trying to connect even
|
||||
* after giving disconnect event. There will be one more disconnect
|
||||
* event for this disconnect command with reason code DISCONNECT_CMD
|
||||
* which will be notified to cfg80211.
|
||||
*/
|
||||
|
||||
if (reason != DISCONNECT_CMD) {
|
||||
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
clear_bit(CONNECT_PEND, &vif->flags);
|
||||
|
||||
if (vif->sme_state == SME_CONNECTING) {
|
||||
|
@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
|
|||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
GFP_KERNEL);
|
||||
} else if (vif->sme_state == SME_CONNECTED) {
|
||||
cfg80211_disconnected(vif->ndev, reason,
|
||||
cfg80211_disconnected(vif->ndev, proto_reason,
|
||||
NULL, 0, GFP_KERNEL);
|
||||
}
|
||||
|
||||
vif->sme_state = SME_DISCONNECTED;
|
||||
|
||||
/*
|
||||
* Send a disconnect command to target when a disconnect event is
|
||||
* received with reason code other than 3 (DISCONNECT_CMD - disconnect
|
||||
* request from host) to make the firmware stop trying to connect even
|
||||
* after giving disconnect event. There will be one more disconnect
|
||||
* event for this disconnect command with reason code DISCONNECT_CMD
|
||||
* which won't be notified to cfg80211.
|
||||
*/
|
||||
if (reason != DISCONNECT_CMD)
|
||||
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
|
||||
}
|
||||
|
||||
static int ath6kl_set_probed_ssids(struct ath6kl *ar,
|
||||
struct ath6kl_vif *vif,
|
||||
struct cfg80211_ssid *ssids, int n_ssids)
|
||||
struct cfg80211_ssid *ssids, int n_ssids,
|
||||
struct cfg80211_match_set *match_set,
|
||||
int n_match_ssid)
|
||||
{
|
||||
u8 i;
|
||||
u8 i, j, index_to_add, ssid_found = false;
|
||||
struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS];
|
||||
|
||||
if (n_ssids > MAX_PROBED_SSID_INDEX)
|
||||
memset(ssid_list, 0, sizeof(ssid_list));
|
||||
|
||||
if (n_ssids > MAX_PROBED_SSIDS ||
|
||||
n_match_ssid > MAX_PROBED_SSIDS)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < n_ssids; i++) {
|
||||
memcpy(ssid_list[i].ssid.ssid,
|
||||
ssids[i].ssid,
|
||||
ssids[i].ssid_len);
|
||||
ssid_list[i].ssid.ssid_len = ssids[i].ssid_len;
|
||||
|
||||
if (ssids[i].ssid_len)
|
||||
ssid_list[i].flag = SPECIFIC_SSID_FLAG;
|
||||
else
|
||||
ssid_list[i].flag = ANY_SSID_FLAG;
|
||||
|
||||
if (n_match_ssid == 0)
|
||||
ssid_list[i].flag |= MATCH_SSID_FLAG;
|
||||
}
|
||||
|
||||
index_to_add = i;
|
||||
|
||||
for (i = 0; i < n_match_ssid; i++) {
|
||||
ssid_found = false;
|
||||
|
||||
for (j = 0; j < n_ssids; j++) {
|
||||
if ((match_set[i].ssid.ssid_len ==
|
||||
ssid_list[j].ssid.ssid_len) &&
|
||||
(!memcmp(ssid_list[j].ssid.ssid,
|
||||
match_set[i].ssid.ssid,
|
||||
match_set[i].ssid.ssid_len))) {
|
||||
ssid_list[j].flag |= MATCH_SSID_FLAG;
|
||||
ssid_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssid_found)
|
||||
continue;
|
||||
|
||||
if (index_to_add >= MAX_PROBED_SSIDS)
|
||||
continue;
|
||||
|
||||
ssid_list[index_to_add].ssid.ssid_len =
|
||||
match_set[i].ssid.ssid_len;
|
||||
memcpy(ssid_list[index_to_add].ssid.ssid,
|
||||
match_set[i].ssid.ssid,
|
||||
match_set[i].ssid.ssid_len);
|
||||
ssid_list[index_to_add].flag |= MATCH_SSID_FLAG;
|
||||
index_to_add++;
|
||||
}
|
||||
|
||||
for (i = 0; i < index_to_add; i++) {
|
||||
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
|
||||
ssids[i].ssid_len ?
|
||||
SPECIFIC_SSID_FLAG : ANY_SSID_FLAG,
|
||||
ssids[i].ssid_len,
|
||||
ssids[i].ssid);
|
||||
ssid_list[i].flag,
|
||||
ssid_list[i].ssid.ssid_len,
|
||||
ssid_list[i].ssid.ssid);
|
||||
|
||||
}
|
||||
|
||||
/* Make sure no old entries are left behind */
|
||||
for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) {
|
||||
for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) {
|
||||
ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
|
||||
DISABLE_SSID_FLAG, 0, NULL);
|
||||
}
|
||||
|
@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
|||
}
|
||||
|
||||
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||
request->n_ssids);
|
||||
request->n_ssids, NULL, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
|
|||
WMI_FRAME_PROBE_REQ,
|
||||
request->ie, request->ie_len);
|
||||
if (ret) {
|
||||
ath6kl_err("failed to set Probe Request appie for scan");
|
||||
ath6kl_err("failed to set Probe Request appie for scan\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
|
|||
}
|
||||
}
|
||||
|
||||
/* need to clean up enhanced bmiss detection fw state */
|
||||
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
|
||||
|
||||
set_iface_type:
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
|
@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
|
|||
if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
|
||||
return -EINVAL;
|
||||
|
||||
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) {
|
||||
if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
|
||||
ar->fw_capabilities)) {
|
||||
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
|
||||
vif->fw_vif_idx, false);
|
||||
if (ret)
|
||||
|
@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
|
|||
|
||||
ar->state = ATH6KL_STATE_ON;
|
||||
|
||||
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) {
|
||||
if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
|
||||
test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
|
||||
ar->fw_capabilities)) {
|
||||
ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
|
||||
vif->fw_vif_idx, true);
|
||||
if (ret)
|
||||
|
@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar)
|
|||
static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
|
||||
bool ht_enable)
|
||||
{
|
||||
struct ath6kl_htcap *htcap = &vif->htcap;
|
||||
struct ath6kl_htcap *htcap = &vif->htcap[band];
|
||||
|
||||
if (htcap->ht_enable == ht_enable)
|
||||
return 0;
|
||||
|
@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag)))
|
||||
return;
|
||||
|
||||
if (vif->nw_type != INFRA_NETWORK)
|
||||
return;
|
||||
|
||||
if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
|
||||
vif->ar->fw_capabilities))
|
||||
return;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n",
|
||||
enable ? "enable" : "disable");
|
||||
|
||||
err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi,
|
||||
vif->fw_vif_idx, enable);
|
||||
if (err)
|
||||
ath6kl_err("failed to %s enhanced bmiss detection: %d\n",
|
||||
enable ? "enable" : "disable", err);
|
||||
}
|
||||
|
||||
static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
|
||||
u8 *rsn_capab)
|
||||
{
|
||||
|
@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
/* TODO:
|
||||
* info->interval
|
||||
* info->dtim_period
|
||||
*/
|
||||
|
||||
ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
info->dtim_period);
|
||||
|
||||
/* ignore error, just print a warning and continue normally */
|
||||
if (ret)
|
||||
ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret);
|
||||
|
||||
if (info->beacon.head == NULL)
|
||||
return -EINVAL;
|
||||
mgmt = (struct ieee80211_mgmt *) info->beacon.head;
|
||||
|
@ -3131,10 +3226,24 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
ath6kl_cfg80211_scan_complete_event(vif, true);
|
||||
|
||||
ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
|
||||
request->n_ssids);
|
||||
request->n_ssids,
|
||||
request->match_sets,
|
||||
request->n_match_sets);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!request->n_match_sets) {
|
||||
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
ALL_BSS_FILTER, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
|
||||
MATCHED_SSID_FILTER, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* fw uses seconds, also make sure that it's >0 */
|
||||
interval = max_t(u16, 1, request->interval / 1000);
|
||||
|
||||
|
@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
|
|||
WMI_FRAME_PROBE_REQ,
|
||||
request->ie, request->ie_len);
|
||||
if (ret) {
|
||||
ath6kl_warn("Failed to set probe request IE for scheduled scan: %d",
|
||||
ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
|
||||
struct net_device *dev,
|
||||
const u8 *addr,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
{
|
||||
struct ath6kl *ar = ath6kl_priv(dev);
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
|
||||
return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
|
||||
mask);
|
||||
}
|
||||
|
||||
static const struct ieee80211_txrx_stypes
|
||||
ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
|
||||
[NL80211_IFTYPE_STATION] = {
|
||||
|
@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
|
|||
.mgmt_frame_register = ath6kl_mgmt_frame_register,
|
||||
.sched_scan_start = ath6kl_cfg80211_sscan_start,
|
||||
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
|
||||
.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
|
||||
};
|
||||
|
||||
void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
|
||||
|
@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
|
|||
vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
|
||||
vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
|
||||
vif->bg_scan_period = 0;
|
||||
vif->htcap.ht_enable = true;
|
||||
vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true;
|
||||
vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
|
||||
|
||||
memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
|
||||
if (fw_vif_idx != 0)
|
||||
|
@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
}
|
||||
|
||||
/* max num of ssids that can be probed during scanning */
|
||||
wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
|
||||
wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
|
||||
|
||||
/* max num of ssids that can be matched after scan */
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
|
||||
ar->fw_capabilities))
|
||||
wiphy->max_match_sets = MAX_PROBED_SSIDS;
|
||||
|
||||
wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
|
||||
switch (ar->hw.cap) {
|
||||
case WMI_11AN_CAP:
|
||||
|
@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
ath6kl_band_5ghz.ht_cap.cap = 0;
|
||||
ath6kl_band_5ghz.ht_cap.ht_supported = false;
|
||||
}
|
||||
|
||||
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
|
||||
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
|
||||
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
|
||||
} else {
|
||||
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
}
|
||||
|
||||
if (band_2gig)
|
||||
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
|
||||
if (band_5gig)
|
||||
|
@ -3499,7 +3639,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
|||
wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
|
||||
#endif
|
||||
|
||||
wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX;
|
||||
wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS;
|
||||
|
||||
ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
|
||||
WIPHY_FLAG_HAVE_AP_SME |
|
||||
|
|
|
@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar);
|
|||
|
||||
struct ath6kl *ath6kl_cfg80211_create(void);
|
||||
void ath6kl_cfg80211_destroy(struct ath6kl *ar);
|
||||
/* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */
|
||||
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable);
|
||||
|
||||
#endif /* ATH6KL_CFG80211_H */
|
||||
|
|
|
@ -100,6 +100,21 @@ enum ath6kl_fw_capability {
|
|||
/* Firmware has support to override rsn cap of rsn ie */
|
||||
ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
|
||||
|
||||
/*
|
||||
* Multicast support in WOW and host awake mode.
|
||||
* Allow all multicast in host awake mode.
|
||||
* Apply multicast filter in WOW mode.
|
||||
*/
|
||||
ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
|
||||
|
||||
/* Firmware supports enhanced bmiss detection */
|
||||
ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
|
||||
|
||||
/*
|
||||
* FW supports matching of ssid in schedule scan
|
||||
*/
|
||||
ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
|
||||
|
||||
/* this needs to be last */
|
||||
ATH6KL_FW_CAPABILITY_MAX,
|
||||
};
|
||||
|
@ -112,6 +127,10 @@ struct ath6kl_fw_ie {
|
|||
u8 data[0];
|
||||
};
|
||||
|
||||
enum ath6kl_hw_flags {
|
||||
ATH6KL_HW_FLAG_64BIT_RATES = BIT(0),
|
||||
};
|
||||
|
||||
#define ATH6KL_FW_API2_FILE "fw-2.bin"
|
||||
#define ATH6KL_FW_API3_FILE "fw-3.bin"
|
||||
|
||||
|
@ -196,7 +215,7 @@ struct ath6kl_fw_ie {
|
|||
|
||||
#define AGGR_NUM_OF_FREE_NETBUFS 16
|
||||
|
||||
#define AGGR_RX_TIMEOUT 400 /* in ms */
|
||||
#define AGGR_RX_TIMEOUT 100 /* in ms */
|
||||
|
||||
#define WMI_TIMEOUT (2 * HZ)
|
||||
|
||||
|
@ -245,7 +264,6 @@ struct skb_hold_q {
|
|||
|
||||
struct rxtid {
|
||||
bool aggr;
|
||||
bool progress;
|
||||
bool timer_mon;
|
||||
u16 win_sz;
|
||||
u16 seq_next;
|
||||
|
@ -254,9 +272,15 @@ struct rxtid {
|
|||
struct sk_buff_head q;
|
||||
|
||||
/*
|
||||
* FIXME: No clue what this should protect. Apparently it should
|
||||
* protect some of the fields above but they are also accessed
|
||||
* without taking the lock.
|
||||
* lock mainly protects seq_next and hold_q. Movement of seq_next
|
||||
* needs to be protected between aggr_timeout() and
|
||||
* aggr_process_recv_frm(). hold_q will be holding the pending
|
||||
* reorder frames and it's access should also be protected.
|
||||
* Some of the other fields like hold_q_sz, win_sz and aggr are
|
||||
* initialized/reset when receiving addba/delba req, also while
|
||||
* deleting aggr state all the pending buffers are flushed before
|
||||
* resetting these fields, so there should not be any race in accessing
|
||||
* these fields.
|
||||
*/
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
@ -541,7 +565,7 @@ struct ath6kl_vif {
|
|||
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
|
||||
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
|
||||
struct aggr_info *aggr_cntxt;
|
||||
struct ath6kl_htcap htcap;
|
||||
struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS];
|
||||
|
||||
struct timer_list disconnect_timer;
|
||||
struct timer_list sched_scan_timer;
|
||||
|
@ -684,6 +708,8 @@ struct ath6kl {
|
|||
u32 testscript_addr;
|
||||
enum wmi_phy_cap cap;
|
||||
|
||||
u32 flags;
|
||||
|
||||
struct ath6kl_hw_fw {
|
||||
const char *dir;
|
||||
const char *otp;
|
||||
|
|
|
@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target,
|
|||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC,
|
||||
"htc rx 0x%p hdr x%x len %d mbox 0x%x\n",
|
||||
"htc rx 0x%p hdr 0x%x len %d mbox 0x%x\n",
|
||||
packet, packet->info.rx.exp_hdr,
|
||||
padded_len, dev->ar->mbox_info.htc_addr);
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.reserved_ram_size = 6912,
|
||||
.refclk_hz = 26000000,
|
||||
.uarttx_pin = 8,
|
||||
.flags = 0,
|
||||
|
||||
/* hw2.0 needs override address hardcoded */
|
||||
.app_start_override_addr = 0x944C00,
|
||||
|
@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.refclk_hz = 26000000,
|
||||
.uarttx_pin = 8,
|
||||
.testscript_addr = 0x57ef74,
|
||||
.flags = 0,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6003_HW_2_1_1_FW_DIR,
|
||||
|
@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.board_addr = 0x433900,
|
||||
.refclk_hz = 26000000,
|
||||
.uarttx_pin = 11,
|
||||
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6004_HW_1_0_FW_DIR,
|
||||
|
@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.board_addr = 0x43d400,
|
||||
.refclk_hz = 40000000,
|
||||
.uarttx_pin = 11,
|
||||
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6004_HW_1_1_FW_DIR,
|
||||
|
@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = {
|
|||
.board_addr = 0x435c00,
|
||||
.refclk_hz = 40000000,
|
||||
.uarttx_pin = 11,
|
||||
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
|
||||
|
||||
.fw = {
|
||||
.dir = AR6004_HW_1_2_FW_DIR,
|
||||
|
@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
|
|||
}
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH6KL_FW_IE_FW_VERSION:
|
||||
strlcpy(ar->wiphy->fw_version, data,
|
||||
sizeof(ar->wiphy->fw_version));
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_BOOT,
|
||||
"found fw version %s\n",
|
||||
ar->wiphy->fw_version);
|
||||
break;
|
||||
case ATH6KL_FW_IE_OTP_IMAGE:
|
||||
ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
|
|||
ar->hw.reserved_ram_size);
|
||||
break;
|
||||
case ATH6KL_FW_IE_CAPABILITIES:
|
||||
if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8))
|
||||
break;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_BOOT,
|
||||
"found firmware capabilities ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
|
|||
index = i / 8;
|
||||
bit = i % 8;
|
||||
|
||||
if (index == ie_len)
|
||||
break;
|
||||
|
||||
if (data[index] & (1 << bit))
|
||||
__set_bit(i, ar->fw_capabilities);
|
||||
}
|
||||
|
@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar)
|
|||
ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
|
||||
ath6kl_err("temporary war to avoid sdio crc error\n");
|
||||
|
||||
param = 0x28;
|
||||
address = GPIO_BASE_ADDRESS + GPIO_PIN9_ADDRESS;
|
||||
status = ath6kl_bmi_reg_write(ar, address, param);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
param = 0x20;
|
||||
|
||||
address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
|
||||
|
@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
|
|||
cfg80211_scan_done(vif->scan_req, true);
|
||||
vif->scan_req = NULL;
|
||||
}
|
||||
|
||||
/* need to clean up enhanced bmiss detection fw state */
|
||||
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
|
||||
}
|
||||
|
||||
void ath6kl_stop_txrx(struct ath6kl *ar)
|
||||
|
|
|
@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver,
|
|||
struct ath6kl *ar = devt;
|
||||
|
||||
memcpy(ar->mac_addr, datap, ETH_ALEN);
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n",
|
||||
__func__, ar->mac_addr);
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_BOOT,
|
||||
"ready event mac addr %pM sw_ver 0x%x abi_ver 0x%x cap 0x%x\n",
|
||||
ar->mac_addr, sw_ver, abi_ver, cap);
|
||||
|
||||
ar->version.wlan_ver = sw_ver;
|
||||
ar->version.abi_ver = abi_ver;
|
||||
ar->hw.cap = cap;
|
||||
|
||||
snprintf(ar->wiphy->fw_version,
|
||||
sizeof(ar->wiphy->fw_version),
|
||||
"%u.%u.%u.%u",
|
||||
(ar->version.wlan_ver & 0xf0000000) >> 28,
|
||||
(ar->version.wlan_ver & 0x0f000000) >> 24,
|
||||
(ar->version.wlan_ver & 0x00ff0000) >> 16,
|
||||
(ar->version.wlan_ver & 0x0000ffff));
|
||||
if (strlen(ar->wiphy->fw_version) == 0) {
|
||||
snprintf(ar->wiphy->fw_version,
|
||||
sizeof(ar->wiphy->fw_version),
|
||||
"%u.%u.%u.%u",
|
||||
(ar->version.wlan_ver & 0xf0000000) >> 28,
|
||||
(ar->version.wlan_ver & 0x0f000000) >> 24,
|
||||
(ar->version.wlan_ver & 0x00ff0000) >> 16,
|
||||
(ar->version.wlan_ver & 0x0000ffff));
|
||||
}
|
||||
|
||||
/* indicate to the waiting thread that the ready event was received */
|
||||
set_bit(WMI_READY, &ar->flag);
|
||||
|
@ -1166,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
|
|||
else
|
||||
clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
|
||||
|
||||
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
|
||||
vif->ar->fw_capabilities)) {
|
||||
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
|
||||
}
|
||||
|
||||
if (!(ndev->flags & IFF_MULTICAST)) {
|
||||
mc_all_on = false;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#define LPO_CAL_ENABLE_S 20
|
||||
#define LPO_CAL_ENABLE 0x00100000
|
||||
|
||||
#define GPIO_PIN9_ADDRESS 0x0000004c
|
||||
#define GPIO_PIN10_ADDRESS 0x00000050
|
||||
#define GPIO_PIN11_ADDRESS 0x00000054
|
||||
#define GPIO_PIN12_ADDRESS 0x00000058
|
||||
|
|
|
@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
|
|||
rxtid = &agg_conn->rx_tid[tid];
|
||||
stats = &agg_conn->stat[tid];
|
||||
|
||||
spin_lock_bh(&rxtid->lock);
|
||||
idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
|
||||
|
||||
/*
|
||||
|
@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
|
|||
seq_end = seq_no ? seq_no : rxtid->seq_next;
|
||||
idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz);
|
||||
|
||||
spin_lock_bh(&rxtid->lock);
|
||||
|
||||
do {
|
||||
node = &rxtid->hold_q[idx];
|
||||
if ((order == 1) && (!node->skb))
|
||||
|
@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
|
|||
((end > extended_end) && (cur > extended_end) &&
|
||||
(cur < end))) {
|
||||
aggr_deque_frms(agg_conn, tid, 0, 0);
|
||||
spin_lock_bh(&rxtid->lock);
|
||||
if (cur >= rxtid->hold_q_sz - 1)
|
||||
rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
|
||||
else
|
||||
rxtid->seq_next = ATH6KL_MAX_SEQ_NO -
|
||||
(rxtid->hold_q_sz - 2 - cur);
|
||||
spin_unlock_bh(&rxtid->lock);
|
||||
} else {
|
||||
/*
|
||||
* Dequeue only those frames that are outside the
|
||||
|
@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
|
|||
aggr_deque_frms(agg_conn, tid, 0, 1);
|
||||
|
||||
if (agg_conn->timer_scheduled)
|
||||
rxtid->progress = true;
|
||||
else
|
||||
for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
|
||||
if (rxtid->hold_q[idx].skb) {
|
||||
/*
|
||||
* There is a frame in the queue and no
|
||||
* timer so start a timer to ensure that
|
||||
* the frame doesn't remain stuck
|
||||
* forever.
|
||||
*/
|
||||
agg_conn->timer_scheduled = true;
|
||||
mod_timer(&agg_conn->timer,
|
||||
(jiffies +
|
||||
HZ * (AGGR_RX_TIMEOUT) / 1000));
|
||||
rxtid->progress = false;
|
||||
rxtid->timer_mon = true;
|
||||
break;
|
||||
}
|
||||
return is_queued;
|
||||
|
||||
spin_lock_bh(&rxtid->lock);
|
||||
for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
|
||||
if (rxtid->hold_q[idx].skb) {
|
||||
/*
|
||||
* There is a frame in the queue and no
|
||||
* timer so start a timer to ensure that
|
||||
* the frame doesn't remain stuck
|
||||
* forever.
|
||||
*/
|
||||
agg_conn->timer_scheduled = true;
|
||||
mod_timer(&agg_conn->timer,
|
||||
(jiffies + (HZ * AGGR_RX_TIMEOUT) / 1000));
|
||||
rxtid->timer_mon = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&rxtid->lock);
|
||||
|
||||
return is_queued;
|
||||
}
|
||||
|
@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg)
|
|||
rxtid = &aggr_conn->rx_tid[i];
|
||||
stats = &aggr_conn->stat[i];
|
||||
|
||||
if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress)
|
||||
if (!rxtid->aggr || !rxtid->timer_mon)
|
||||
continue;
|
||||
|
||||
stats->num_timeouts++;
|
||||
|
@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg)
|
|||
rxtid = &aggr_conn->rx_tid[i];
|
||||
|
||||
if (rxtid->aggr && rxtid->hold_q) {
|
||||
spin_lock_bh(&rxtid->lock);
|
||||
for (j = 0; j < rxtid->hold_q_sz; j++) {
|
||||
if (rxtid->hold_q[j].skb) {
|
||||
aggr_conn->timer_scheduled = true;
|
||||
rxtid->timer_mon = true;
|
||||
rxtid->progress = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&rxtid->lock);
|
||||
|
||||
if (j >= rxtid->hold_q_sz)
|
||||
rxtid->timer_mon = false;
|
||||
|
@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid)
|
|||
aggr_deque_frms(aggr_conn, tid, 0, 0);
|
||||
|
||||
rxtid->aggr = false;
|
||||
rxtid->progress = false;
|
||||
rxtid->timer_mon = false;
|
||||
rxtid->win_sz = 0;
|
||||
rxtid->seq_next = 0;
|
||||
|
@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info,
|
|||
for (i = 0; i < NUM_OF_TIDS; i++) {
|
||||
rxtid = &aggr_conn->rx_tid[i];
|
||||
rxtid->aggr = false;
|
||||
rxtid->progress = false;
|
||||
rxtid->timer_mon = false;
|
||||
skb_queue_head_init(&rxtid->q);
|
||||
spin_lock_init(&rxtid->lock);
|
||||
|
|
|
@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
|
|||
return -ENOMEM;
|
||||
|
||||
cmd = (struct roam_ctrl_cmd *) skb->data;
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
||||
memcpy(cmd->info.bssid, bssid, ETH_ALEN);
|
||||
cmd->roam_ctrl = WMI_FORCE_ROAM;
|
||||
|
@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
|
|||
NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct set_dtim_cmd *cmd;
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct set_dtim_cmd *) skb->data;
|
||||
|
||||
cmd->dtim_period = cpu_to_le32(dtim_period);
|
||||
return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
|
||||
WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG);
|
||||
}
|
||||
|
||||
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
|
|||
return -ENOMEM;
|
||||
|
||||
cmd = (struct roam_ctrl_cmd *) skb->data;
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
||||
cmd->info.roam_mode = mode;
|
||||
cmd->roam_ctrl = WMI_SET_ROAM_MODE;
|
||||
|
@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
|
|||
struct wmi_probed_ssid_cmd *cmd;
|
||||
int ret;
|
||||
|
||||
if (index > MAX_PROBED_SSID_INDEX)
|
||||
if (index >= MAX_PROBED_SSIDS)
|
||||
return -EINVAL;
|
||||
|
||||
if (ssid_len > sizeof(cmd->ssid))
|
||||
|
@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
|
|||
spin_unlock_bh(&wmi->lock);
|
||||
}
|
||||
|
||||
static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret, mode, band;
|
||||
u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
|
||||
struct wmi_set_tx_select_rates64_cmd *cmd;
|
||||
|
||||
memset(&ratemask, 0, sizeof(ratemask));
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
/* copy legacy rate mask */
|
||||
ratemask[band] = mask->control[band].legacy;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
ratemask[band] =
|
||||
mask->control[band].legacy << 4;
|
||||
|
||||
/* copy mcs rate mask */
|
||||
mcsrate = mask->control[band].mcs[1];
|
||||
mcsrate <<= 8;
|
||||
mcsrate |= mask->control[band].mcs[0];
|
||||
ratemask[band] |= mcsrate << 12;
|
||||
ratemask[band] |= mcsrate << 28;
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"Ratemask 64 bit: 2.4:%llx 5:%llx\n",
|
||||
ratemask[0], ratemask[1]);
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
|
||||
for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
|
||||
/* A mode operate in 5GHZ band */
|
||||
if (mode == WMI_RATES_MODE_11A ||
|
||||
mode == WMI_RATES_MODE_11A_HT20 ||
|
||||
mode == WMI_RATES_MODE_11A_HT40)
|
||||
band = IEEE80211_BAND_5GHZ;
|
||||
else
|
||||
band = IEEE80211_BAND_2GHZ;
|
||||
cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
|
||||
}
|
||||
|
||||
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
|
||||
WMI_SET_TX_SELECT_RATES_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret, mode, band;
|
||||
u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
|
||||
struct wmi_set_tx_select_rates32_cmd *cmd;
|
||||
|
||||
memset(&ratemask, 0, sizeof(ratemask));
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
/* copy legacy rate mask */
|
||||
ratemask[band] = mask->control[band].legacy;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
ratemask[band] =
|
||||
mask->control[band].legacy << 4;
|
||||
|
||||
/* copy mcs rate mask */
|
||||
mcsrate = mask->control[band].mcs[0];
|
||||
ratemask[band] |= mcsrate << 12;
|
||||
ratemask[band] |= mcsrate << 20;
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI,
|
||||
"Ratemask 32 bit: 2.4:%x 5:%x\n",
|
||||
ratemask[0], ratemask[1]);
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
|
||||
for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
|
||||
/* A mode operate in 5GHZ band */
|
||||
if (mode == WMI_RATES_MODE_11A ||
|
||||
mode == WMI_RATES_MODE_11A_HT20 ||
|
||||
mode == WMI_RATES_MODE_11A_HT40)
|
||||
band = IEEE80211_BAND_5GHZ;
|
||||
else
|
||||
band = IEEE80211_BAND_2GHZ;
|
||||
cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
|
||||
}
|
||||
|
||||
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
|
||||
WMI_SET_TX_SELECT_RATES_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
{
|
||||
struct ath6kl *ar = wmi->parent_dev;
|
||||
|
||||
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
|
||||
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
|
||||
else
|
||||
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
|
||||
}
|
||||
|
||||
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
|
||||
enum ath6kl_host_mode host_mode)
|
||||
{
|
||||
|
@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_sta_bmiss_enhance_cmd *cmd;
|
||||
int ret;
|
||||
|
||||
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_sta_bmiss_enhance_cmd *) skb->data;
|
||||
cmd->enable = enhance ? 1 : 0;
|
||||
|
||||
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
|
||||
WMI_STA_BMISS_ENHANCE_CMDID,
|
||||
NO_SYNC_WMIFLAG);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 ath6kl_wmi_get_rate(s8 rate_index)
|
||||
{
|
||||
if (rate_index == RATE_AUTO)
|
||||
|
|
|
@ -624,6 +624,10 @@ enum wmi_cmd_id {
|
|||
WMI_SEND_MGMT_CMDID,
|
||||
WMI_BEGIN_SCAN_CMDID,
|
||||
|
||||
WMI_SET_BLACK_LIST,
|
||||
WMI_SET_MCASTRATE,
|
||||
|
||||
WMI_STA_BMISS_ENHANCE_CMDID,
|
||||
};
|
||||
|
||||
enum wmi_mgmt_frame_type {
|
||||
|
@ -960,6 +964,9 @@ enum wmi_bss_filter {
|
|||
/* beacons matching probed ssid */
|
||||
PROBED_SSID_FILTER,
|
||||
|
||||
/* beacons matching matched ssid */
|
||||
MATCHED_SSID_FILTER,
|
||||
|
||||
/* marker only */
|
||||
LAST_BSS_FILTER,
|
||||
};
|
||||
|
@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd {
|
|||
} __packed;
|
||||
|
||||
/* WMI_SET_PROBED_SSID_CMDID */
|
||||
#define MAX_PROBED_SSID_INDEX 9
|
||||
#define MAX_PROBED_SSIDS 16
|
||||
|
||||
enum wmi_ssid_flag {
|
||||
/* disables entry */
|
||||
|
@ -989,10 +996,13 @@ enum wmi_ssid_flag {
|
|||
|
||||
/* probes for any ssid */
|
||||
ANY_SSID_FLAG = 0x02,
|
||||
|
||||
/* match for ssid */
|
||||
MATCH_SSID_FLAG = 0x08,
|
||||
};
|
||||
|
||||
struct wmi_probed_ssid_cmd {
|
||||
/* 0 to MAX_PROBED_SSID_INDEX */
|
||||
/* 0 to MAX_PROBED_SSIDS - 1 */
|
||||
u8 entry_index;
|
||||
|
||||
/* see, enum wmi_ssid_flg */
|
||||
|
@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd {
|
|||
__le16 num_beacons;
|
||||
};
|
||||
|
||||
/* WMI_STA_ENHANCE_BMISS_CMDID */
|
||||
struct wmi_sta_bmiss_enhance_cmd {
|
||||
u8 enable;
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_POWER_MODE_CMDID */
|
||||
enum wmi_power_mode {
|
||||
REC_POWER = 0x01,
|
||||
|
@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd {
|
|||
__le16 ps_fail_event_policy;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Ratemask for below modes should be passed
|
||||
* to WMI_SET_TX_SELECT_RATES_CMDID.
|
||||
* AR6003 has 32 bit mask for each modes.
|
||||
* First 12 bits for legacy rates, 13 to 20
|
||||
* bits for HT 20 rates and 21 to 28 bits for
|
||||
* HT 40 rates
|
||||
*/
|
||||
enum wmi_mode_phy {
|
||||
WMI_RATES_MODE_11A = 0,
|
||||
WMI_RATES_MODE_11G,
|
||||
WMI_RATES_MODE_11B,
|
||||
WMI_RATES_MODE_11GONLY,
|
||||
WMI_RATES_MODE_11A_HT20,
|
||||
WMI_RATES_MODE_11G_HT20,
|
||||
WMI_RATES_MODE_11A_HT40,
|
||||
WMI_RATES_MODE_11G_HT40,
|
||||
WMI_RATES_MODE_MAX
|
||||
};
|
||||
|
||||
/* WMI_SET_TX_SELECT_RATES_CMDID */
|
||||
struct wmi_set_tx_select_rates32_cmd {
|
||||
__le32 ratemask[WMI_RATES_MODE_MAX];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_TX_SELECT_RATES_CMDID */
|
||||
struct wmi_set_tx_select_rates64_cmd {
|
||||
__le64 ratemask[WMI_RATES_MODE_MAX];
|
||||
} __packed;
|
||||
|
||||
/* WMI_SET_DISC_TIMEOUT_CMDID */
|
||||
struct wmi_disc_timeout_cmd {
|
||||
/* seconds */
|
||||
|
@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd {
|
|||
u8 roam_ctrl;
|
||||
} __packed;
|
||||
|
||||
struct set_dtim_cmd {
|
||||
__le32 dtim_period;
|
||||
} __packed;
|
||||
|
||||
/* BSS INFO HDR version 2.0 */
|
||||
struct wmi_bss_info_hdr2 {
|
||||
__le16 ch; /* frequency in MHz */
|
||||
|
@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
|
|||
__be32 ips0, __be32 ips1);
|
||||
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
|
||||
enum ath6kl_host_mode host_mode);
|
||||
int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
|
||||
const struct cfg80211_bitrate_mask *mask);
|
||||
int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
|
||||
enum ath6kl_wow_mode wow_mode,
|
||||
u32 filter, u16 host_req_delay);
|
||||
|
@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
|
|||
int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
|
||||
u16 list_id, u16 filter_id);
|
||||
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
|
||||
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
|
||||
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
|
||||
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
|
||||
int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
|
||||
int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
|
||||
u8 *filter, bool add_filter);
|
||||
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
|
||||
|
||||
/* AP mode uAPSD */
|
||||
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);
|
||||
|
||||
|
|
|
@ -104,11 +104,6 @@ static const struct ani_cck_level_entry cck_level_table[] = {
|
|||
#define ATH9K_ANI_CCK_DEF_LEVEL \
|
||||
2 /* default level - matches the INI settings */
|
||||
|
||||
static bool use_new_ani(struct ath_hw *ah)
|
||||
{
|
||||
return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
|
||||
}
|
||||
|
||||
static void ath9k_hw_update_mibstats(struct ath_hw *ah,
|
||||
struct ath9k_mib_stats *stats)
|
||||
{
|
||||
|
@ -122,8 +117,6 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah,
|
|||
static void ath9k_ani_restart(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 ofdm_base = 0, cck_base = 0;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
@ -131,18 +124,10 @@ static void ath9k_ani_restart(struct ath_hw *ah)
|
|||
aniState = &ah->curchan->ani;
|
||||
aniState->listenTime = 0;
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
|
||||
cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
|
||||
}
|
||||
|
||||
ath_dbg(common, ANI, "Writing ofdmbase=%u cckbase=%u\n",
|
||||
ofdm_base, cck_base);
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, 0);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, 0);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
|
||||
|
||||
|
@ -154,110 +139,6 @@ static void ath9k_ani_restart(struct ath_hw *ah)
|
|||
aniState->cckPhyErrCount = 0;
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
|
||||
{
|
||||
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ah->opmode == NL80211_IFTYPE_AP) {
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
rssi = BEACON_RSSI(ah);
|
||||
if (rssi > aniState->rssiThrHigh) {
|
||||
if (!aniState->ofdmWeakSigDetectOff) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
false)) {
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
return;
|
||||
}
|
||||
} else if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
true);
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
return;
|
||||
} else {
|
||||
if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
|
||||
!conf_is_ht(conf)) {
|
||||
if (!aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
false);
|
||||
if (aniState->firstepLevel > 0)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
|
||||
{
|
||||
struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ah->opmode == NL80211_IFTYPE_AP) {
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
rssi = BEACON_RSSI(ah);
|
||||
if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
} else {
|
||||
if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
|
||||
!conf_is_ht(conf)) {
|
||||
if (aniState->firstepLevel > 0)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the OFDM Noise Immunity Level */
|
||||
static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
|
||||
{
|
||||
|
@ -265,18 +146,15 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
|
|||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
const struct ani_ofdm_level_entry *entry_ofdm;
|
||||
const struct ani_cck_level_entry *entry_cck;
|
||||
|
||||
aniState->noiseFloor = BEACON_RSSI(ah);
|
||||
bool weak_sig;
|
||||
|
||||
ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
|
||||
aniState->ofdmNoiseImmunityLevel,
|
||||
immunityLevel, aniState->noiseFloor,
|
||||
immunityLevel, BEACON_RSSI(ah),
|
||||
aniState->rssiThrLow, aniState->rssiThrHigh);
|
||||
|
||||
if (aniState->update_ani)
|
||||
aniState->ofdmNoiseImmunityLevel =
|
||||
(immunityLevel > ATH9K_ANI_OFDM_DEF_LEVEL) ?
|
||||
immunityLevel : ATH9K_ANI_OFDM_DEF_LEVEL;
|
||||
aniState->ofdmNoiseImmunityLevel = immunityLevel;
|
||||
|
||||
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
|
||||
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
|
||||
|
@ -292,12 +170,22 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
|
|||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
entry_ofdm->fir_step_level);
|
||||
|
||||
if ((aniState->noiseFloor >= aniState->rssiThrHigh) &&
|
||||
(!aniState->ofdmWeakSigDetectOff !=
|
||||
entry_ofdm->ofdm_weak_signal_on)) {
|
||||
weak_sig = entry_ofdm->ofdm_weak_signal_on;
|
||||
if (ah->opmode == NL80211_IFTYPE_STATION &&
|
||||
BEACON_RSSI(ah) <= aniState->rssiThrHigh)
|
||||
weak_sig = true;
|
||||
|
||||
if (aniState->ofdmWeakSigDetect != weak_sig)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
entry_ofdm->ofdm_weak_signal_on);
|
||||
|
||||
if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
|
||||
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
|
||||
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI;
|
||||
} else {
|
||||
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI;
|
||||
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,11 +196,6 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
|
|||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ath9k_hw_ani_ofdm_err_trigger_old(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
|
||||
|
@ -329,22 +212,18 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
|
|||
const struct ani_ofdm_level_entry *entry_ofdm;
|
||||
const struct ani_cck_level_entry *entry_cck;
|
||||
|
||||
aniState->noiseFloor = BEACON_RSSI(ah);
|
||||
ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
|
||||
aniState->cckNoiseImmunityLevel, immunityLevel,
|
||||
aniState->noiseFloor, aniState->rssiThrLow,
|
||||
BEACON_RSSI(ah), aniState->rssiThrLow,
|
||||
aniState->rssiThrHigh);
|
||||
|
||||
if ((ah->opmode == NL80211_IFTYPE_STATION ||
|
||||
ah->opmode == NL80211_IFTYPE_ADHOC) &&
|
||||
aniState->noiseFloor <= aniState->rssiThrLow &&
|
||||
if (ah->opmode == NL80211_IFTYPE_STATION &&
|
||||
BEACON_RSSI(ah) <= aniState->rssiThrLow &&
|
||||
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
|
||||
immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
|
||||
|
||||
if (aniState->update_ani)
|
||||
aniState->cckNoiseImmunityLevel =
|
||||
(immunityLevel > ATH9K_ANI_CCK_DEF_LEVEL) ?
|
||||
immunityLevel : ATH9K_ANI_CCK_DEF_LEVEL;
|
||||
aniState->cckNoiseImmunityLevel = immunityLevel;
|
||||
|
||||
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
|
||||
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
|
||||
|
@ -359,7 +238,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
|
|||
if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
|
||||
return;
|
||||
|
||||
if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
|
||||
if (aniState->mrcCCK != entry_cck->mrc_cck_on)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_MRC_CCK,
|
||||
entry_cck->mrc_cck_on);
|
||||
|
@ -372,70 +251,12 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
|
|||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ath9k_hw_ani_cck_err_trigger_old(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
|
||||
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (ah->opmode == NL80211_IFTYPE_AP) {
|
||||
if (aniState->firstepLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel - 1))
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
rssi = BEACON_RSSI(ah);
|
||||
if (rssi > aniState->rssiThrHigh) {
|
||||
/* XXX: Handle me */
|
||||
} else if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->ofdmWeakSigDetectOff) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
true))
|
||||
return;
|
||||
}
|
||||
if (aniState->firstepLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel - 1))
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (aniState->firstepLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel - 1))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aniState->spurImmunityLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel - 1))
|
||||
return;
|
||||
}
|
||||
|
||||
if (aniState->noiseImmunityLevel > 0) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* only lower either OFDM or CCK errors per turn
|
||||
* we lower the other one next time
|
||||
|
@ -446,11 +267,6 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
|
|||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ath9k_hw_ani_lower_immunity_old(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
/* lower OFDM noise immunity */
|
||||
if (aniState->ofdmNoiseImmunityLevel > 0 &&
|
||||
(aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
|
||||
|
@ -463,72 +279,6 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
|
|||
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
|
||||
}
|
||||
|
||||
static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
|
||||
{
|
||||
struct ar5416AniState *aniState;
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
|
||||
if (ah->opmode != NL80211_IFTYPE_STATION
|
||||
&& ah->opmode != NL80211_IFTYPE_ADHOC) {
|
||||
ath_dbg(common, ANI, "Reset ANI state opmode %u\n", ah->opmode);
|
||||
ah->stats.ast_ani_reset++;
|
||||
|
||||
if (ah->opmode == NL80211_IFTYPE_AP) {
|
||||
/*
|
||||
* ath9k_hw_ani_control() will only process items set on
|
||||
* ah->ani_function
|
||||
*/
|
||||
if (IS_CHAN_2GHZ(chan))
|
||||
ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
|
||||
ATH9K_ANI_FIRSTEP_LEVEL);
|
||||
else
|
||||
ah->ani_function = 0;
|
||||
}
|
||||
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
!ATH9K_ANI_USE_OFDM_WEAK_SIG);
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
|
||||
ATH9K_ANI_CCK_WEAK_SIG_THR);
|
||||
|
||||
ath9k_ani_restart(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aniState->noiseImmunityLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel);
|
||||
if (aniState->spurImmunityLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel);
|
||||
if (aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
!aniState->ofdmWeakSigDetectOff);
|
||||
if (aniState->cckWeakSigThreshold)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
|
||||
aniState->cckWeakSigThreshold);
|
||||
if (aniState->firstepLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel);
|
||||
|
||||
ath9k_ani_restart(ah);
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the ANI parameters in the HAL and reset the statistics.
|
||||
* This routine should be called for every hardware reset and for
|
||||
|
@ -539,13 +289,11 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
|
|||
struct ar5416AniState *aniState = &ah->curchan->ani;
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int ofdm_nil, cck_nil;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
if (!use_new_ani(ah))
|
||||
return ath9k_ani_reset_old(ah, is_scanning);
|
||||
|
||||
BUG_ON(aniState == NULL);
|
||||
ah->stats.ast_ani_reset++;
|
||||
|
||||
|
@ -563,6 +311,11 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
|
|||
/* always allow mode (on/off) to be controlled */
|
||||
ah->ani_function |= ATH9K_ANI_MODE;
|
||||
|
||||
ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
|
||||
aniState->ofdmNoiseImmunityLevel);
|
||||
cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
|
||||
aniState->cckNoiseImmunityLevel);
|
||||
|
||||
if (is_scanning ||
|
||||
(ah->opmode != NL80211_IFTYPE_STATION &&
|
||||
ah->opmode != NL80211_IFTYPE_ADHOC)) {
|
||||
|
@ -586,8 +339,8 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
|
|||
aniState->cckNoiseImmunityLevel);
|
||||
|
||||
aniState->update_ani = false;
|
||||
ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
|
||||
ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
|
||||
ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
|
||||
cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -603,11 +356,9 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
|
|||
aniState->cckNoiseImmunityLevel);
|
||||
|
||||
aniState->update_ani = true;
|
||||
ath9k_hw_set_ofdm_nil(ah,
|
||||
aniState->ofdmNoiseImmunityLevel);
|
||||
ath9k_hw_set_cck_nil(ah,
|
||||
aniState->cckNoiseImmunityLevel);
|
||||
}
|
||||
ath9k_hw_set_ofdm_nil(ah, ofdm_nil);
|
||||
ath9k_hw_set_cck_nil(ah, cck_nil);
|
||||
|
||||
/*
|
||||
* enable phy counters if hw supports or if not, enable phy
|
||||
|
@ -627,9 +378,6 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
|
|||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ar5416AniState *aniState = &ah->curchan->ani;
|
||||
u32 ofdm_base = 0;
|
||||
u32 cck_base = 0;
|
||||
u32 ofdmPhyErrCnt, cckPhyErrCnt;
|
||||
u32 phyCnt1, phyCnt2;
|
||||
int32_t listenTime;
|
||||
|
||||
|
@ -642,11 +390,6 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!use_new_ani(ah)) {
|
||||
ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
|
||||
cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
|
||||
}
|
||||
|
||||
aniState->listenTime += listenTime;
|
||||
|
||||
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
|
||||
|
@ -654,35 +397,12 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
|
|||
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
|
||||
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
|
||||
|
||||
if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
|
||||
if (phyCnt1 < ofdm_base) {
|
||||
ath_dbg(common, ANI,
|
||||
"phyCnt1 0x%x, resetting counter value to 0x%x\n",
|
||||
phyCnt1, ofdm_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1,
|
||||
AR_PHY_ERR_OFDM_TIMING);
|
||||
}
|
||||
if (phyCnt2 < cck_base) {
|
||||
ath_dbg(common, ANI,
|
||||
"phyCnt2 0x%x, resetting counter value to 0x%x\n",
|
||||
phyCnt2, cck_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2,
|
||||
AR_PHY_ERR_CCK_TIMING);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ah->stats.ast_ani_ofdmerrs += phyCnt1 - aniState->ofdmPhyErrCount;
|
||||
aniState->ofdmPhyErrCount = phyCnt1;
|
||||
|
||||
ofdmPhyErrCnt = phyCnt1 - ofdm_base;
|
||||
ah->stats.ast_ani_ofdmerrs +=
|
||||
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
|
||||
aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
|
||||
ah->stats.ast_ani_cckerrs += phyCnt2 - aniState->cckPhyErrCount;
|
||||
aniState->cckPhyErrCount = phyCnt2;
|
||||
|
||||
cckPhyErrCnt = phyCnt2 - cck_base;
|
||||
ah->stats.ast_ani_cckerrs +=
|
||||
cckPhyErrCnt - aniState->cckPhyErrCount;
|
||||
aniState->cckPhyErrCount = cckPhyErrCnt;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -716,21 +436,10 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
|
||||
if (aniState->listenTime > ah->aniperiod) {
|
||||
if (cckPhyErrRate < ah->config.cck_trig_low &&
|
||||
((ofdmPhyErrRate < ah->config.ofdm_trig_low &&
|
||||
aniState->ofdmNoiseImmunityLevel <
|
||||
ATH9K_ANI_OFDM_DEF_LEVEL) ||
|
||||
(ofdmPhyErrRate < ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI &&
|
||||
aniState->ofdmNoiseImmunityLevel >=
|
||||
ATH9K_ANI_OFDM_DEF_LEVEL))) {
|
||||
ofdmPhyErrRate < ah->config.ofdm_trig_low) {
|
||||
ath9k_hw_ani_lower_immunity(ah);
|
||||
aniState->ofdmsTurn = !aniState->ofdmsTurn;
|
||||
} else if ((ofdmPhyErrRate > ah->config.ofdm_trig_high &&
|
||||
aniState->ofdmNoiseImmunityLevel >=
|
||||
ATH9K_ANI_OFDM_DEF_LEVEL) ||
|
||||
(ofdmPhyErrRate >
|
||||
ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI &&
|
||||
aniState->ofdmNoiseImmunityLevel <
|
||||
ATH9K_ANI_OFDM_DEF_LEVEL)) {
|
||||
} else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
|
||||
ath9k_hw_ani_ofdm_err_trigger(ah);
|
||||
aniState->ofdmsTurn = false;
|
||||
} else if (cckPhyErrRate > ah->config.cck_trig_high) {
|
||||
|
@ -778,49 +487,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
|
|||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
|
||||
|
||||
/*
|
||||
* Process a MIB interrupt. We may potentially be invoked because
|
||||
* any of the MIB counters overflow/trigger so don't assume we're
|
||||
* here because a PHY error counter triggered.
|
||||
*/
|
||||
void ath9k_hw_proc_mib_event(struct ath_hw *ah)
|
||||
{
|
||||
u32 phyCnt1, phyCnt2;
|
||||
|
||||
/* Reset these counters regardless */
|
||||
REG_WRITE(ah, AR_FILT_OFDM, 0);
|
||||
REG_WRITE(ah, AR_FILT_CCK, 0);
|
||||
if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
|
||||
REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
|
||||
|
||||
/* Clear the mib counters and save them in the stats */
|
||||
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
|
||||
|
||||
if (!DO_ANI(ah)) {
|
||||
/*
|
||||
* We must always clear the interrupt cause by
|
||||
* resetting the phy error regs.
|
||||
*/
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, 0);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* NB: these are not reset-on-read */
|
||||
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
|
||||
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
|
||||
if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
|
||||
((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
|
||||
|
||||
if (!use_new_ani(ah))
|
||||
ath9k_hw_ani_read_counters(ah);
|
||||
|
||||
/* NB: always restart to insure the h/w counters are reset */
|
||||
ath9k_ani_restart(ah);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_proc_mib_event);
|
||||
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
@ -845,50 +511,27 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
|
|||
|
||||
ath_dbg(common, ANI, "Initialize ANI\n");
|
||||
|
||||
if (use_new_ani(ah)) {
|
||||
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
|
||||
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
|
||||
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
|
||||
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
|
||||
|
||||
ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
|
||||
ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
|
||||
} else {
|
||||
ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
|
||||
ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
|
||||
|
||||
ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
|
||||
ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
|
||||
}
|
||||
ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
|
||||
ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
|
||||
struct ath9k_channel *chan = &ah->channels[i];
|
||||
struct ar5416AniState *ani = &chan->ani;
|
||||
|
||||
if (use_new_ani(ah)) {
|
||||
ani->spurImmunityLevel =
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
|
||||
ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
|
||||
|
||||
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
|
||||
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
ani->mrcCCKOff =
|
||||
!ATH9K_ANI_ENABLE_MRC_CCK;
|
||||
else
|
||||
ani->mrcCCKOff = true;
|
||||
ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false;
|
||||
|
||||
ani->ofdmsTurn = true;
|
||||
} else {
|
||||
ani->spurImmunityLevel =
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
|
||||
ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
|
||||
|
||||
ani->cckWeakSigThreshold =
|
||||
ATH9K_ANI_CCK_WEAK_SIG_THR;
|
||||
}
|
||||
ani->ofdmsTurn = true;
|
||||
|
||||
ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
|
||||
ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
|
||||
ani->ofdmWeakSigDetectOff =
|
||||
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
|
||||
ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
|
||||
ani->update_ani = false;
|
||||
|
@ -898,13 +541,8 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
|
|||
* since we expect some ongoing maintenance on the tables, let's sanity
|
||||
* check here default level should not modify INI setting.
|
||||
*/
|
||||
if (use_new_ani(ah)) {
|
||||
ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
|
||||
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
|
||||
} else {
|
||||
ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
|
||||
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
|
||||
}
|
||||
ah->aniperiod = ATH9K_ANI_PERIOD;
|
||||
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL;
|
||||
|
||||
if (ah->config.enable_ani)
|
||||
ah->proc_phyerr |= HAL_PROCESS_ANI;
|
||||
|
|
|
@ -24,42 +24,34 @@
|
|||
#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
|
||||
|
||||
/* units are errors per second */
|
||||
#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500
|
||||
#define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 3500
|
||||
#define ATH9K_ANI_OFDM_TRIG_HIGH 3500
|
||||
#define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
|
||||
|
||||
/* units are errors per second */
|
||||
#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200
|
||||
#define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400
|
||||
#define ATH9K_ANI_OFDM_TRIG_LOW 400
|
||||
#define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
|
||||
|
||||
/* units are errors per second */
|
||||
#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200
|
||||
#define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600
|
||||
#define ATH9K_ANI_CCK_TRIG_HIGH 600
|
||||
|
||||
/* units are errors per second */
|
||||
#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100
|
||||
#define ATH9K_ANI_CCK_TRIG_LOW_NEW 300
|
||||
#define ATH9K_ANI_CCK_TRIG_LOW 300
|
||||
|
||||
#define ATH9K_ANI_NOISE_IMMUNE_LVL 4
|
||||
#define ATH9K_ANI_USE_OFDM_WEAK_SIG true
|
||||
#define ATH9K_ANI_CCK_WEAK_SIG_THR false
|
||||
|
||||
#define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7
|
||||
#define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3
|
||||
#define ATH9K_ANI_SPUR_IMMUNE_LVL 3
|
||||
|
||||
#define ATH9K_ANI_FIRSTEP_LVL_OLD 0
|
||||
#define ATH9K_ANI_FIRSTEP_LVL_NEW 2
|
||||
#define ATH9K_ANI_FIRSTEP_LVL 2
|
||||
|
||||
#define ATH9K_ANI_RSSI_THR_HIGH 40
|
||||
#define ATH9K_ANI_RSSI_THR_LOW 7
|
||||
|
||||
#define ATH9K_ANI_PERIOD_OLD 100
|
||||
#define ATH9K_ANI_PERIOD_NEW 300
|
||||
#define ATH9K_ANI_PERIOD 300
|
||||
|
||||
/* in ms */
|
||||
#define ATH9K_ANI_POLLINTERVAL_OLD 100
|
||||
#define ATH9K_ANI_POLLINTERVAL_NEW 1000
|
||||
#define ATH9K_ANI_POLLINTERVAL 1000
|
||||
|
||||
#define HAL_NOISE_IMMUNE_MAX 4
|
||||
#define HAL_SPUR_IMMUNE_MAX 7
|
||||
|
@ -70,8 +62,6 @@
|
|||
#define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0
|
||||
#define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22
|
||||
|
||||
#define ATH9K_ANI_ENABLE_MRC_CCK true
|
||||
|
||||
/* values here are relative to the INI */
|
||||
|
||||
enum ath9k_ani_cmd {
|
||||
|
@ -119,16 +109,15 @@ struct ar5416AniState {
|
|||
u8 ofdmNoiseImmunityLevel;
|
||||
u8 cckNoiseImmunityLevel;
|
||||
bool ofdmsTurn;
|
||||
u8 mrcCCKOff;
|
||||
u8 mrcCCK;
|
||||
u8 spurImmunityLevel;
|
||||
u8 firstepLevel;
|
||||
u8 ofdmWeakSigDetectOff;
|
||||
u8 ofdmWeakSigDetect;
|
||||
u8 cckWeakSigThreshold;
|
||||
bool update_ani;
|
||||
u32 listenTime;
|
||||
int32_t rssiThrLow;
|
||||
int32_t rssiThrHigh;
|
||||
u32 noiseFloor;
|
||||
u32 ofdmPhyErrCount;
|
||||
u32 cckPhyErrCount;
|
||||
int16_t pktRssi[2];
|
||||
|
|
|
@ -995,141 +995,6 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah,
|
|||
return pll;
|
||||
}
|
||||
|
||||
static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
|
||||
enum ath9k_ani_cmd cmd,
|
||||
int param)
|
||||
{
|
||||
struct ar5416AniState *aniState = &ah->curchan->ani;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
switch (cmd & ah->ani_function) {
|
||||
case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
|
||||
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
|
||||
level, ARRAY_SIZE(ah->totalSizeDesired));
|
||||
return false;
|
||||
}
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
|
||||
AR_PHY_DESIRED_SZ_TOT_DES,
|
||||
ah->totalSizeDesired[level]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
|
||||
AR_PHY_AGC_CTL1_COARSE_LOW,
|
||||
ah->coarse_low[level]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
|
||||
AR_PHY_AGC_CTL1_COARSE_HIGH,
|
||||
ah->coarse_high[level]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
|
||||
AR_PHY_FIND_SIG_FIRPWR,
|
||||
ah->firpwr[level]);
|
||||
|
||||
if (level > aniState->noiseImmunityLevel)
|
||||
ah->stats.ast_ani_niup++;
|
||||
else if (level < aniState->noiseImmunityLevel)
|
||||
ah->stats.ast_ani_nidown++;
|
||||
aniState->noiseImmunityLevel = level;
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
|
||||
u32 on = param ? 1 : 0;
|
||||
|
||||
if (on)
|
||||
REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
|
||||
else
|
||||
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
|
||||
|
||||
if (!on != aniState->ofdmWeakSigDetectOff) {
|
||||
if (on)
|
||||
ah->stats.ast_ani_ofdmon++;
|
||||
else
|
||||
ah->stats.ast_ani_ofdmoff++;
|
||||
aniState->ofdmWeakSigDetectOff = !on;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
|
||||
static const int weakSigThrCck[] = { 8, 6 };
|
||||
u32 high = param ? 1 : 0;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
|
||||
AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
|
||||
weakSigThrCck[high]);
|
||||
if (high != aniState->cckWeakSigThreshold) {
|
||||
if (high)
|
||||
ah->stats.ast_ani_cckhigh++;
|
||||
else
|
||||
ah->stats.ast_ani_ccklow++;
|
||||
aniState->cckWeakSigThreshold = high;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_FIRSTEP_LEVEL:{
|
||||
static const int firstep[] = { 0, 4, 8 };
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(firstep)) {
|
||||
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
|
||||
level, ARRAY_SIZE(firstep));
|
||||
return false;
|
||||
}
|
||||
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
|
||||
AR_PHY_FIND_SIG_FIRSTEP,
|
||||
firstep[level]);
|
||||
if (level > aniState->firstepLevel)
|
||||
ah->stats.ast_ani_stepup++;
|
||||
else if (level < aniState->firstepLevel)
|
||||
ah->stats.ast_ani_stepdown++;
|
||||
aniState->firstepLevel = level;
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
|
||||
static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(cycpwrThr1)) {
|
||||
ath_dbg(common, ANI, "level out of range (%u > %zu)\n",
|
||||
level, ARRAY_SIZE(cycpwrThr1));
|
||||
return false;
|
||||
}
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING5,
|
||||
AR_PHY_TIMING5_CYCPWR_THR1,
|
||||
cycpwrThr1[level]);
|
||||
if (level > aniState->spurImmunityLevel)
|
||||
ah->stats.ast_ani_spurup++;
|
||||
else if (level < aniState->spurImmunityLevel)
|
||||
ah->stats.ast_ani_spurdown++;
|
||||
aniState->spurImmunityLevel = level;
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_PRESENT:
|
||||
break;
|
||||
default:
|
||||
ath_dbg(common, ANI, "invalid cmd %u\n", cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
ath_dbg(common, ANI, "ANI parameters:\n");
|
||||
ath_dbg(common, ANI,
|
||||
"noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n",
|
||||
aniState->noiseImmunityLevel,
|
||||
aniState->spurImmunityLevel,
|
||||
!aniState->ofdmWeakSigDetectOff);
|
||||
ath_dbg(common, ANI,
|
||||
"cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n",
|
||||
aniState->cckWeakSigThreshold,
|
||||
aniState->firstepLevel,
|
||||
aniState->listenTime);
|
||||
ath_dbg(common, ANI, "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
|
||||
aniState->ofdmPhyErrCount,
|
||||
aniState->cckPhyErrCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
||||
enum ath9k_ani_cmd cmd,
|
||||
int param)
|
||||
|
@ -1206,18 +1071,18 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
|
||||
|
||||
if (!on != aniState->ofdmWeakSigDetectOff) {
|
||||
if (on != aniState->ofdmWeakSigDetect) {
|
||||
ath_dbg(common, ANI,
|
||||
"** ch %d: ofdm weak signal: %s=>%s\n",
|
||||
chan->channel,
|
||||
!aniState->ofdmWeakSigDetectOff ?
|
||||
aniState->ofdmWeakSigDetect ?
|
||||
"on" : "off",
|
||||
on ? "on" : "off");
|
||||
if (on)
|
||||
ah->stats.ast_ani_ofdmon++;
|
||||
else
|
||||
ah->stats.ast_ani_ofdmoff++;
|
||||
aniState->ofdmWeakSigDetectOff = !on;
|
||||
aniState->ofdmWeakSigDetect = on;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1236,7 +1101,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
* from INI file & cap value
|
||||
*/
|
||||
value = firstep_table[level] -
|
||||
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
|
||||
firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
|
||||
aniState->iniDef.firstep;
|
||||
if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
|
||||
value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
|
||||
|
@ -1251,7 +1116,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
* from INI file & cap value
|
||||
*/
|
||||
value2 = firstep_table[level] -
|
||||
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
|
||||
firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
|
||||
aniState->iniDef.firstepLow;
|
||||
if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
|
||||
value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
|
||||
|
@ -1267,7 +1132,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
chan->channel,
|
||||
aniState->firstepLevel,
|
||||
level,
|
||||
ATH9K_ANI_FIRSTEP_LVL_NEW,
|
||||
ATH9K_ANI_FIRSTEP_LVL,
|
||||
value,
|
||||
aniState->iniDef.firstep);
|
||||
ath_dbg(common, ANI,
|
||||
|
@ -1275,7 +1140,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
chan->channel,
|
||||
aniState->firstepLevel,
|
||||
level,
|
||||
ATH9K_ANI_FIRSTEP_LVL_NEW,
|
||||
ATH9K_ANI_FIRSTEP_LVL,
|
||||
value2,
|
||||
aniState->iniDef.firstepLow);
|
||||
if (level > aniState->firstepLevel)
|
||||
|
@ -1300,7 +1165,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
* from INI file & cap value
|
||||
*/
|
||||
value = cycpwrThr1_table[level] -
|
||||
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
|
||||
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
|
||||
aniState->iniDef.cycpwrThr1;
|
||||
if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
|
||||
value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
|
||||
|
@ -1316,7 +1181,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
* from INI file & cap value
|
||||
*/
|
||||
value2 = cycpwrThr1_table[level] -
|
||||
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
|
||||
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
|
||||
aniState->iniDef.cycpwrThr1Ext;
|
||||
if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
|
||||
value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
|
||||
|
@ -1331,7 +1196,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
chan->channel,
|
||||
aniState->spurImmunityLevel,
|
||||
level,
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL,
|
||||
value,
|
||||
aniState->iniDef.cycpwrThr1);
|
||||
ath_dbg(common, ANI,
|
||||
|
@ -1339,7 +1204,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
chan->channel,
|
||||
aniState->spurImmunityLevel,
|
||||
level,
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL,
|
||||
value2,
|
||||
aniState->iniDef.cycpwrThr1Ext);
|
||||
if (level > aniState->spurImmunityLevel)
|
||||
|
@ -1367,9 +1232,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
|
|||
ath_dbg(common, ANI,
|
||||
"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
|
||||
aniState->spurImmunityLevel,
|
||||
!aniState->ofdmWeakSigDetectOff ? "on" : "off",
|
||||
aniState->ofdmWeakSigDetect ? "on" : "off",
|
||||
aniState->firstepLevel,
|
||||
!aniState->mrcCCKOff ? "on" : "off",
|
||||
aniState->mrcCCK ? "on" : "off",
|
||||
aniState->listenTime,
|
||||
aniState->ofdmPhyErrCount,
|
||||
aniState->cckPhyErrCount);
|
||||
|
@ -1454,10 +1319,10 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
|
|||
AR_PHY_EXT_TIMING5_CYCPWR_THR1);
|
||||
|
||||
/* these levels just got reset to defaults by the INI */
|
||||
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
|
||||
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
|
||||
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
aniState->mrcCCKOff = true; /* not available on pre AR9003 */
|
||||
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
|
||||
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
|
||||
aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
aniState->mrcCCK = false; /* not available on pre AR9003 */
|
||||
}
|
||||
|
||||
static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
|
||||
|
@ -1545,11 +1410,8 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
|
|||
priv_ops->do_getnf = ar5008_hw_do_getnf;
|
||||
priv_ops->set_radar_params = ar5008_hw_set_radar_params;
|
||||
|
||||
if (modparam_force_new_ani) {
|
||||
priv_ops->ani_control = ar5008_hw_ani_control_new;
|
||||
priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
|
||||
} else
|
||||
priv_ops->ani_control = ar5008_hw_ani_control_old;
|
||||
priv_ops->ani_control = ar5008_hw_ani_control_new;
|
||||
priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
|
||||
|
||||
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
|
||||
priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
#include "ar9002_initvals.h"
|
||||
#include "ar9002_phy.h"
|
||||
|
||||
int modparam_force_new_ani;
|
||||
module_param_named(force_new_ani, modparam_force_new_ani, int, 0444);
|
||||
MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002");
|
||||
|
||||
/* General hardware code for the A5008/AR9001/AR9002 hadware families */
|
||||
|
||||
static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
|
|
|
@ -181,11 +181,14 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
|||
u32 mask2 = 0;
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 sync_cause = 0, async_cause;
|
||||
u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ;
|
||||
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
async_mask |= AR_INTR_ASYNC_MASK_MCI;
|
||||
|
||||
async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
|
||||
|
||||
if (async_cause & (AR_INTR_MAC_IRQ | AR_INTR_ASYNC_MASK_MCI)) {
|
||||
if (async_cause & async_mask) {
|
||||
if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
|
||||
== AR_RTC_STATUS_ON)
|
||||
isr = REG_READ(ah, AR_ISR);
|
||||
|
|
|
@ -321,7 +321,7 @@ void ar9003_mci_set_full_sleep(struct ath_hw *ah)
|
|||
{
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
|
||||
if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) &&
|
||||
if (ar9003_mci_state(ah, MCI_STATE_ENABLE) &&
|
||||
(mci->bt_state != MCI_BT_SLEEP) &&
|
||||
!mci->halted_bt_gpm) {
|
||||
ar9003_mci_send_coex_halt_bt_gpm(ah, true, true);
|
||||
|
@ -484,7 +484,7 @@ static void ar9003_mci_sync_bt_state(struct ath_hw *ah)
|
|||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
u32 cur_bt_state;
|
||||
|
||||
cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL);
|
||||
cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP);
|
||||
|
||||
if (mci->bt_state != cur_bt_state)
|
||||
mci->bt_state = cur_bt_state;
|
||||
|
@ -593,8 +593,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
|
|||
if (!time_out)
|
||||
break;
|
||||
|
||||
offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
|
||||
&more_data);
|
||||
offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
|
||||
|
||||
if (offset == MCI_GPM_INVALID)
|
||||
continue;
|
||||
|
@ -658,8 +657,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
|
|||
time_out = 0;
|
||||
|
||||
while (more_data == MCI_GPM_MORE) {
|
||||
offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
|
||||
&more_data);
|
||||
offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
|
||||
if (offset == MCI_GPM_INVALID)
|
||||
break;
|
||||
|
||||
|
@ -769,10 +767,6 @@ static void ar9003_mci_mute_bt(struct ath_hw *ah)
|
|||
{
|
||||
/* disable all MCI messages */
|
||||
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
|
||||
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
|
||||
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff);
|
||||
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff);
|
||||
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff);
|
||||
REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
|
||||
|
||||
/* wait pending HW messages to flush out */
|
||||
|
@ -893,13 +887,16 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
|||
udelay(100);
|
||||
}
|
||||
|
||||
/* Check pending GPM msg before MCI Reset Rx */
|
||||
ar9003_mci_check_gpm_offset(ah);
|
||||
|
||||
regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
|
||||
REG_WRITE(ah, AR_MCI_COMMAND2, regval);
|
||||
udelay(1);
|
||||
regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
|
||||
REG_WRITE(ah, AR_MCI_COMMAND2, regval);
|
||||
|
||||
ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL);
|
||||
ar9003_mci_get_next_gpm_offset(ah, true, NULL);
|
||||
|
||||
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
|
||||
(SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
|
||||
|
@ -1010,17 +1007,20 @@ static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
|
|||
}
|
||||
}
|
||||
|
||||
void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
|
||||
void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
|
||||
{
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
|
||||
if (!mci->update_2g5g)
|
||||
if (!mci->update_2g5g && !force)
|
||||
return;
|
||||
|
||||
if (mci->is_2g) {
|
||||
ar9003_mci_send_2g5g_status(ah, true);
|
||||
ar9003_mci_send_lna_transfer(ah, true);
|
||||
udelay(5);
|
||||
if (!force) {
|
||||
ar9003_mci_send_2g5g_status(ah, true);
|
||||
|
||||
ar9003_mci_send_lna_transfer(ah, true);
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
|
||||
AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
|
||||
|
@ -1028,20 +1028,21 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
|
|||
AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
|
||||
|
||||
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
|
||||
REG_SET_BIT(ah, AR_BTCOEX_CTRL,
|
||||
AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
|
||||
ar9003_mci_osla_setup(ah, true);
|
||||
} else {
|
||||
ar9003_mci_send_lna_take(ah, true);
|
||||
udelay(5);
|
||||
if (!force) {
|
||||
ar9003_mci_send_lna_take(ah, true);
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_MCI_TX_CTRL,
|
||||
AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
|
||||
REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
|
||||
AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
|
||||
REG_CLR_BIT(ah, AR_BTCOEX_CTRL,
|
||||
AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
|
||||
|
||||
ar9003_mci_send_2g5g_status(ah, true);
|
||||
ar9003_mci_osla_setup(ah, false);
|
||||
if (!force)
|
||||
ar9003_mci_send_2g5g_status(ah, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1169,11 +1170,10 @@ void ar9003_mci_cleanup(struct ath_hw *ah)
|
|||
}
|
||||
EXPORT_SYMBOL(ar9003_mci_cleanup);
|
||||
|
||||
u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
|
||||
u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
u32 value = 0, more_gpm = 0, gpm_ptr;
|
||||
u32 value = 0;
|
||||
u8 query_type;
|
||||
|
||||
switch (state_type) {
|
||||
|
@ -1185,81 +1185,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
|
|||
value = 0;
|
||||
}
|
||||
value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
|
||||
break;
|
||||
case MCI_STATE_INIT_GPM_OFFSET:
|
||||
value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
mci->gpm_idx = value;
|
||||
break;
|
||||
case MCI_STATE_NEXT_GPM_OFFSET:
|
||||
case MCI_STATE_LAST_GPM_OFFSET:
|
||||
/*
|
||||
* This could be useful to avoid new GPM message interrupt which
|
||||
* may lead to spurious interrupt after power sleep, or multiple
|
||||
* entry of ath_mci_intr().
|
||||
* Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
|
||||
* alleviate this effect, but clearing GPM RX interrupt bit is
|
||||
* safe, because whether this is called from hw or driver code
|
||||
* there must be an interrupt bit set/triggered initially
|
||||
*/
|
||||
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
|
||||
AR_MCI_INTERRUPT_RX_MSG_GPM);
|
||||
|
||||
gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
value = gpm_ptr;
|
||||
|
||||
if (value == 0)
|
||||
value = mci->gpm_len - 1;
|
||||
else if (value >= mci->gpm_len) {
|
||||
if (value != 0xFFFF)
|
||||
value = 0;
|
||||
} else {
|
||||
value--;
|
||||
}
|
||||
|
||||
if (value == 0xFFFF) {
|
||||
value = MCI_GPM_INVALID;
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
} else if (state_type == MCI_STATE_NEXT_GPM_OFFSET) {
|
||||
if (gpm_ptr == mci->gpm_idx) {
|
||||
value = MCI_GPM_INVALID;
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
} else {
|
||||
for (;;) {
|
||||
u32 temp_index;
|
||||
|
||||
/* skip reserved GPM if any */
|
||||
|
||||
if (value != mci->gpm_idx)
|
||||
more_gpm = MCI_GPM_MORE;
|
||||
else
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
|
||||
temp_index = mci->gpm_idx;
|
||||
mci->gpm_idx++;
|
||||
|
||||
if (mci->gpm_idx >=
|
||||
mci->gpm_len)
|
||||
mci->gpm_idx = 0;
|
||||
|
||||
if (ar9003_mci_is_gpm_valid(ah,
|
||||
temp_index)) {
|
||||
value = temp_index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (more_gpm == MCI_GPM_NOMORE) {
|
||||
value = MCI_GPM_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p_data)
|
||||
*p_data = more_gpm;
|
||||
}
|
||||
|
||||
if (value != MCI_GPM_INVALID)
|
||||
value <<= 4;
|
||||
|
||||
break;
|
||||
case MCI_STATE_LAST_SCHD_MSG_OFFSET:
|
||||
value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
|
||||
|
@ -1272,21 +1197,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
|
|||
AR_MCI_RX_REMOTE_SLEEP) ?
|
||||
MCI_BT_SLEEP : MCI_BT_AWAKE;
|
||||
break;
|
||||
case MCI_STATE_CONT_RSSI_POWER:
|
||||
value = MS(mci->cont_status, AR_MCI_CONT_RSSI_POWER);
|
||||
break;
|
||||
case MCI_STATE_CONT_PRIORITY:
|
||||
value = MS(mci->cont_status, AR_MCI_CONT_RRIORITY);
|
||||
break;
|
||||
case MCI_STATE_CONT_TXRX:
|
||||
value = MS(mci->cont_status, AR_MCI_CONT_TXRX);
|
||||
break;
|
||||
case MCI_STATE_BT:
|
||||
value = mci->bt_state;
|
||||
break;
|
||||
case MCI_STATE_SET_BT_SLEEP:
|
||||
mci->bt_state = MCI_BT_SLEEP;
|
||||
break;
|
||||
case MCI_STATE_SET_BT_AWAKE:
|
||||
mci->bt_state = MCI_BT_AWAKE;
|
||||
ar9003_mci_send_coex_version_query(ah, true);
|
||||
|
@ -1295,7 +1205,7 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
|
|||
if (mci->unhalt_bt_gpm)
|
||||
ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
|
||||
|
||||
ar9003_mci_2g5g_switch(ah, true);
|
||||
ar9003_mci_2g5g_switch(ah, false);
|
||||
break;
|
||||
case MCI_STATE_SET_BT_CAL_START:
|
||||
mci->bt_state = MCI_BT_CAL_START;
|
||||
|
@ -1319,34 +1229,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
|
|||
case MCI_STATE_SEND_WLAN_COEX_VERSION:
|
||||
ar9003_mci_send_coex_version_response(ah, true);
|
||||
break;
|
||||
case MCI_STATE_SET_BT_COEX_VERSION:
|
||||
if (!p_data)
|
||||
ath_dbg(common, MCI,
|
||||
"MCI Set BT Coex version with NULL data!!\n");
|
||||
else {
|
||||
mci->bt_ver_major = (*p_data >> 8) & 0xff;
|
||||
mci->bt_ver_minor = (*p_data) & 0xff;
|
||||
mci->bt_version_known = true;
|
||||
ath_dbg(common, MCI, "MCI BT version set: %d.%d\n",
|
||||
mci->bt_ver_major, mci->bt_ver_minor);
|
||||
}
|
||||
break;
|
||||
case MCI_STATE_SEND_WLAN_CHANNELS:
|
||||
if (p_data) {
|
||||
if (((mci->wlan_channels[1] & 0xffff0000) ==
|
||||
(*(p_data + 1) & 0xffff0000)) &&
|
||||
(mci->wlan_channels[2] == *(p_data + 2)) &&
|
||||
(mci->wlan_channels[3] == *(p_data + 3)))
|
||||
break;
|
||||
|
||||
mci->wlan_channels[0] = *p_data++;
|
||||
mci->wlan_channels[1] = *p_data++;
|
||||
mci->wlan_channels[2] = *p_data++;
|
||||
mci->wlan_channels[3] = *p_data++;
|
||||
}
|
||||
mci->wlan_channels_update = true;
|
||||
ar9003_mci_send_coex_wlan_channels(ah, true);
|
||||
break;
|
||||
case MCI_STATE_SEND_VERSION_QUERY:
|
||||
ar9003_mci_send_coex_version_query(ah, true);
|
||||
break;
|
||||
|
@ -1354,29 +1236,12 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
|
|||
query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY;
|
||||
ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
|
||||
break;
|
||||
case MCI_STATE_NEED_FLUSH_BT_INFO:
|
||||
/*
|
||||
* btcoex_hw.mci.unhalt_bt_gpm means whether it's
|
||||
* needed to send UNHALT message. It's set whenever
|
||||
* there's a request to send HALT message.
|
||||
* mci_halted_bt_gpm means whether HALT message is sent
|
||||
* out successfully.
|
||||
*
|
||||
* Checking (mci_unhalt_bt_gpm == false) instead of
|
||||
* checking (ah->mci_halted_bt_gpm == false) will make
|
||||
* sure currently is in UNHALT-ed mode and BT can
|
||||
* respond to status query.
|
||||
*/
|
||||
value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0;
|
||||
if (p_data)
|
||||
mci->need_flush_btinfo = (*p_data != 0) ? true : false;
|
||||
break;
|
||||
case MCI_STATE_RECOVER_RX:
|
||||
ar9003_mci_prep_interface(ah);
|
||||
mci->query_bt = true;
|
||||
mci->need_flush_btinfo = true;
|
||||
ar9003_mci_send_coex_wlan_channels(ah, true);
|
||||
ar9003_mci_2g5g_switch(ah, true);
|
||||
ar9003_mci_2g5g_switch(ah, false);
|
||||
break;
|
||||
case MCI_STATE_NEED_FTP_STOMP:
|
||||
value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP);
|
||||
|
@ -1396,6 +1261,9 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
|
|||
|
||||
ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n");
|
||||
|
||||
ar9003_mci_send_lna_take(ah, true);
|
||||
udelay(50);
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
|
||||
mci->is_2g = false;
|
||||
mci->update_2g5g = true;
|
||||
|
@ -1404,3 +1272,154 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
|
|||
/* Force another 2g5g update at next scanning */
|
||||
mci->update_2g5g = true;
|
||||
}
|
||||
|
||||
void ar9003_mci_set_power_awake(struct ath_hw *ah)
|
||||
{
|
||||
u32 btcoex_ctrl2, diag_sw;
|
||||
int i;
|
||||
u8 lna_ctrl, bt_sleep;
|
||||
|
||||
for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
|
||||
btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2);
|
||||
if (btcoex_ctrl2 != 0xdeadbeef)
|
||||
break;
|
||||
udelay(AH_TIME_QUANTUM);
|
||||
}
|
||||
REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23)));
|
||||
|
||||
for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
|
||||
diag_sw = REG_READ(ah, AR_DIAG_SW);
|
||||
if (diag_sw != 0xdeadbeef)
|
||||
break;
|
||||
udelay(AH_TIME_QUANTUM);
|
||||
}
|
||||
REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18)));
|
||||
lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3;
|
||||
bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP;
|
||||
|
||||
REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2);
|
||||
REG_WRITE(ah, AR_DIAG_SW, diag_sw);
|
||||
|
||||
if (bt_sleep && (lna_ctrl == 2)) {
|
||||
REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1);
|
||||
REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1);
|
||||
udelay(50);
|
||||
}
|
||||
}
|
||||
|
||||
void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
u32 offset;
|
||||
|
||||
/*
|
||||
* This should only be called before "MAC Warm Reset" or "MCI Reset Rx".
|
||||
*/
|
||||
offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
if (mci->gpm_idx == offset)
|
||||
return;
|
||||
ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n",
|
||||
mci->gpm_idx, offset);
|
||||
mci->query_bt = true;
|
||||
mci->need_flush_btinfo = true;
|
||||
mci->gpm_idx = 0;
|
||||
}
|
||||
|
||||
u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more)
|
||||
{
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
u32 offset, more_gpm = 0, gpm_ptr;
|
||||
|
||||
if (first) {
|
||||
gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
mci->gpm_idx = gpm_ptr;
|
||||
return gpm_ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This could be useful to avoid new GPM message interrupt which
|
||||
* may lead to spurious interrupt after power sleep, or multiple
|
||||
* entry of ath_mci_intr().
|
||||
* Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
|
||||
* alleviate this effect, but clearing GPM RX interrupt bit is
|
||||
* safe, because whether this is called from hw or driver code
|
||||
* there must be an interrupt bit set/triggered initially
|
||||
*/
|
||||
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
|
||||
AR_MCI_INTERRUPT_RX_MSG_GPM);
|
||||
|
||||
gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
offset = gpm_ptr;
|
||||
|
||||
if (!offset)
|
||||
offset = mci->gpm_len - 1;
|
||||
else if (offset >= mci->gpm_len) {
|
||||
if (offset != 0xFFFF)
|
||||
offset = 0;
|
||||
} else {
|
||||
offset--;
|
||||
}
|
||||
|
||||
if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) {
|
||||
offset = MCI_GPM_INVALID;
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
goto out;
|
||||
}
|
||||
for (;;) {
|
||||
u32 temp_index;
|
||||
|
||||
/* skip reserved GPM if any */
|
||||
|
||||
if (offset != mci->gpm_idx)
|
||||
more_gpm = MCI_GPM_MORE;
|
||||
else
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
|
||||
temp_index = mci->gpm_idx;
|
||||
mci->gpm_idx++;
|
||||
|
||||
if (mci->gpm_idx >= mci->gpm_len)
|
||||
mci->gpm_idx = 0;
|
||||
|
||||
if (ar9003_mci_is_gpm_valid(ah, temp_index)) {
|
||||
offset = temp_index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (more_gpm == MCI_GPM_NOMORE) {
|
||||
offset = MCI_GPM_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset != MCI_GPM_INVALID)
|
||||
offset <<= 4;
|
||||
out:
|
||||
if (more)
|
||||
*more = more_gpm;
|
||||
|
||||
return offset;
|
||||
}
|
||||
EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset);
|
||||
|
||||
void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor)
|
||||
{
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
|
||||
mci->bt_ver_major = major;
|
||||
mci->bt_ver_minor = minor;
|
||||
mci->bt_version_known = true;
|
||||
ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n",
|
||||
mci->bt_ver_major, mci->bt_ver_minor);
|
||||
}
|
||||
EXPORT_SYMBOL(ar9003_mci_set_bt_version);
|
||||
|
||||
void ar9003_mci_send_wlan_channels(struct ath_hw *ah)
|
||||
{
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
|
||||
mci->wlan_channels_update = true;
|
||||
ar9003_mci_send_coex_wlan_channels(ah, true);
|
||||
}
|
||||
EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);
|
||||
|
|
|
@ -189,26 +189,15 @@ enum mci_bt_state {
|
|||
/* Type of state query */
|
||||
enum mci_state_type {
|
||||
MCI_STATE_ENABLE,
|
||||
MCI_STATE_INIT_GPM_OFFSET,
|
||||
MCI_STATE_NEXT_GPM_OFFSET,
|
||||
MCI_STATE_LAST_GPM_OFFSET,
|
||||
MCI_STATE_BT,
|
||||
MCI_STATE_SET_BT_SLEEP,
|
||||
MCI_STATE_SET_BT_AWAKE,
|
||||
MCI_STATE_SET_BT_CAL_START,
|
||||
MCI_STATE_SET_BT_CAL,
|
||||
MCI_STATE_LAST_SCHD_MSG_OFFSET,
|
||||
MCI_STATE_REMOTE_SLEEP,
|
||||
MCI_STATE_CONT_RSSI_POWER,
|
||||
MCI_STATE_CONT_PRIORITY,
|
||||
MCI_STATE_CONT_TXRX,
|
||||
MCI_STATE_RESET_REQ_WAKE,
|
||||
MCI_STATE_SEND_WLAN_COEX_VERSION,
|
||||
MCI_STATE_SET_BT_COEX_VERSION,
|
||||
MCI_STATE_SEND_WLAN_CHANNELS,
|
||||
MCI_STATE_SEND_VERSION_QUERY,
|
||||
MCI_STATE_SEND_STATUS_QUERY,
|
||||
MCI_STATE_NEED_FLUSH_BT_INFO,
|
||||
MCI_STATE_SET_CONCUR_TX_PRI,
|
||||
MCI_STATE_RECOVER_RX,
|
||||
MCI_STATE_NEED_FTP_STOMP,
|
||||
|
@ -259,14 +248,15 @@ enum mci_gpm_coex_opcode {
|
|||
bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
|
||||
u32 *payload, u8 len, bool wait_done,
|
||||
bool check_bt);
|
||||
u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data);
|
||||
u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type);
|
||||
void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
|
||||
u16 len, u32 sched_addr);
|
||||
void ar9003_mci_cleanup(struct ath_hw *ah);
|
||||
void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
|
||||
u32 *rx_msg_intr);
|
||||
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
|
||||
|
||||
u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more);
|
||||
void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor);
|
||||
void ar9003_mci_send_wlan_channels(struct ath_hw *ah);
|
||||
/*
|
||||
* These functions are used by ath9k_hw.
|
||||
*/
|
||||
|
@ -277,7 +267,7 @@ void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep);
|
|||
void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable);
|
||||
void ar9003_mci_init_cal_done(struct ath_hw *ah);
|
||||
void ar9003_mci_set_full_sleep(struct ath_hw *ah);
|
||||
void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done);
|
||||
void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force);
|
||||
void ar9003_mci_check_bt(struct ath_hw *ah);
|
||||
bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
|
@ -285,6 +275,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
||||
bool is_full_sleep);
|
||||
void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
|
||||
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
|
||||
void ar9003_mci_set_power_awake(struct ath_hw *ah);
|
||||
void ar9003_mci_check_gpm_offset(struct ath_hw *ah);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -322,6 +315,15 @@ static inline void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
|||
static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
{
|
||||
}
|
||||
static inline void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
|
||||
{
|
||||
}
|
||||
static inline void ar9003_mci_set_power_awake(struct ath_hw *ah)
|
||||
{
|
||||
}
|
||||
static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -173,7 +173,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
|
|||
int cur_bb_spur, negative = 0, cck_spur_freq;
|
||||
int i;
|
||||
int range, max_spur_cnts, synth_freq;
|
||||
u8 *spur_fbin_ptr = NULL;
|
||||
u8 *spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan));
|
||||
|
||||
/*
|
||||
* Need to verify range +/- 10 MHz in control channel, otherwise spur
|
||||
|
@ -181,8 +181,6 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
|
|||
*/
|
||||
|
||||
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
|
||||
spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
|
||||
IS_CHAN_2GHZ(chan));
|
||||
if (spur_fbin_ptr[0] == 0) /* No spur */
|
||||
return;
|
||||
max_spur_cnts = 5;
|
||||
|
@ -825,18 +823,18 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
|
||||
|
||||
if (!on != aniState->ofdmWeakSigDetectOff) {
|
||||
if (on != aniState->ofdmWeakSigDetect) {
|
||||
ath_dbg(common, ANI,
|
||||
"** ch %d: ofdm weak signal: %s=>%s\n",
|
||||
chan->channel,
|
||||
!aniState->ofdmWeakSigDetectOff ?
|
||||
aniState->ofdmWeakSigDetect ?
|
||||
"on" : "off",
|
||||
on ? "on" : "off");
|
||||
if (on)
|
||||
ah->stats.ast_ani_ofdmon++;
|
||||
else
|
||||
ah->stats.ast_ani_ofdmoff++;
|
||||
aniState->ofdmWeakSigDetectOff = !on;
|
||||
aniState->ofdmWeakSigDetect = on;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -855,7 +853,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
* from INI file & cap value
|
||||
*/
|
||||
value = firstep_table[level] -
|
||||
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
|
||||
firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
|
||||
aniState->iniDef.firstep;
|
||||
if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
|
||||
value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
|
||||
|
@ -870,7 +868,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
* from INI file & cap value
|
||||
*/
|
||||
value2 = firstep_table[level] -
|
||||
firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
|
||||
firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
|
||||
aniState->iniDef.firstepLow;
|
||||
if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
|
||||
value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
|
||||
|
@ -886,7 +884,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
chan->channel,
|
||||
aniState->firstepLevel,
|
||||
level,
|
||||
ATH9K_ANI_FIRSTEP_LVL_NEW,
|
||||
ATH9K_ANI_FIRSTEP_LVL,
|
||||
value,
|
||||
aniState->iniDef.firstep);
|
||||
ath_dbg(common, ANI,
|
||||
|
@ -894,7 +892,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
chan->channel,
|
||||
aniState->firstepLevel,
|
||||
level,
|
||||
ATH9K_ANI_FIRSTEP_LVL_NEW,
|
||||
ATH9K_ANI_FIRSTEP_LVL,
|
||||
value2,
|
||||
aniState->iniDef.firstepLow);
|
||||
if (level > aniState->firstepLevel)
|
||||
|
@ -919,7 +917,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
* from INI file & cap value
|
||||
*/
|
||||
value = cycpwrThr1_table[level] -
|
||||
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
|
||||
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
|
||||
aniState->iniDef.cycpwrThr1;
|
||||
if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
|
||||
value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
|
||||
|
@ -935,7 +933,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
* from INI file & cap value
|
||||
*/
|
||||
value2 = cycpwrThr1_table[level] -
|
||||
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
|
||||
cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
|
||||
aniState->iniDef.cycpwrThr1Ext;
|
||||
if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
|
||||
value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
|
||||
|
@ -950,7 +948,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
chan->channel,
|
||||
aniState->spurImmunityLevel,
|
||||
level,
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL,
|
||||
value,
|
||||
aniState->iniDef.cycpwrThr1);
|
||||
ath_dbg(common, ANI,
|
||||
|
@ -958,7 +956,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
chan->channel,
|
||||
aniState->spurImmunityLevel,
|
||||
level,
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
|
||||
ATH9K_ANI_SPUR_IMMUNE_LVL,
|
||||
value2,
|
||||
aniState->iniDef.cycpwrThr1Ext);
|
||||
if (level > aniState->spurImmunityLevel)
|
||||
|
@ -979,16 +977,16 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
AR_PHY_MRC_CCK_ENABLE, is_on);
|
||||
REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
|
||||
AR_PHY_MRC_CCK_MUX_REG, is_on);
|
||||
if (!is_on != aniState->mrcCCKOff) {
|
||||
if (is_on != aniState->mrcCCK) {
|
||||
ath_dbg(common, ANI, "** ch %d: MRC CCK: %s=>%s\n",
|
||||
chan->channel,
|
||||
!aniState->mrcCCKOff ? "on" : "off",
|
||||
aniState->mrcCCK ? "on" : "off",
|
||||
is_on ? "on" : "off");
|
||||
if (is_on)
|
||||
ah->stats.ast_ani_ccklow++;
|
||||
else
|
||||
ah->stats.ast_ani_cckhigh++;
|
||||
aniState->mrcCCKOff = !is_on;
|
||||
aniState->mrcCCK = is_on;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1002,9 +1000,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
|||
ath_dbg(common, ANI,
|
||||
"ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
|
||||
aniState->spurImmunityLevel,
|
||||
!aniState->ofdmWeakSigDetectOff ? "on" : "off",
|
||||
aniState->ofdmWeakSigDetect ? "on" : "off",
|
||||
aniState->firstepLevel,
|
||||
!aniState->mrcCCKOff ? "on" : "off",
|
||||
aniState->mrcCCK ? "on" : "off",
|
||||
aniState->listenTime,
|
||||
aniState->ofdmPhyErrCount,
|
||||
aniState->cckPhyErrCount);
|
||||
|
@ -1111,10 +1109,10 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
|
|||
AR_PHY_EXT_CYCPWR_THR1);
|
||||
|
||||
/* these levels just got reset to defaults by the INI */
|
||||
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
|
||||
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
|
||||
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
|
||||
aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
|
||||
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
|
||||
aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
aniState->mrcCCK = true;
|
||||
}
|
||||
|
||||
static void ar9003_hw_set_radar_params(struct ath_hw *ah,
|
||||
|
|
|
@ -52,7 +52,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
|
|||
{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
|
||||
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
|
||||
{0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x33795d5e},
|
||||
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e},
|
||||
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
|
||||
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
|
||||
|
@ -61,7 +61,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
|
|||
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
|
||||
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
|
||||
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
|
||||
{0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0},
|
||||
{0x0000a204, 0x01318fc0, 0x01318fc4, 0x01318fc4, 0x01318fc0},
|
||||
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
|
||||
{0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f},
|
||||
{0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
|
||||
|
@ -1007,6 +1007,7 @@ static const u32 ar9462_2p0_radio_core[][2] = {
|
|||
|
||||
static const u32 ar9462_2p0_soc_preamble[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000040a4 ,0x00a0c1c9},
|
||||
{0x00007020, 0x00000000},
|
||||
{0x00007034, 0x00000002},
|
||||
{0x00007038, 0x000004c2},
|
||||
|
|
|
@ -698,6 +698,7 @@ struct ath_softc {
|
|||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||
struct ath_btcoex btcoex;
|
||||
struct ath_mci_coex mci_coex;
|
||||
struct work_struct mci_work;
|
||||
#endif
|
||||
|
||||
struct ath_descdma txsdma;
|
||||
|
@ -720,6 +721,7 @@ extern int ath9k_modparam_nohwcrypt;
|
|||
extern int led_blink;
|
||||
extern bool is_ath9k_unloaded;
|
||||
|
||||
u8 ath9k_parse_mpdudensity(u8 mpdudensity);
|
||||
irqreturn_t ath_isr(int irq, void *dev);
|
||||
int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
const struct ath_bus_ops *bus_ops);
|
||||
|
|
|
@ -348,8 +348,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
|
|||
sc->debug.stats.istats.txok++;
|
||||
if (status & ATH9K_INT_TXURN)
|
||||
sc->debug.stats.istats.txurn++;
|
||||
if (status & ATH9K_INT_MIB)
|
||||
sc->debug.stats.istats.mib++;
|
||||
if (status & ATH9K_INT_RXPHY)
|
||||
sc->debug.stats.istats.rxphyerr++;
|
||||
if (status & ATH9K_INT_RXKCM)
|
||||
|
|
|
@ -202,7 +202,7 @@ static void ath_btcoex_period_timer(unsigned long data)
|
|||
|
||||
btcoex->bt_wait_time += btcoex->btcoex_period;
|
||||
if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
|
||||
if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP, NULL) &&
|
||||
if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
|
||||
(mci->num_pan || mci->num_other_acl))
|
||||
ah->btcoex_hw.mci.stomp_ftp =
|
||||
(sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
|
||||
|
@ -232,7 +232,7 @@ static void ath_btcoex_period_timer(unsigned long data)
|
|||
}
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
timer_period = btcoex->btcoex_period / 1000;
|
||||
timer_period = btcoex->btcoex_period;
|
||||
mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
|
||||
}
|
||||
|
||||
|
@ -267,10 +267,10 @@ static int ath_init_btcoex_timer(struct ath_softc *sc)
|
|||
{
|
||||
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||
|
||||
btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
|
||||
btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
|
||||
btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
|
||||
btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 1000 *
|
||||
btcoex->btcoex_period / 100;
|
||||
btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
|
||||
btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 1000 *
|
||||
btcoex->btcoex_period / 100;
|
||||
|
||||
setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
|
||||
|
|
|
@ -453,7 +453,6 @@ struct ath9k_htc_priv {
|
|||
u8 num_sta_assoc_vif;
|
||||
u8 num_ap_vif;
|
||||
|
||||
u16 op_flags;
|
||||
u16 curtxpow;
|
||||
u16 txpowlimit;
|
||||
u16 nvifs;
|
||||
|
@ -461,6 +460,7 @@ struct ath9k_htc_priv {
|
|||
bool rearm_ani;
|
||||
bool reconfig_beacon;
|
||||
unsigned int rxfilter;
|
||||
unsigned long op_flags;
|
||||
|
||||
struct ath9k_hw_cal_data caldata;
|
||||
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||
|
@ -572,8 +572,6 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
|
|||
|
||||
void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
|
||||
void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
|
||||
void ath9k_htc_radio_enable(struct ieee80211_hw *hw);
|
||||
void ath9k_htc_radio_disable(struct ieee80211_hw *hw);
|
||||
|
||||
#ifdef CONFIG_MAC80211_LEDS
|
||||
void ath9k_init_leds(struct ath9k_htc_priv *priv);
|
||||
|
|
|
@ -207,9 +207,9 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
|
|||
else
|
||||
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
|
||||
|
||||
if (priv->op_flags & OP_TSF_RESET) {
|
||||
if (test_bit(OP_TSF_RESET, &priv->op_flags)) {
|
||||
ath9k_hw_reset_tsf(priv->ah);
|
||||
priv->op_flags &= ~OP_TSF_RESET;
|
||||
clear_bit(OP_TSF_RESET, &priv->op_flags);
|
||||
} else {
|
||||
/*
|
||||
* Pull nexttbtt forward to reflect the current TSF.
|
||||
|
@ -221,7 +221,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
|
|||
} while (nexttbtt < tsftu);
|
||||
}
|
||||
|
||||
if (priv->op_flags & OP_ENABLE_BEACON)
|
||||
if (test_bit(OP_ENABLE_BEACON, &priv->op_flags))
|
||||
imask |= ATH9K_INT_SWBA;
|
||||
|
||||
ath_dbg(common, CONFIG,
|
||||
|
@ -269,7 +269,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
|
|||
else
|
||||
priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE;
|
||||
|
||||
if (priv->op_flags & OP_ENABLE_BEACON)
|
||||
if (test_bit(OP_ENABLE_BEACON, &priv->op_flags))
|
||||
imask |= ATH9K_INT_SWBA;
|
||||
|
||||
ath_dbg(common, CONFIG,
|
||||
|
@ -365,7 +365,7 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
|
|||
vif = priv->cur_beacon_conf.bslot[slot];
|
||||
avp = (struct ath9k_htc_vif *)vif->drv_priv;
|
||||
|
||||
if (unlikely(priv->op_flags & OP_SCANNING)) {
|
||||
if (unlikely(test_bit(OP_SCANNING, &priv->op_flags))) {
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -37,17 +37,18 @@ static void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
|
|||
|
||||
if (time_after(jiffies, btcoex->bt_priority_time +
|
||||
msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
|
||||
priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
|
||||
clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
|
||||
clear_bit(OP_BT_SCAN, &priv->op_flags);
|
||||
/* Detect if colocated bt started scanning */
|
||||
if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
|
||||
ath_dbg(ath9k_hw_common(ah), BTCOEX,
|
||||
"BT scan detected\n");
|
||||
priv->op_flags |= (OP_BT_SCAN |
|
||||
OP_BT_PRIORITY_DETECTED);
|
||||
set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
|
||||
set_bit(OP_BT_SCAN, &priv->op_flags);
|
||||
} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
|
||||
ath_dbg(ath9k_hw_common(ah), BTCOEX,
|
||||
"BT priority traffic detected\n");
|
||||
priv->op_flags |= OP_BT_PRIORITY_DETECTED;
|
||||
set_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
|
||||
}
|
||||
|
||||
btcoex->bt_priority_cnt = 0;
|
||||
|
@ -67,26 +68,23 @@ static void ath_btcoex_period_work(struct work_struct *work)
|
|||
struct ath_btcoex *btcoex = &priv->btcoex;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
u32 timer_period;
|
||||
bool is_btscan;
|
||||
int ret;
|
||||
|
||||
ath_detect_bt_priority(priv);
|
||||
|
||||
is_btscan = !!(priv->op_flags & OP_BT_SCAN);
|
||||
|
||||
ret = ath9k_htc_update_cap_target(priv,
|
||||
!!(priv->op_flags & OP_BT_PRIORITY_DETECTED));
|
||||
test_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags));
|
||||
if (ret) {
|
||||
ath_err(common, "Unable to set BTCOEX parameters\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
|
||||
btcoex->bt_stomp_type);
|
||||
ath9k_hw_btcoex_bt_stomp(priv->ah, test_bit(OP_BT_SCAN, &priv->op_flags) ?
|
||||
ATH_BTCOEX_STOMP_ALL : btcoex->bt_stomp_type);
|
||||
|
||||
ath9k_hw_btcoex_enable(priv->ah);
|
||||
timer_period = is_btscan ? btcoex->btscan_no_stomp :
|
||||
btcoex->btcoex_no_stomp;
|
||||
timer_period = test_bit(OP_BT_SCAN, &priv->op_flags) ?
|
||||
btcoex->btscan_no_stomp : btcoex->btcoex_no_stomp;
|
||||
ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
|
||||
msecs_to_jiffies(timer_period));
|
||||
ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work,
|
||||
|
@ -104,14 +102,15 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work)
|
|||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_btcoex *btcoex = &priv->btcoex;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
bool is_btscan = priv->op_flags & OP_BT_SCAN;
|
||||
|
||||
ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n");
|
||||
|
||||
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
|
||||
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
|
||||
test_bit(OP_BT_SCAN, &priv->op_flags))
|
||||
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
|
||||
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
|
||||
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
|
||||
|
||||
ath9k_hw_btcoex_enable(priv->ah);
|
||||
}
|
||||
|
||||
|
@ -141,7 +140,8 @@ static void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
|
|||
|
||||
btcoex->bt_priority_cnt = 0;
|
||||
btcoex->bt_priority_time = jiffies;
|
||||
priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
|
||||
clear_bit(OP_BT_PRIORITY_DETECTED, &priv->op_flags);
|
||||
clear_bit(OP_BT_SCAN, &priv->op_flags);
|
||||
ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
|
||||
}
|
||||
|
||||
|
@ -310,95 +310,3 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
|
|||
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
|
||||
wiphy_rfkill_start_polling(priv->hw->wiphy);
|
||||
}
|
||||
|
||||
void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int ret;
|
||||
u8 cmd_rsp;
|
||||
|
||||
if (!ah->curchan)
|
||||
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
|
||||
|
||||
/* Reset the HW */
|
||||
ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
|
||||
if (ret) {
|
||||
ath_err(common,
|
||||
"Unable to reset hardware; reset status %d (freq %u MHz)\n",
|
||||
ret, ah->curchan->channel);
|
||||
}
|
||||
|
||||
ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
|
||||
&priv->curtxpow);
|
||||
|
||||
/* Start RX */
|
||||
WMI_CMD(WMI_START_RECV_CMDID);
|
||||
ath9k_host_rx_init(priv);
|
||||
|
||||
/* Start TX */
|
||||
htc_start(priv->htc);
|
||||
spin_lock_bh(&priv->tx.tx_lock);
|
||||
priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
|
||||
spin_unlock_bh(&priv->tx.tx_lock);
|
||||
ieee80211_wake_queues(hw);
|
||||
|
||||
WMI_CMD(WMI_ENABLE_INTR_CMDID);
|
||||
|
||||
/* Enable LED */
|
||||
ath9k_hw_cfg_output(ah, ah->led_pin,
|
||||
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
||||
}
|
||||
|
||||
void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int ret;
|
||||
u8 cmd_rsp;
|
||||
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
|
||||
/* Disable LED */
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 1);
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||
|
||||
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||
|
||||
/* Stop TX */
|
||||
ieee80211_stop_queues(hw);
|
||||
ath9k_htc_tx_drain(priv);
|
||||
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
|
||||
|
||||
/* Stop RX */
|
||||
WMI_CMD(WMI_STOP_RECV_CMDID);
|
||||
|
||||
/* Clear the WMI event queue */
|
||||
ath9k_wmi_event_drain(priv);
|
||||
|
||||
/*
|
||||
* The MIB counters have to be disabled here,
|
||||
* since the target doesn't do it.
|
||||
*/
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
|
||||
if (!ah->curchan)
|
||||
ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
|
||||
|
||||
/* Reset the HW */
|
||||
ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
|
||||
if (ret) {
|
||||
ath_err(common,
|
||||
"Unable to reset hardware; reset status %d (freq %u MHz)\n",
|
||||
ret, ah->curchan->channel);
|
||||
}
|
||||
|
||||
/* Disable the PHY */
|
||||
ath9k_hw_phy_disable(ah);
|
||||
|
||||
ath9k_htc_ps_restore(priv);
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
|
||||
}
|
||||
|
|
|
@ -611,7 +611,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
|||
struct ath_common *common;
|
||||
int i, ret = 0, csz = 0;
|
||||
|
||||
priv->op_flags |= OP_INVALID;
|
||||
set_bit(OP_INVALID, &priv->op_flags);
|
||||
|
||||
ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
|
||||
if (!ah)
|
||||
|
@ -718,7 +718,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
|||
|
||||
hw->queues = 4;
|
||||
hw->channel_change_time = 5000;
|
||||
hw->max_listen_interval = 10;
|
||||
hw->max_listen_interval = 1;
|
||||
|
||||
hw->vif_data_size = sizeof(struct ath9k_htc_vif);
|
||||
hw->sta_data_size = sizeof(struct ath9k_htc_sta);
|
||||
|
|
|
@ -75,14 +75,19 @@ void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv)
|
|||
|
||||
void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
bool reset;
|
||||
|
||||
mutex_lock(&priv->htc_pm_lock);
|
||||
if (--priv->ps_usecount != 0)
|
||||
goto unlock;
|
||||
|
||||
if (priv->ps_idle)
|
||||
if (priv->ps_idle) {
|
||||
ath9k_hw_setrxabort(priv->ah, true);
|
||||
ath9k_hw_stopdmarecv(priv->ah, &reset);
|
||||
ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
|
||||
else if (priv->ps_enabled)
|
||||
} else if (priv->ps_enabled) {
|
||||
ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
|
@ -250,7 +255,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
|||
u8 cmd_rsp;
|
||||
int ret;
|
||||
|
||||
if (priv->op_flags & OP_INVALID)
|
||||
if (test_bit(OP_INVALID, &priv->op_flags))
|
||||
return -EIO;
|
||||
|
||||
fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
|
||||
|
@ -304,7 +309,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
|||
|
||||
htc_start(priv->htc);
|
||||
|
||||
if (!(priv->op_flags & OP_SCANNING) &&
|
||||
if (!test_bit(OP_SCANNING, &priv->op_flags) &&
|
||||
!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
|
||||
ath9k_htc_vif_reconfig(priv);
|
||||
|
||||
|
@ -750,7 +755,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
|
|||
common->ani.shortcal_timer = timestamp;
|
||||
common->ani.checkani_timer = timestamp;
|
||||
|
||||
priv->op_flags |= OP_ANI_RUNNING;
|
||||
set_bit(OP_ANI_RUNNING, &priv->op_flags);
|
||||
|
||||
ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
|
||||
msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
|
||||
|
@ -759,7 +764,7 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
|
|||
void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
cancel_delayed_work_sync(&priv->ani_work);
|
||||
priv->op_flags &= ~OP_ANI_RUNNING;
|
||||
clear_bit(OP_ANI_RUNNING, &priv->op_flags);
|
||||
}
|
||||
|
||||
void ath9k_htc_ani_work(struct work_struct *work)
|
||||
|
@ -944,7 +949,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
|
|||
ath_dbg(common, CONFIG,
|
||||
"Failed to update capability in target\n");
|
||||
|
||||
priv->op_flags &= ~OP_INVALID;
|
||||
clear_bit(OP_INVALID, &priv->op_flags);
|
||||
htc_start(priv->htc);
|
||||
|
||||
spin_lock_bh(&priv->tx.tx_lock);
|
||||
|
@ -973,7 +978,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (priv->op_flags & OP_INVALID) {
|
||||
if (test_bit(OP_INVALID, &priv->op_flags)) {
|
||||
ath_dbg(common, ANY, "Device not present\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
|
@ -1015,7 +1020,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
|||
ath9k_htc_ps_restore(priv);
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
|
||||
|
||||
priv->op_flags |= OP_INVALID;
|
||||
set_bit(OP_INVALID, &priv->op_flags);
|
||||
|
||||
ath_dbg(common, CONFIG, "Driver halt\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
@ -1105,7 +1110,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
|||
ath9k_htc_set_opmode(priv);
|
||||
|
||||
if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
|
||||
!(priv->op_flags & OP_ANI_RUNNING)) {
|
||||
!test_bit(OP_ANI_RUNNING, &priv->op_flags)) {
|
||||
ath9k_hw_set_tsfadjust(priv->ah, 1);
|
||||
ath9k_htc_start_ani(priv);
|
||||
}
|
||||
|
@ -1178,24 +1183,20 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
|||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
bool chip_reset = false;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||
bool enable_radio = false;
|
||||
bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
|
||||
|
||||
mutex_lock(&priv->htc_pm_lock);
|
||||
if (!idle && priv->ps_idle)
|
||||
enable_radio = true;
|
||||
priv->ps_idle = idle;
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
|
||||
if (enable_radio) {
|
||||
ath_dbg(common, CONFIG, "not-idle: enabling radio\n");
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
|
||||
ath9k_htc_radio_enable(hw);
|
||||
}
|
||||
priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
|
||||
if (priv->ps_idle)
|
||||
chip_reset = true;
|
||||
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1210,7 +1211,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
|||
ath9k_htc_remove_monitor_interface(priv);
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) {
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
int pos = curchan->hw_value;
|
||||
|
||||
|
@ -1223,8 +1224,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
|||
|
||||
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
|
||||
ath_err(common, "Unable to set channel\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1246,21 +1247,10 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
|||
priv->txpowlimit, &priv->curtxpow);
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||
mutex_lock(&priv->htc_pm_lock);
|
||||
if (!priv->ps_idle) {
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
|
||||
ath_dbg(common, CONFIG, "idle: disabling radio\n");
|
||||
ath9k_htc_radio_disable(hw);
|
||||
}
|
||||
|
||||
out:
|
||||
ath9k_htc_ps_restore(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SUPPORTED_FILTERS \
|
||||
|
@ -1285,7 +1275,7 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
|
|||
changed_flags &= SUPPORTED_FILTERS;
|
||||
*total_flags &= SUPPORTED_FILTERS;
|
||||
|
||||
if (priv->op_flags & OP_INVALID) {
|
||||
if (test_bit(OP_INVALID, &priv->op_flags)) {
|
||||
ath_dbg(ath9k_hw_common(priv->ah), ANY,
|
||||
"Unable to configure filter on invalid state\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
@ -1517,7 +1507,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
|
|||
ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n",
|
||||
bss_conf->bssid);
|
||||
ath9k_htc_set_tsfadjust(priv, vif);
|
||||
priv->op_flags |= OP_ENABLE_BEACON;
|
||||
set_bit(OP_ENABLE_BEACON, &priv->op_flags);
|
||||
ath9k_htc_beacon_config(priv, vif);
|
||||
}
|
||||
|
||||
|
@ -1530,7 +1520,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
|
|||
ath_dbg(common, CONFIG,
|
||||
"Beacon disabled for BSS: %pM\n",
|
||||
bss_conf->bssid);
|
||||
priv->op_flags &= ~OP_ENABLE_BEACON;
|
||||
clear_bit(OP_ENABLE_BEACON, &priv->op_flags);
|
||||
ath9k_htc_beacon_config(priv, vif);
|
||||
}
|
||||
}
|
||||
|
@ -1543,7 +1533,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
|
|||
(priv->nvifs == 1) &&
|
||||
(priv->num_ap_vif == 1) &&
|
||||
(vif->type == NL80211_IFTYPE_AP)) {
|
||||
priv->op_flags |= OP_TSF_RESET;
|
||||
set_bit(OP_TSF_RESET, &priv->op_flags);
|
||||
}
|
||||
ath_dbg(common, CONFIG,
|
||||
"Beacon interval changed for BSS: %pM\n",
|
||||
|
@ -1655,7 +1645,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
spin_lock_bh(&priv->beacon_lock);
|
||||
priv->op_flags |= OP_SCANNING;
|
||||
set_bit(OP_SCANNING, &priv->op_flags);
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
cancel_work_sync(&priv->ps_work);
|
||||
ath9k_htc_stop_ani(priv);
|
||||
|
@ -1668,7 +1658,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
spin_lock_bh(&priv->beacon_lock);
|
||||
priv->op_flags &= ~OP_SCANNING;
|
||||
clear_bit(OP_SCANNING, &priv->op_flags);
|
||||
spin_unlock_bh(&priv->beacon_lock);
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
ath9k_htc_vif_reconfig(priv);
|
||||
|
|
|
@ -916,7 +916,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv)
|
|||
{
|
||||
ath9k_hw_rxena(priv->ah);
|
||||
ath9k_htc_opmode_init(priv);
|
||||
ath9k_hw_startpcureceive(priv->ah, (priv->op_flags & OP_SCANNING));
|
||||
ath9k_hw_startpcureceive(priv->ah, test_bit(OP_SCANNING, &priv->op_flags));
|
||||
priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
}
|
||||
|
||||
|
|
|
@ -1348,6 +1348,9 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
|
|||
}
|
||||
}
|
||||
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
ar9003_mci_check_gpm_offset(ah);
|
||||
|
||||
REG_WRITE(ah, AR_RTC_RC, rst_flags);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
|
@ -1708,7 +1711,7 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
ath9k_hw_start_nfcal(ah, true);
|
||||
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
ar9003_mci_2g5g_switch(ah, true);
|
||||
ar9003_mci_2g5g_switch(ah, false);
|
||||
|
||||
if (AR_SREV_9271(ah))
|
||||
ar9002_hw_load_ani_reg(ah, chan);
|
||||
|
@ -1912,7 +1915,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
|
||||
ath9k_hw_set_dma(ah);
|
||||
|
||||
REG_WRITE(ah, AR_OBS, 8);
|
||||
if (!ath9k_hw_mci_is_enabled(ah))
|
||||
REG_WRITE(ah, AR_OBS, 8);
|
||||
|
||||
if (ah->config.rx_intr_mitigation) {
|
||||
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
|
||||
|
@ -2111,6 +2115,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
|
|||
AR_RTC_FORCE_WAKE_EN);
|
||||
udelay(50);
|
||||
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
ar9003_mci_set_power_awake(ah);
|
||||
|
||||
for (i = POWER_UP_TIME / 50; i > 0; i--) {
|
||||
val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
|
||||
if (val == AR_RTC_STATUS_ON)
|
||||
|
|
|
@ -1019,16 +1019,8 @@ void ar9002_hw_attach_ops(struct ath_hw *ah);
|
|||
void ar9003_hw_attach_ops(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
/*
|
||||
* ANI work can be shared between all families but a next
|
||||
* generation implementation of ANI will be used only for AR9003 only
|
||||
* for now as the other families still need to be tested with the same
|
||||
* next generation ANI. Feel free to start testing it though for the
|
||||
* older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
|
||||
*/
|
||||
extern int modparam_force_new_ani;
|
||||
|
||||
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
|
||||
void ath9k_hw_proc_mib_event(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
|
||||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||
|
@ -1038,7 +1030,8 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah)
|
|||
}
|
||||
static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah)
|
||||
{
|
||||
return ah->btcoex_hw.enabled && (ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
|
||||
return ah->common.btcoex_enabled &&
|
||||
(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
|
||||
|
||||
}
|
||||
void ath9k_hw_btcoex_enable(struct ath_hw *ah);
|
||||
|
|
|
@ -136,6 +136,14 @@ void ath_hw_pll_work(struct work_struct *work)
|
|||
u32 pll_sqsum;
|
||||
struct ath_softc *sc = container_of(work, struct ath_softc,
|
||||
hw_pll_work.work);
|
||||
/*
|
||||
* ensure that the PLL WAR is executed only
|
||||
* after the STA is associated (or) if the
|
||||
* beaconing had started in interfaces that
|
||||
* uses beacons.
|
||||
*/
|
||||
if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
|
||||
return;
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
|
||||
|
@ -399,6 +407,7 @@ void ath_ani_calibrate(unsigned long data)
|
|||
longcal ? "long" : "", shortcal ? "short" : "",
|
||||
aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
|
||||
|
||||
ath9k_debug_samp_bb_mac(sc);
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
set_timer:
|
||||
|
@ -407,7 +416,6 @@ void ath_ani_calibrate(unsigned long data)
|
|||
* The interval must be the shortest necessary to satisfy ANI,
|
||||
* short calibration and long calibration.
|
||||
*/
|
||||
ath9k_debug_samp_bb_mac(sc);
|
||||
cal_interval = ATH_LONG_CALINTERVAL;
|
||||
if (sc->sc_ah->config.enable_ani)
|
||||
cal_interval = min(cal_interval,
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "ath9k.h"
|
||||
#include "btcoex.h"
|
||||
|
||||
static u8 parse_mpdudensity(u8 mpdudensity)
|
||||
u8 ath9k_parse_mpdudensity(u8 mpdudensity)
|
||||
{
|
||||
/*
|
||||
* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
|
||||
|
@ -150,6 +150,11 @@ static void __ath_cancel_work(struct ath_softc *sc)
|
|||
cancel_work_sync(&sc->hw_check_work);
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
cancel_delayed_work_sync(&sc->hw_pll_work);
|
||||
|
||||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
|
||||
cancel_work_sync(&sc->mci_work);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ath_cancel_work(struct ath_softc *sc)
|
||||
|
@ -317,6 +322,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_node *an;
|
||||
u8 density;
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
|
@ -331,7 +337,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
ath_tx_node_init(sc, an);
|
||||
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
sta->ht_cap.ampdu_factor);
|
||||
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
an->mpdudensity = density;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,24 +520,6 @@ irqreturn_t ath_isr(int irq, void *dev)
|
|||
ath9k_hw_set_interrupts(ah);
|
||||
}
|
||||
|
||||
if (status & ATH9K_INT_MIB) {
|
||||
/*
|
||||
* Disable interrupts until we service the MIB
|
||||
* interrupt; otherwise it will continue to
|
||||
* fire.
|
||||
*/
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
/*
|
||||
* Let the hal handle the event. We assume
|
||||
* it will clear whatever condition caused
|
||||
* the interrupt.
|
||||
*/
|
||||
spin_lock(&common->cc_lock);
|
||||
ath9k_hw_proc_mib_event(ah);
|
||||
spin_unlock(&common->cc_lock);
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
}
|
||||
|
||||
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
if (status & ATH9K_INT_TIM_TIMER) {
|
||||
if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle))
|
||||
|
@ -956,14 +945,10 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
|
|||
/*
|
||||
* Enable MIB interrupts when there are hardware phy counters.
|
||||
*/
|
||||
if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) {
|
||||
if (ah->config.enable_ani)
|
||||
ah->imask |= ATH9K_INT_MIB;
|
||||
if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
|
||||
ah->imask |= ATH9K_INT_TSFOOR;
|
||||
} else {
|
||||
ah->imask &= ~ATH9K_INT_MIB;
|
||||
else
|
||||
ah->imask &= ~ATH9K_INT_TSFOOR;
|
||||
}
|
||||
|
||||
ath9k_hw_set_interrupts(ah);
|
||||
|
||||
|
@ -1033,15 +1018,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
|
|||
}
|
||||
}
|
||||
|
||||
if ((ah->opmode == NL80211_IFTYPE_ADHOC) ||
|
||||
((vif->type == NL80211_IFTYPE_ADHOC) &&
|
||||
sc->nvifs > 0)) {
|
||||
ath_err(common, "Cannot create ADHOC interface when other"
|
||||
" interfaces already exist.\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
|
||||
|
||||
sc->nvifs++;
|
||||
|
@ -1066,15 +1042,6 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
|
|||
mutex_lock(&sc->mutex);
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
/* See if new interface type is valid. */
|
||||
if ((new_type == NL80211_IFTYPE_ADHOC) &&
|
||||
(sc->nvifs > 1)) {
|
||||
ath_err(common, "When using ADHOC, it must be the only"
|
||||
" interface.\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ath9k_uses_beacons(new_type) &&
|
||||
!ath9k_uses_beacons(vif->type)) {
|
||||
if (sc->nbcnvifs >= ATH_BCBUF) {
|
||||
|
@ -1258,6 +1225,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
|||
if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
|
||||
ath_err(common, "Unable to set channel\n");
|
||||
mutex_unlock(&sc->mutex);
|
||||
ath9k_ps_restore(sc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "ath9k.h"
|
||||
#include "mci.h"
|
||||
|
||||
static const u8 ath_mci_duty_cycle[] = { 0, 50, 60, 70, 80, 85, 90, 95, 98 };
|
||||
static const u8 ath_mci_duty_cycle[] = { 55, 50, 60, 70, 80, 85, 90, 95, 98 };
|
||||
|
||||
static struct ath_mci_profile_info*
|
||||
ath_mci_find_profile(struct ath_mci_profile *mci,
|
||||
|
@ -28,11 +28,14 @@ ath_mci_find_profile(struct ath_mci_profile *mci,
|
|||
{
|
||||
struct ath_mci_profile_info *entry;
|
||||
|
||||
if (list_empty(&mci->info))
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(entry, &mci->info, list) {
|
||||
if (entry->conn_handle == info->conn_handle)
|
||||
break;
|
||||
return entry;
|
||||
}
|
||||
return entry;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool ath_mci_add_profile(struct ath_common *common,
|
||||
|
@ -49,31 +52,21 @@ static bool ath_mci_add_profile(struct ath_common *common,
|
|||
(info->type != MCI_GPM_COEX_PROFILE_VOICE))
|
||||
return false;
|
||||
|
||||
entry = ath_mci_find_profile(mci, info);
|
||||
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
|
||||
if (!entry)
|
||||
return false;
|
||||
|
||||
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);
|
||||
}
|
||||
memcpy(entry, info, 10);
|
||||
INC_PROF(mci, info);
|
||||
list_add_tail(&entry->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)
|
||||
{
|
||||
struct ath_mci_profile_info *entry;
|
||||
|
||||
entry = ath_mci_find_profile(mci, info);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
|
@ -86,12 +79,16 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci)
|
|||
{
|
||||
struct ath_mci_profile_info *info, *tinfo;
|
||||
|
||||
mci->aggr_limit = 0;
|
||||
|
||||
if (list_empty(&mci->info))
|
||||
return;
|
||||
|
||||
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)
|
||||
|
@ -123,6 +120,8 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
|
|||
if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING)
|
||||
goto skip_tuning;
|
||||
|
||||
btcoex->duty_cycle = ath_mci_duty_cycle[num_profile];
|
||||
|
||||
if (num_profile == 1) {
|
||||
info = list_first_entry(&mci->info,
|
||||
struct ath_mci_profile_info,
|
||||
|
@ -181,12 +180,11 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
|
|||
if (IS_CHAN_5GHZ(sc->sc_ah->curchan))
|
||||
return;
|
||||
|
||||
btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_MAX_DUTY_CYCLE : 0);
|
||||
btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_BDR_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 *
|
||||
btcoex->btcoex_no_stomp = btcoex->btcoex_period * 1000 *
|
||||
(100 - btcoex->duty_cycle) / 100;
|
||||
|
||||
ath9k_hw_btcoex_enable(sc->sc_ah);
|
||||
|
@ -197,20 +195,16 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
|
|||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
|
||||
u32 payload[4] = {0, 0, 0, 0};
|
||||
|
||||
switch (opcode) {
|
||||
case MCI_GPM_BT_CAL_REQ:
|
||||
if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) {
|
||||
ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START, NULL);
|
||||
if (mci_hw->bt_state == MCI_BT_AWAKE) {
|
||||
ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START);
|
||||
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
|
||||
} else {
|
||||
ath_dbg(common, MCI, "MCI State mismatch: %d\n",
|
||||
ar9003_mci_state(ah, MCI_STATE_BT, NULL));
|
||||
}
|
||||
break;
|
||||
case MCI_GPM_BT_CAL_DONE:
|
||||
ar9003_mci_state(ah, MCI_STATE_BT, NULL);
|
||||
ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
|
||||
break;
|
||||
case MCI_GPM_BT_CAL_GRANT:
|
||||
MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE);
|
||||
|
@ -223,32 +217,55 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
|
|||
}
|
||||
}
|
||||
|
||||
static void ath9k_mci_work(struct work_struct *work)
|
||||
{
|
||||
struct ath_softc *sc = container_of(work, struct ath_softc, mci_work);
|
||||
|
||||
ath_mci_update_scheme(sc);
|
||||
}
|
||||
|
||||
static 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;
|
||||
struct ath_mci_profile_info *entry = NULL;
|
||||
|
||||
entry = ath_mci_find_profile(mci, info);
|
||||
if (entry) {
|
||||
/*
|
||||
* Two MCI interrupts are generated while connecting to
|
||||
* headset and A2DP profile, but only one MCI interrupt
|
||||
* is generated with last added profile type while disconnecting
|
||||
* both profiles.
|
||||
* So while adding second profile type decrement
|
||||
* the first one.
|
||||
*/
|
||||
if (entry->type != info->type) {
|
||||
DEC_PROF(mci, entry);
|
||||
INC_PROF(mci, info);
|
||||
}
|
||||
memcpy(entry, info, 10);
|
||||
}
|
||||
|
||||
if (info->start) {
|
||||
if (!ath_mci_add_profile(common, mci, info))
|
||||
if (!entry && !ath_mci_add_profile(common, mci, info))
|
||||
return;
|
||||
} else
|
||||
ath_mci_del_profile(common, mci, info);
|
||||
ath_mci_del_profile(common, mci, entry);
|
||||
|
||||
btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD;
|
||||
mci->aggr_limit = mci->num_sco ? 6 : 0;
|
||||
|
||||
if (NUM_PROF(mci)) {
|
||||
btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)];
|
||||
if (NUM_PROF(mci))
|
||||
btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
|
||||
btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)];
|
||||
} else {
|
||||
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);
|
||||
ieee80211_queue_work(sc->hw, &sc->mci_work);
|
||||
}
|
||||
|
||||
static void ath_mci_process_status(struct ath_softc *sc,
|
||||
|
@ -263,8 +280,6 @@ static void ath_mci_process_status(struct ath_softc *sc,
|
|||
if (status->is_link)
|
||||
return;
|
||||
|
||||
memset(&info, 0, sizeof(struct ath_mci_profile_info));
|
||||
|
||||
info.conn_handle = status->conn_handle;
|
||||
if (ath_mci_find_profile(mci, &info))
|
||||
return;
|
||||
|
@ -284,7 +299,7 @@ static void ath_mci_process_status(struct ath_softc *sc,
|
|||
} while (++i < ATH_MCI_MAX_PROFILE);
|
||||
|
||||
if (old_num_mgmt != mci->num_mgmt)
|
||||
ath_mci_update_scheme(sc);
|
||||
ieee80211_queue_work(sc->hw, &sc->mci_work);
|
||||
}
|
||||
|
||||
static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
|
||||
|
@ -293,25 +308,20 @@ static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
|
|||
struct ath_mci_profile_info profile_info;
|
||||
struct ath_mci_profile_status profile_status;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
u32 version;
|
||||
u8 major;
|
||||
u8 minor;
|
||||
u8 major, minor;
|
||||
u32 seq_num;
|
||||
|
||||
switch (opcode) {
|
||||
case MCI_GPM_COEX_VERSION_QUERY:
|
||||
version = ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION,
|
||||
NULL);
|
||||
ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_COEX_VERSION);
|
||||
break;
|
||||
case MCI_GPM_COEX_VERSION_RESPONSE:
|
||||
major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION);
|
||||
minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION);
|
||||
version = (major << 8) + minor;
|
||||
version = ar9003_mci_state(ah, MCI_STATE_SET_BT_COEX_VERSION,
|
||||
&version);
|
||||
ar9003_mci_set_bt_version(ah, major, minor);
|
||||
break;
|
||||
case MCI_GPM_COEX_STATUS_QUERY:
|
||||
ar9003_mci_state(ah, MCI_STATE_SEND_WLAN_CHANNELS, NULL);
|
||||
ar9003_mci_send_wlan_channels(ah);
|
||||
break;
|
||||
case MCI_GPM_COEX_BT_PROFILE_INFO:
|
||||
memcpy(&profile_info,
|
||||
|
@ -378,6 +388,7 @@ int ath_mci_setup(struct ath_softc *sc)
|
|||
mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4),
|
||||
mci->sched_buf.bf_paddr);
|
||||
|
||||
INIT_WORK(&sc->mci_work, ath9k_mci_work);
|
||||
ath_dbg(common, MCI, "MCI Initialized\n");
|
||||
|
||||
return 0;
|
||||
|
@ -405,6 +416,7 @@ void ath_mci_intr(struct ath_softc *sc)
|
|||
struct ath_mci_coex *mci = &sc->mci_coex;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
|
||||
u32 mci_int, mci_int_rxmsg;
|
||||
u32 offset, subtype, opcode;
|
||||
u32 *pgpm;
|
||||
|
@ -413,8 +425,8 @@ void ath_mci_intr(struct ath_softc *sc)
|
|||
|
||||
ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg);
|
||||
|
||||
if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) {
|
||||
ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL);
|
||||
if (ar9003_mci_state(ah, MCI_STATE_ENABLE) == 0) {
|
||||
ar9003_mci_get_next_gpm_offset(ah, true, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -433,46 +445,41 @@ void ath_mci_intr(struct ath_softc *sc)
|
|||
NULL, 0, true, false);
|
||||
|
||||
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE;
|
||||
ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE, NULL);
|
||||
ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE);
|
||||
|
||||
/*
|
||||
* always do this for recovery and 2G/5G toggling and LNA_TRANS
|
||||
*/
|
||||
ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE, NULL);
|
||||
ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE);
|
||||
}
|
||||
|
||||
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING) {
|
||||
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING;
|
||||
|
||||
if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_SLEEP) {
|
||||
if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) !=
|
||||
MCI_BT_SLEEP)
|
||||
ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE,
|
||||
NULL);
|
||||
}
|
||||
if ((mci_hw->bt_state == MCI_BT_SLEEP) &&
|
||||
(ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP) !=
|
||||
MCI_BT_SLEEP))
|
||||
ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE);
|
||||
}
|
||||
|
||||
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) {
|
||||
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING;
|
||||
|
||||
if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) {
|
||||
if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) !=
|
||||
MCI_BT_AWAKE)
|
||||
ar9003_mci_state(ah, MCI_STATE_SET_BT_SLEEP,
|
||||
NULL);
|
||||
}
|
||||
if ((mci_hw->bt_state == MCI_BT_AWAKE) &&
|
||||
(ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP) !=
|
||||
MCI_BT_AWAKE))
|
||||
mci_hw->bt_state = MCI_BT_SLEEP;
|
||||
}
|
||||
|
||||
if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) ||
|
||||
(mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) {
|
||||
ar9003_mci_state(ah, MCI_STATE_RECOVER_RX, NULL);
|
||||
ar9003_mci_state(ah, MCI_STATE_RECOVER_RX);
|
||||
skip_gpm = true;
|
||||
}
|
||||
|
||||
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) {
|
||||
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO;
|
||||
offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET,
|
||||
NULL);
|
||||
offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET);
|
||||
}
|
||||
|
||||
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) {
|
||||
|
@ -481,8 +488,8 @@ void ath_mci_intr(struct ath_softc *sc)
|
|||
while (more_data == MCI_GPM_MORE) {
|
||||
|
||||
pgpm = mci->gpm_buf.bf_addr;
|
||||
offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
|
||||
&more_data);
|
||||
offset = ar9003_mci_get_next_gpm_offset(ah, false,
|
||||
&more_data);
|
||||
|
||||
if (offset == MCI_GPM_INVALID)
|
||||
break;
|
||||
|
@ -523,23 +530,17 @@ void ath_mci_intr(struct ath_softc *sc)
|
|||
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO;
|
||||
|
||||
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
|
||||
int value_dbm = ar9003_mci_state(ah,
|
||||
MCI_STATE_CONT_RSSI_POWER, NULL);
|
||||
int value_dbm = MS(mci_hw->cont_status,
|
||||
AR_MCI_CONT_RSSI_POWER);
|
||||
|
||||
mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO;
|
||||
|
||||
if (ar9003_mci_state(ah, MCI_STATE_CONT_TXRX, NULL))
|
||||
ath_dbg(common, MCI,
|
||||
"MCI CONT_INFO: (tx) pri = %d, pwr = %d dBm\n",
|
||||
ar9003_mci_state(ah,
|
||||
MCI_STATE_CONT_PRIORITY, NULL),
|
||||
value_dbm);
|
||||
else
|
||||
ath_dbg(common, MCI,
|
||||
"MCI CONT_INFO: (rx) pri = %d,pwr = %d dBm\n",
|
||||
ar9003_mci_state(ah,
|
||||
MCI_STATE_CONT_PRIORITY, NULL),
|
||||
value_dbm);
|
||||
ath_dbg(common, MCI,
|
||||
"MCI CONT_INFO: (%s) pri = %d pwr = %d dBm\n",
|
||||
MS(mci_hw->cont_status, AR_MCI_CONT_TXRX) ?
|
||||
"tx" : "rx",
|
||||
MS(mci_hw->cont_status, AR_MCI_CONT_PRIORITY),
|
||||
value_dbm);
|
||||
}
|
||||
|
||||
if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_NACK)
|
||||
|
|
|
@ -770,7 +770,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
|||
struct ieee80211_tx_rate *rates = tx_info->control.rates;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 try_per_rate, i = 0, rix, high_rix;
|
||||
u8 try_per_rate, i = 0, rix;
|
||||
int is_probe = 0;
|
||||
|
||||
if (rate_control_send_low(sta, priv_sta, txrc))
|
||||
|
@ -791,7 +791,6 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
|||
rate_table = ath_rc_priv->rate_table;
|
||||
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
|
||||
&is_probe, false);
|
||||
high_rix = rix;
|
||||
|
||||
/*
|
||||
* If we're in HT mode and both us and our peer supports LDPC.
|
||||
|
@ -839,16 +838,16 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
|||
try_per_rate = 8;
|
||||
|
||||
/*
|
||||
* Use a legacy rate as last retry to ensure that the frame
|
||||
* is tried in both MCS and legacy rates.
|
||||
* If the last rate in the rate series is MCS and has
|
||||
* more than 80% of per thresh, then use a legacy rate
|
||||
* as last retry to ensure that the frame is tried in both
|
||||
* MCS and legacy rate.
|
||||
*/
|
||||
if ((rates[2].flags & IEEE80211_TX_RC_MCS) &&
|
||||
(!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) ||
|
||||
(ath_rc_priv->per[high_rix] > 45)))
|
||||
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
|
||||
if (WLAN_RC_PHY_HT(rate_table->info[rix].phy) &&
|
||||
(ath_rc_priv->per[rix] > 45))
|
||||
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
|
||||
&is_probe, true);
|
||||
else
|
||||
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
|
||||
|
||||
/* All other rates in the series have RTS enabled */
|
||||
ath_rc_rate_set_series(rate_table, &rates[i], txrc,
|
||||
|
|
|
@ -2098,8 +2098,8 @@ enum {
|
|||
#define AR_MCI_CONT_STATUS 0x1848
|
||||
#define AR_MCI_CONT_RSSI_POWER 0x000000FF
|
||||
#define AR_MCI_CONT_RSSI_POWER_S 0
|
||||
#define AR_MCI_CONT_RRIORITY 0x0000FF00
|
||||
#define AR_MCI_CONT_RRIORITY_S 8
|
||||
#define AR_MCI_CONT_PRIORITY 0x0000FF00
|
||||
#define AR_MCI_CONT_PRIORITY_S 8
|
||||
#define AR_MCI_CONT_TXRX 0x00010000
|
||||
#define AR_MCI_CONT_TXRX_S 16
|
||||
|
||||
|
@ -2162,10 +2162,6 @@ enum {
|
|||
#define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000
|
||||
#define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31
|
||||
|
||||
#define AR_BTCOEX_WL_WEIGHTS0 0x18b0
|
||||
#define AR_BTCOEX_WL_WEIGHTS1 0x18b4
|
||||
#define AR_BTCOEX_WL_WEIGHTS2 0x18b8
|
||||
#define AR_BTCOEX_WL_WEIGHTS3 0x18bc
|
||||
#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
|
||||
#define AR_BTCOEX_WL_LNA 0x1940
|
||||
#define AR_BTCOEX_RFGAIN_CTRL 0x1944
|
||||
|
|
|
@ -1175,6 +1175,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
{
|
||||
struct ath_atx_tid *txtid;
|
||||
struct ath_node *an;
|
||||
u8 density;
|
||||
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
txtid = ATH_AN_2_TID(an, tid);
|
||||
|
@ -1182,6 +1183,17 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
|
||||
return -EAGAIN;
|
||||
|
||||
/* update ampdu factor/density, they may have changed. This may happen
|
||||
* in HT IBSS when a beacon with HT-info is received after the station
|
||||
* has already been added.
|
||||
*/
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
sta->ht_cap.ampdu_factor);
|
||||
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
an->mpdudensity = density;
|
||||
}
|
||||
|
||||
txtid->state |= AGGR_ADDBA_PROGRESS;
|
||||
txtid->paused = true;
|
||||
*ssn = txtid->seq_start = txtid->seq_next;
|
||||
|
|
|
@ -877,6 +877,10 @@ struct b43_wl {
|
|||
* from the mac80211 subsystem. */
|
||||
u16 mac80211_initially_registered_queues;
|
||||
|
||||
/* Set this if we call ieee80211_register_hw() and check if we call
|
||||
* ieee80211_unregister_hw(). */
|
||||
bool hw_registred;
|
||||
|
||||
/* We can only have one operating interface (802.11 core)
|
||||
* at a time. General information about this interface follows.
|
||||
*/
|
||||
|
|
|
@ -2437,6 +2437,7 @@ static void b43_request_firmware(struct work_struct *work)
|
|||
err = ieee80211_register_hw(wl->hw);
|
||||
if (err)
|
||||
goto err_one_core_detach;
|
||||
wl->hw_registred = true;
|
||||
b43_leds_register(wl->current_dev);
|
||||
goto out;
|
||||
|
||||
|
@ -5299,6 +5300,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
|
|||
|
||||
hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1;
|
||||
wl->mac80211_initially_registered_queues = hw->queues;
|
||||
wl->hw_registred = false;
|
||||
hw->max_rates = 2;
|
||||
SET_IEEE80211_DEV(hw, dev->dev);
|
||||
if (is_valid_ether_addr(sprom->et1mac))
|
||||
|
@ -5370,12 +5372,15 @@ static void b43_bcma_remove(struct bcma_device *core)
|
|||
* as the ieee80211 unreg will destroy the workqueue. */
|
||||
cancel_work_sync(&wldev->restart_work);
|
||||
|
||||
/* Restore the queues count before unregistering, because firmware detect
|
||||
* might have modified it. Restoring is important, so the networking
|
||||
* stack can properly free resources. */
|
||||
wl->hw->queues = wl->mac80211_initially_registered_queues;
|
||||
b43_leds_stop(wldev);
|
||||
ieee80211_unregister_hw(wl->hw);
|
||||
B43_WARN_ON(!wl);
|
||||
if (wl->current_dev == wldev && wl->hw_registred) {
|
||||
/* Restore the queues count before unregistering, because firmware detect
|
||||
* might have modified it. Restoring is important, so the networking
|
||||
* stack can properly free resources. */
|
||||
wl->hw->queues = wl->mac80211_initially_registered_queues;
|
||||
b43_leds_stop(wldev);
|
||||
ieee80211_unregister_hw(wl->hw);
|
||||
}
|
||||
|
||||
b43_one_core_detach(wldev->dev);
|
||||
|
||||
|
@ -5446,7 +5451,7 @@ static void b43_ssb_remove(struct ssb_device *sdev)
|
|||
cancel_work_sync(&wldev->restart_work);
|
||||
|
||||
B43_WARN_ON(!wl);
|
||||
if (wl->current_dev == wldev) {
|
||||
if (wl->current_dev == wldev && wl->hw_registred) {
|
||||
/* Restore the queues count before unregistering, because firmware detect
|
||||
* might have modified it. Restoring is important, so the networking
|
||||
* stack can properly free resources. */
|
||||
|
|
|
@ -34,3 +34,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
|
|||
sdio_chip.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
|
||||
usb.o
|
||||
brcmfmac-$(CONFIG_BRCMDBG) += \
|
||||
dhd_dbg.o
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
|
||||
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
|
||||
#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334
|
||||
|
||||
#define SDIO_FUNC1_BLOCKSIZE 64
|
||||
#define SDIO_FUNC2_BLOCKSIZE 512
|
||||
|
@ -52,6 +53,7 @@
|
|||
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
|
||||
{ /* end: all zeroes */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
||||
|
|
|
@ -613,6 +613,9 @@ struct brcmf_pub {
|
|||
struct work_struct multicast_work;
|
||||
u8 macvalue[ETH_ALEN];
|
||||
atomic_t pend_8021x_cnt;
|
||||
#ifdef DEBUG
|
||||
struct dentry *dbgfs_dir;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct brcmf_if_event {
|
||||
|
|
|
@ -36,6 +36,13 @@ struct dngl_stats {
|
|||
unsigned long multicast; /* multicast packets received */
|
||||
};
|
||||
|
||||
struct brcmf_bus_dcmd {
|
||||
char *name;
|
||||
char *param;
|
||||
int param_len;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/* interface structure between common and bus layer */
|
||||
struct brcmf_bus {
|
||||
u8 type; /* bus type */
|
||||
|
@ -50,6 +57,7 @@ struct brcmf_bus {
|
|||
unsigned long tx_realloc; /* Tx packets realloced for headroom */
|
||||
struct dngl_stats dstats; /* Stats for dongle-based data */
|
||||
u8 align; /* bus alignment requirement */
|
||||
struct list_head dcmd_list;
|
||||
|
||||
/* interface functions pointers */
|
||||
/* Stop bus module: clear pending frames, disable data flow */
|
||||
|
|
|
@ -800,13 +800,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
|
|||
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
|
||||
"event_msgs" + '\0' + bitvec */
|
||||
char buf[128], *ptr;
|
||||
u32 dongle_align = drvr->bus_if->align;
|
||||
u32 glom = 0;
|
||||
u32 roaming = 1;
|
||||
uint bcn_timeout = 3;
|
||||
int scan_assoc_time = 40;
|
||||
int scan_unassoc_time = 40;
|
||||
int i;
|
||||
struct brcmf_bus_dcmd *cmdlst;
|
||||
struct list_head *cur, *q;
|
||||
|
||||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
|
@ -827,17 +827,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
|
|||
/* Print fw version info */
|
||||
brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
|
||||
|
||||
/* Match Host and Dongle rx alignment */
|
||||
brcmf_c_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
|
||||
sizeof(iovbuf));
|
||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
|
||||
sizeof(iovbuf));
|
||||
|
||||
/* disable glom option per default */
|
||||
brcmf_c_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
|
||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
|
||||
sizeof(iovbuf));
|
||||
|
||||
/* Setup timeout if Beacons are lost and roam is off to report
|
||||
link down */
|
||||
brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
|
||||
|
@ -874,6 +863,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
|
|||
0, true);
|
||||
}
|
||||
|
||||
/* set bus specific command if there is any */
|
||||
list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) {
|
||||
cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list);
|
||||
if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
|
||||
brcmf_c_mkiovar(cmdlst->name, cmdlst->param,
|
||||
cmdlst->param_len, iovbuf,
|
||||
sizeof(iovbuf));
|
||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
|
||||
iovbuf, sizeof(iovbuf));
|
||||
}
|
||||
list_del(cur);
|
||||
kfree(cmdlst);
|
||||
}
|
||||
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
|
||||
return 0;
|
||||
|
|
126
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
Normal file
126
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include <brcmu_wifi.h>
|
||||
#include <brcmu_utils.h>
|
||||
#include "dhd.h"
|
||||
#include "dhd_bus.h"
|
||||
#include "dhd_dbg.h"
|
||||
|
||||
static struct dentry *root_folder;
|
||||
|
||||
void brcmf_debugfs_init(void)
|
||||
{
|
||||
root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
|
||||
if (IS_ERR(root_folder))
|
||||
root_folder = NULL;
|
||||
}
|
||||
|
||||
void brcmf_debugfs_exit(void)
|
||||
{
|
||||
if (!root_folder)
|
||||
return;
|
||||
|
||||
debugfs_remove_recursive(root_folder);
|
||||
root_folder = NULL;
|
||||
}
|
||||
|
||||
int brcmf_debugfs_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
if (!root_folder)
|
||||
return -ENODEV;
|
||||
|
||||
drvr->dbgfs_dir = debugfs_create_dir(dev_name(drvr->dev), root_folder);
|
||||
return PTR_RET(drvr->dbgfs_dir);
|
||||
}
|
||||
|
||||
void brcmf_debugfs_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
|
||||
debugfs_remove_recursive(drvr->dbgfs_dir);
|
||||
}
|
||||
|
||||
struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
|
||||
{
|
||||
return drvr->dbgfs_dir;
|
||||
}
|
||||
|
||||
static
|
||||
ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct brcmf_sdio_count *sdcnt = f->private_data;
|
||||
char buf[750];
|
||||
int res;
|
||||
|
||||
/* only allow read from start */
|
||||
if (*ppos > 0)
|
||||
return 0;
|
||||
|
||||
res = scnprintf(buf, sizeof(buf),
|
||||
"intrcount: %u\nlastintrs: %u\n"
|
||||
"pollcnt: %u\nregfails: %u\n"
|
||||
"tx_sderrs: %u\nfcqueued: %u\n"
|
||||
"rxrtx: %u\nrx_toolong: %u\n"
|
||||
"rxc_errors: %u\nrx_hdrfail: %u\n"
|
||||
"rx_badhdr: %u\nrx_badseq: %u\n"
|
||||
"fc_rcvd: %u\nfc_xoff: %u\n"
|
||||
"fc_xon: %u\nrxglomfail: %u\n"
|
||||
"rxglomframes: %u\nrxglompkts: %u\n"
|
||||
"f2rxhdrs: %u\nf2rxdata: %u\n"
|
||||
"f2txdata: %u\nf1regdata: %u\n"
|
||||
"tickcnt: %u\ntx_ctlerrs: %lu\n"
|
||||
"tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n"
|
||||
"rx_ctlpkts: %lu\nrx_readahead: %lu\n",
|
||||
sdcnt->intrcount, sdcnt->lastintrs,
|
||||
sdcnt->pollcnt, sdcnt->regfails,
|
||||
sdcnt->tx_sderrs, sdcnt->fcqueued,
|
||||
sdcnt->rxrtx, sdcnt->rx_toolong,
|
||||
sdcnt->rxc_errors, sdcnt->rx_hdrfail,
|
||||
sdcnt->rx_badhdr, sdcnt->rx_badseq,
|
||||
sdcnt->fc_rcvd, sdcnt->fc_xoff,
|
||||
sdcnt->fc_xon, sdcnt->rxglomfail,
|
||||
sdcnt->rxglomframes, sdcnt->rxglompkts,
|
||||
sdcnt->f2rxhdrs, sdcnt->f2rxdata,
|
||||
sdcnt->f2txdata, sdcnt->f1regdata,
|
||||
sdcnt->tickcnt, sdcnt->tx_ctlerrs,
|
||||
sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
|
||||
sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
|
||||
|
||||
return simple_read_from_buffer(data, count, ppos, buf, res);
|
||||
}
|
||||
|
||||
static const struct file_operations brcmf_debugfs_sdio_counter_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = brcmf_debugfs_sdio_counter_read
|
||||
};
|
||||
|
||||
void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
|
||||
struct brcmf_sdio_count *sdcnt)
|
||||
{
|
||||
struct dentry *dentry = drvr->dbgfs_dir;
|
||||
|
||||
if (!IS_ERR_OR_NULL(dentry))
|
||||
debugfs_create_file("counters", S_IRUGO, dentry,
|
||||
sdcnt, &brcmf_debugfs_sdio_counter_ops);
|
||||
}
|
|
@ -76,4 +76,63 @@ do { \
|
|||
|
||||
extern int brcmf_msg_level;
|
||||
|
||||
/*
|
||||
* hold counter variables used in brcmfmac sdio driver.
|
||||
*/
|
||||
struct brcmf_sdio_count {
|
||||
uint intrcount; /* Count of device interrupt callbacks */
|
||||
uint lastintrs; /* Count as of last watchdog timer */
|
||||
uint pollcnt; /* Count of active polls */
|
||||
uint regfails; /* Count of R_REG failures */
|
||||
uint tx_sderrs; /* Count of tx attempts with sd errors */
|
||||
uint fcqueued; /* Tx packets that got queued */
|
||||
uint rxrtx; /* Count of rtx requests (NAK to dongle) */
|
||||
uint rx_toolong; /* Receive frames too long to receive */
|
||||
uint rxc_errors; /* SDIO errors when reading control frames */
|
||||
uint rx_hdrfail; /* SDIO errors on header reads */
|
||||
uint rx_badhdr; /* Bad received headers (roosync?) */
|
||||
uint rx_badseq; /* Mismatched rx sequence number */
|
||||
uint fc_rcvd; /* Number of flow-control events received */
|
||||
uint fc_xoff; /* Number which turned on flow-control */
|
||||
uint fc_xon; /* Number which turned off flow-control */
|
||||
uint rxglomfail; /* Failed deglom attempts */
|
||||
uint rxglomframes; /* Number of glom frames (superframes) */
|
||||
uint rxglompkts; /* Number of packets from glom frames */
|
||||
uint f2rxhdrs; /* Number of header reads */
|
||||
uint f2rxdata; /* Number of frame data reads */
|
||||
uint f2txdata; /* Number of f2 frame writes */
|
||||
uint f1regdata; /* Number of f1 register accesses */
|
||||
uint tickcnt; /* Number of watchdog been schedule */
|
||||
ulong tx_ctlerrs; /* Err of sending ctrl frames */
|
||||
ulong tx_ctlpkts; /* Ctrl frames sent to dongle */
|
||||
ulong rx_ctlerrs; /* Err of processing rx ctrl frames */
|
||||
ulong rx_ctlpkts; /* Ctrl frames processed from dongle */
|
||||
ulong rx_readahead_cnt; /* packets where header read-ahead was used */
|
||||
};
|
||||
|
||||
struct brcmf_pub;
|
||||
#ifdef DEBUG
|
||||
void brcmf_debugfs_init(void);
|
||||
void brcmf_debugfs_exit(void);
|
||||
int brcmf_debugfs_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_debugfs_detach(struct brcmf_pub *drvr);
|
||||
struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
|
||||
void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
|
||||
struct brcmf_sdio_count *sdcnt);
|
||||
#else
|
||||
static inline void brcmf_debugfs_init(void)
|
||||
{
|
||||
}
|
||||
static inline void brcmf_debugfs_exit(void)
|
||||
{
|
||||
}
|
||||
static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BRCMF_DBG_H_ */
|
||||
|
|
|
@ -1007,6 +1007,9 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
|||
drvr->bus_if->drvr = drvr;
|
||||
drvr->dev = dev;
|
||||
|
||||
/* create device debugfs folder */
|
||||
brcmf_debugfs_attach(drvr);
|
||||
|
||||
/* Attach and link in the protocol */
|
||||
ret = brcmf_proto_attach(drvr);
|
||||
if (ret != 0) {
|
||||
|
@ -1017,6 +1020,8 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
|||
INIT_WORK(&drvr->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&drvr->multicast_work, _brcmf_set_multicast_list);
|
||||
|
||||
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
|
@ -1123,6 +1128,7 @@ void brcmf_detach(struct device *dev)
|
|||
brcmf_proto_detach(drvr);
|
||||
}
|
||||
|
||||
brcmf_debugfs_detach(drvr);
|
||||
bus_if->drvr = NULL;
|
||||
kfree(drvr);
|
||||
}
|
||||
|
@ -1192,6 +1198,8 @@ int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size)
|
|||
|
||||
static void brcmf_driver_init(struct work_struct *work)
|
||||
{
|
||||
brcmf_debugfs_init();
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO
|
||||
brcmf_sdio_init();
|
||||
#endif
|
||||
|
@ -1219,6 +1227,7 @@ static void __exit brcmfmac_module_exit(void)
|
|||
#ifdef CONFIG_BRCMFMAC_USB
|
||||
brcmf_usb_exit();
|
||||
#endif
|
||||
brcmf_debugfs_exit();
|
||||
}
|
||||
|
||||
module_init(brcmfmac_module_init);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -403,6 +403,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
|
|||
ci->c_inf[3].cib = 0x03004211;
|
||||
ci->ramsize = 0x48000;
|
||||
break;
|
||||
case BCM4334_CHIP_ID:
|
||||
ci->c_inf[0].wrapbase = 0x18100000;
|
||||
ci->c_inf[0].cib = 0x29004211;
|
||||
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
|
||||
ci->c_inf[1].base = 0x18002000;
|
||||
ci->c_inf[1].wrapbase = 0x18102000;
|
||||
ci->c_inf[1].cib = 0x0d004211;
|
||||
ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
|
||||
ci->c_inf[2].base = 0x18004000;
|
||||
ci->c_inf[2].wrapbase = 0x18104000;
|
||||
ci->c_inf[2].cib = 0x13080401;
|
||||
ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
|
||||
ci->c_inf[3].base = 0x18003000;
|
||||
ci->c_inf[3].wrapbase = 0x18103000;
|
||||
ci->c_inf[3].cib = 0x07004211;
|
||||
ci->ramsize = 0x80000;
|
||||
break;
|
||||
default:
|
||||
brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
|
||||
return -ENODEV;
|
||||
|
|
|
@ -735,10 +735,8 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
|
|||
* a candidate for aggregation
|
||||
*/
|
||||
p = pktq_ppeek(&qi->q, prec);
|
||||
/* tx_info must be checked with current p */
|
||||
tx_info = IEEE80211_SKB_CB(p);
|
||||
|
||||
if (p) {
|
||||
tx_info = IEEE80211_SKB_CB(p);
|
||||
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
|
||||
((u8) (p->priority) == tid)) {
|
||||
plen = p->len + AMPDU_MAX_MPDU_OVERHEAD;
|
||||
|
@ -759,6 +757,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
|
|||
p = NULL;
|
||||
continue;
|
||||
}
|
||||
/* next packet fit for aggregation so dequeue */
|
||||
p = brcmu_pktq_pdeq(&qi->q, prec);
|
||||
} else {
|
||||
p = NULL;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -37,9 +37,6 @@ brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
|
|||
|
||||
extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
|
||||
|
||||
extern u8 brcms_c_channel_locale_flags_in_band(struct brcms_cm_info *wlc_cm,
|
||||
uint bandunit);
|
||||
|
||||
extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
|
||||
u16 chspec);
|
||||
|
||||
|
@ -49,5 +46,6 @@ extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
|
|||
extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
|
||||
u16 chanspec,
|
||||
u8 local_constraint_qdbm);
|
||||
extern void brcms_c_regd_init(struct brcms_c_info *wlc);
|
||||
|
||||
#endif /* _WLC_CHANNEL_H */
|
||||
|
|
|
@ -721,14 +721,6 @@ static const struct ieee80211_ops brcms_ops = {
|
|||
.flush = brcms_ops_flush,
|
||||
};
|
||||
|
||||
/*
|
||||
* is called in brcms_bcma_probe() context, therefore no locking required.
|
||||
*/
|
||||
static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
|
||||
{
|
||||
return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
|
||||
}
|
||||
|
||||
void brcms_dpc(unsigned long data)
|
||||
{
|
||||
struct brcms_info *wl;
|
||||
|
@ -1058,6 +1050,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
brcms_c_regd_init(wl->wlc);
|
||||
|
||||
memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
|
||||
if (WARN_ON(!is_valid_ether_addr(perm)))
|
||||
goto fail;
|
||||
|
@ -1068,9 +1062,9 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
|
|||
wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"
|
||||
"%d\n", __func__, err);
|
||||
|
||||
if (wl->pub->srom_ccode[0] && brcms_set_hint(wl, wl->pub->srom_ccode))
|
||||
wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n",
|
||||
__func__, err);
|
||||
if (wl->pub->srom_ccode[0] &&
|
||||
regulatory_hint(wl->wiphy, wl->pub->srom_ccode))
|
||||
wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__);
|
||||
|
||||
n_adapters_found++;
|
||||
return wl;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <linux/pci_ids.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <brcm_hw_ids.h>
|
||||
#include <aiutils.h>
|
||||
|
@ -3139,20 +3140,6 @@ void brcms_c_reset(struct brcms_c_info *wlc)
|
|||
brcms_b_reset(wlc->hw);
|
||||
}
|
||||
|
||||
/* Return the channel the driver should initialize during brcms_c_init.
|
||||
* the channel may have to be changed from the currently configured channel
|
||||
* if other configurations are in conflict (bandlocked, 11n mode disabled,
|
||||
* invalid channel for current country, etc.)
|
||||
*/
|
||||
static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc)
|
||||
{
|
||||
u16 chanspec =
|
||||
1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
|
||||
WL_CHANSPEC_BAND_2G;
|
||||
|
||||
return chanspec;
|
||||
}
|
||||
|
||||
void brcms_c_init_scb(struct scb *scb)
|
||||
{
|
||||
int i;
|
||||
|
@ -5129,6 +5116,8 @@ static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
|
|||
/* make interface operational */
|
||||
int brcms_c_up(struct brcms_c_info *wlc)
|
||||
{
|
||||
struct ieee80211_channel *ch;
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
|
||||
|
||||
/* HW is turned off so don't try to access it */
|
||||
|
@ -5195,8 +5184,9 @@ int brcms_c_up(struct brcms_c_info *wlc)
|
|||
wlc->pub->up = true;
|
||||
|
||||
if (wlc->bandinit_pending) {
|
||||
ch = wlc->pub->ieee_hw->conf.channel;
|
||||
brcms_c_suspend_mac_and_wait(wlc);
|
||||
brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec);
|
||||
brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value));
|
||||
wlc->bandinit_pending = false;
|
||||
brcms_c_enable_mac(wlc);
|
||||
}
|
||||
|
@ -5397,11 +5387,6 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
|
|||
else
|
||||
return -EINVAL;
|
||||
|
||||
/* Legacy or bust when no OFDM is supported by regulatory */
|
||||
if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
|
||||
BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B))
|
||||
return -EINVAL;
|
||||
|
||||
/* update configuration value */
|
||||
if (config)
|
||||
brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
|
||||
|
@ -8201,19 +8186,12 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
|
|||
void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
|
||||
{
|
||||
struct bcma_device *core = wlc->hw->d11core;
|
||||
struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel;
|
||||
u16 chanspec;
|
||||
|
||||
BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
|
||||
|
||||
/*
|
||||
* This will happen if a big-hammer was executed. In
|
||||
* that case, we want to go back to the channel that
|
||||
* we were on and not new channel
|
||||
*/
|
||||
if (wlc->pub->associated)
|
||||
chanspec = wlc->home_chanspec;
|
||||
else
|
||||
chanspec = brcms_c_init_chanspec(wlc);
|
||||
chanspec = ch20mhz_chspec(ch->hw_value);
|
||||
|
||||
brcms_b_init(wlc->hw, chanspec);
|
||||
|
||||
|
|
|
@ -37,5 +37,6 @@
|
|||
#define BCM4329_CHIP_ID 0x4329
|
||||
#define BCM4330_CHIP_ID 0x4330
|
||||
#define BCM4331_CHIP_ID 0x4331
|
||||
#define BCM4334_CHIP_ID 0x4334
|
||||
|
||||
#endif /* _BRCM_HW_IDS_H_ */
|
||||
|
|
|
@ -1903,14 +1903,6 @@ static void ipw2100_down(struct ipw2100_priv *priv)
|
|||
netif_stop_queue(priv->net_dev);
|
||||
}
|
||||
|
||||
/* Called by register_netdev() */
|
||||
static int ipw2100_net_init(struct net_device *dev)
|
||||
{
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
||||
return ipw2100_up(priv, 1);
|
||||
}
|
||||
|
||||
static int ipw2100_wdev_init(struct net_device *dev)
|
||||
{
|
||||
struct ipw2100_priv *priv = libipw_priv(dev);
|
||||
|
@ -6087,7 +6079,6 @@ static const struct net_device_ops ipw2100_netdev_ops = {
|
|||
.ndo_stop = ipw2100_close,
|
||||
.ndo_start_xmit = libipw_xmit,
|
||||
.ndo_change_mtu = libipw_change_mtu,
|
||||
.ndo_init = ipw2100_net_init,
|
||||
.ndo_tx_timeout = ipw2100_tx_timeout,
|
||||
.ndo_set_mac_address = ipw2100_set_address,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
|
@ -6329,6 +6320,10 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
|
|||
printk(KERN_INFO DRV_NAME
|
||||
": Detected Intel PRO/Wireless 2100 Network Connection\n");
|
||||
|
||||
err = ipw2100_up(priv, 1);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = ipw2100_wdev_init(dev);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
@ -6338,12 +6333,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
|
|||
* network device we would call ipw2100_up. This introduced a race
|
||||
* condition with newer hotplug configurations (network was coming
|
||||
* up and making calls before the device was initialized).
|
||||
*
|
||||
* If we called ipw2100_up before we registered the device, then the
|
||||
* device name wasn't registered. So, we instead use the net_dev->init
|
||||
* member to call a function that then just turns and calls ipw2100_up.
|
||||
* net_dev->init is called after name allocation but before the
|
||||
* notifier chain is called */
|
||||
*/
|
||||
err = register_netdev(dev);
|
||||
if (err) {
|
||||
printk(KERN_WARNING DRV_NAME
|
||||
|
|
|
@ -1,31 +1,19 @@
|
|||
# DVM
|
||||
obj-$(CONFIG_IWLDVM) += iwldvm.o
|
||||
iwldvm-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o
|
||||
iwldvm-objs += iwl-ucode.o iwl-agn-tx.o
|
||||
iwldvm-objs += iwl-agn-lib.o iwl-agn-calib.o
|
||||
iwldvm-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o
|
||||
iwldvm-objs += iwl-eeprom.o iwl-power.o
|
||||
iwldvm-objs += iwl-scan.o iwl-led.o
|
||||
iwldvm-objs += iwl-agn-rxon.o iwl-agn-devices.o
|
||||
|
||||
iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
|
||||
iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o
|
||||
|
||||
CFLAGS_iwl-devtrace.o := -I$(src)
|
||||
|
||||
# WIFI
|
||||
# common
|
||||
obj-$(CONFIG_IWLWIFI) += iwlwifi.o
|
||||
iwlwifi-objs += iwl-5000.o
|
||||
iwlwifi-objs += iwl-6000.o
|
||||
iwlwifi-objs += iwl-1000.o
|
||||
iwlwifi-objs += iwl-2000.o
|
||||
iwlwifi-objs += iwl-io.o
|
||||
iwlwifi-objs += iwl-pci.o
|
||||
iwlwifi-objs += iwl-drv.o
|
||||
iwlwifi-objs += iwl-debug.o
|
||||
iwlwifi-objs += iwl-notif-wait.o
|
||||
iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
|
||||
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
|
||||
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
|
||||
iwlwifi-objs += pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o
|
||||
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)
|
||||
|
||||
|
||||
obj-$(CONFIG_IWLDVM) += dvm/
|
||||
|
||||
CFLAGS_iwl-devtrace.o := -I$(src)
|
||||
|
|
13
drivers/net/wireless/iwlwifi/dvm/Makefile
Normal file
13
drivers/net/wireless/iwlwifi/dvm/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
# DVM
|
||||
obj-$(CONFIG_IWLDVM) += iwldvm.o
|
||||
iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o
|
||||
iwldvm-objs += lib.o calib.o tt.o sta.o rx.o
|
||||
|
||||
iwldvm-objs += power.o
|
||||
iwldvm-objs += scan.o led.o
|
||||
iwldvm-objs += rxon.o devices.o
|
||||
|
||||
iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
|
||||
iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += testmode.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
|
|
@ -63,9 +63,10 @@
|
|||
#ifndef __iwl_agn_h__
|
||||
#define __iwl_agn_h__
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-config.h"
|
||||
|
||||
#include "dev.h"
|
||||
|
||||
/* The first 11 queues (0-10) are used otherwise */
|
||||
#define IWLAGN_FIRST_AMPDU_QUEUE 11
|
||||
|
||||
|
@ -91,7 +92,6 @@ extern struct iwl_lib_ops iwl6030_lib;
|
|||
#define STATUS_CT_KILL 1
|
||||
#define STATUS_ALIVE 2
|
||||
#define STATUS_READY 3
|
||||
#define STATUS_GEO_CONFIGURED 4
|
||||
#define STATUS_EXIT_PENDING 5
|
||||
#define STATUS_STATISTICS 6
|
||||
#define STATUS_SCANNING 7
|
||||
|
@ -101,6 +101,7 @@ extern struct iwl_lib_ops iwl6030_lib;
|
|||
#define STATUS_CHANNEL_SWITCH_PENDING 11
|
||||
#define STATUS_SCAN_COMPLETE 12
|
||||
#define STATUS_POWER_PMI 13
|
||||
#define STATUS_SCAN_ROC_EXPIRED 14
|
||||
|
||||
struct iwl_ucode_capabilities;
|
||||
|
||||
|
@ -255,6 +256,10 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
|
|||
enum iwl_scan_type scan_type,
|
||||
enum ieee80211_band band);
|
||||
|
||||
void iwl_scan_roc_expired(struct iwl_priv *priv);
|
||||
void iwl_scan_offchannel_skb(struct iwl_priv *priv);
|
||||
void iwl_scan_offchannel_skb_status(struct iwl_priv *priv);
|
||||
|
||||
/* For faster active scanning, scan will move to the next channel if fewer than
|
||||
* PLCP_QUIET_THRESH packets are heard on this channel within
|
||||
* ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell
|
||||
|
@ -264,7 +269,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
|
|||
#define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */
|
||||
#define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */
|
||||
|
||||
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
|
||||
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 15)
|
||||
|
||||
|
||||
/* bt coex */
|
||||
|
@ -390,8 +395,10 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
|
|||
}
|
||||
|
||||
extern int iwl_alive_start(struct iwl_priv *priv);
|
||||
/* svtool */
|
||||
|
||||
/* testmode support */
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
||||
|
||||
extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data,
|
||||
int len);
|
||||
extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw,
|
||||
|
@ -399,13 +406,16 @@ extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw,
|
|||
struct netlink_callback *cb,
|
||||
void *data, int len);
|
||||
extern void iwl_testmode_init(struct iwl_priv *priv);
|
||||
extern void iwl_testmode_cleanup(struct iwl_priv *priv);
|
||||
extern void iwl_testmode_free(struct iwl_priv *priv);
|
||||
|
||||
#else
|
||||
|
||||
static inline
|
||||
int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline
|
||||
int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct netlink_callback *cb,
|
||||
|
@ -413,12 +423,12 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
static inline
|
||||
void iwl_testmode_init(struct iwl_priv *priv)
|
||||
|
||||
static inline void iwl_testmode_init(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void iwl_testmode_cleanup(struct iwl_priv *priv)
|
||||
|
||||
static inline void iwl_testmode_free(struct iwl_priv *priv)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
@ -437,10 +447,8 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
|||
|
||||
static inline int iwl_is_ready(struct iwl_priv *priv)
|
||||
{
|
||||
/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
|
||||
* set but EXIT_PENDING is not */
|
||||
/* The adapter is 'ready' if READY EXIT_PENDING is not set */
|
||||
return test_bit(STATUS_READY, &priv->status) &&
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
|
||||
!test_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
}
|
||||
|
||||
|
@ -518,85 +526,4 @@ static inline const char *iwl_dvm_get_cmd_string(u8 cmd)
|
|||
return s;
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
/* API method exported for mvm hybrid state */
|
||||
void iwl_setup_deferred_work(struct iwl_priv *priv);
|
||||
int iwl_send_wimax_coex(struct iwl_priv *priv);
|
||||
int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
|
||||
void iwl_option_config(struct iwl_priv *priv);
|
||||
void iwl_set_hw_params(struct iwl_priv *priv);
|
||||
void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags);
|
||||
int iwl_init_drv(struct iwl_priv *priv);
|
||||
void iwl_uninit_drv(struct iwl_priv *priv);
|
||||
void iwl_send_bt_config(struct iwl_priv *priv);
|
||||
void iwl_rf_kill_ct_config(struct iwl_priv *priv);
|
||||
int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwl_teardown_interface(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
bool mode_change);
|
||||
int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwlagn_check_needed_chains(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_bss_conf *bss_conf);
|
||||
void iwlagn_chain_noise_reset(struct iwl_priv *priv);
|
||||
int iwlagn_update_beacon(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_tt_handler(struct iwl_priv *priv);
|
||||
void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode);
|
||||
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue);
|
||||
void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state);
|
||||
void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb);
|
||||
void iwl_nic_error(struct iwl_op_mode *op_mode);
|
||||
void iwl_cmd_queue_full(struct iwl_op_mode *op_mode);
|
||||
void iwl_nic_config(struct iwl_op_mode *op_mode);
|
||||
int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, bool set);
|
||||
void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
||||
enum ieee80211_rssi_event rssi_event);
|
||||
int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw);
|
||||
int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw);
|
||||
void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop);
|
||||
void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue);
|
||||
void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
enum ieee80211_sta_state old_state,
|
||||
enum ieee80211_sta_state new_state);
|
||||
int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
|
||||
u8 buf_size);
|
||||
int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req);
|
||||
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta);
|
||||
void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
u64 multicast);
|
||||
int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_gtk_rekey_data *data);
|
||||
void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 iv32, u16 *phase1key);
|
||||
int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
void iwlagn_mac_stop(struct ieee80211_hw *hw);
|
||||
void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
|
||||
#endif /* __iwl_agn_h__ */
|
|
@ -63,10 +63,11 @@
|
|||
#include <linux/slab.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-agn.h"
|
||||
|
||||
#include "dev.h"
|
||||
#include "calib.h"
|
||||
#include "agn.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* INIT calibrations framework
|
||||
|
@ -832,14 +833,14 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
|||
* To be safe, simply mask out any chains that we know
|
||||
* are not on the device.
|
||||
*/
|
||||
active_chains &= priv->hw_params.valid_rx_ant;
|
||||
active_chains &= priv->eeprom_data->valid_rx_ant;
|
||||
|
||||
num_tx_chains = 0;
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
/* loops on all the bits of
|
||||
* priv->hw_setting.valid_tx_ant */
|
||||
u8 ant_msk = (1 << i);
|
||||
if (!(priv->hw_params.valid_tx_ant & ant_msk))
|
||||
if (!(priv->eeprom_data->valid_tx_ant & ant_msk))
|
||||
continue;
|
||||
|
||||
num_tx_chains++;
|
||||
|
@ -853,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
|||
* connect the first valid tx chain
|
||||
*/
|
||||
first_chain =
|
||||
find_first_chain(priv->hw_params.valid_tx_ant);
|
||||
find_first_chain(priv->eeprom_data->valid_tx_ant);
|
||||
data->disconn_array[first_chain] = 0;
|
||||
active_chains |= BIT(first_chain);
|
||||
IWL_DEBUG_CALIB(priv,
|
||||
|
@ -863,13 +864,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
|||
}
|
||||
}
|
||||
|
||||
if (active_chains != priv->hw_params.valid_rx_ant &&
|
||||
if (active_chains != priv->eeprom_data->valid_rx_ant &&
|
||||
active_chains != priv->chain_noise_data.active_chains)
|
||||
IWL_DEBUG_CALIB(priv,
|
||||
"Detected that not all antennas are connected! "
|
||||
"Connected: %#x, valid: %#x.\n",
|
||||
active_chains,
|
||||
priv->hw_params.valid_rx_ant);
|
||||
priv->eeprom_data->valid_rx_ant);
|
||||
|
||||
/* Save for use within RXON, TX, SCAN commands, etc. */
|
||||
data->active_chains = active_chains;
|
||||
|
@ -1054,7 +1055,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
|||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
/* Disable disconnected antenna algorithm for advanced
|
||||
bt coex, assuming valid antennas are connected */
|
||||
data->active_chains = priv->hw_params.valid_rx_ant;
|
||||
data->active_chains = priv->eeprom_data->valid_rx_ant;
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++)
|
||||
if (!(data->active_chains & (1<<i)))
|
||||
data->disconn_array[i] = 1;
|
||||
|
@ -1083,8 +1084,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
|||
IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
|
||||
min_average_noise, min_average_noise_antenna_i);
|
||||
|
||||
iwlagn_gain_computation(priv, average_noise,
|
||||
find_first_chain(priv->hw_params.valid_rx_ant));
|
||||
iwlagn_gain_computation(
|
||||
priv, average_noise,
|
||||
find_first_chain(priv->eeprom_data->valid_rx_ant));
|
||||
|
||||
/* Some power changes may have been made during the calibration.
|
||||
* Update and commit the RXON
|
|
@ -62,8 +62,8 @@
|
|||
#ifndef __iwl_calib_h__
|
||||
#define __iwl_calib_h__
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-commands.h"
|
||||
#include "dev.h"
|
||||
#include "commands.h"
|
||||
|
||||
void iwl_chain_noise_calibration(struct iwl_priv *priv);
|
||||
void iwl_sensitivity_calibration(struct iwl_priv *priv);
|
|
@ -61,9 +61,9 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Please use this file (iwl-commands.h) only for uCode API definitions.
|
||||
* Please use this file (commands.h) only for uCode API definitions.
|
||||
* Please use iwl-xxxx-hw.h for hardware-related definitions.
|
||||
* Please use iwl-dev.h for driver implementation definitions.
|
||||
* Please use dev.h for driver implementation definitions.
|
||||
*/
|
||||
|
||||
#ifndef __iwl_commands_h__
|
|
@ -30,16 +30,12 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
|
||||
/* create and remove of files */
|
||||
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
|
||||
|
@ -307,13 +303,13 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
|
|||
const u8 *ptr;
|
||||
char *buf;
|
||||
u16 eeprom_ver;
|
||||
size_t eeprom_len = priv->cfg->base_params->eeprom_size;
|
||||
size_t eeprom_len = priv->eeprom_blob_size;
|
||||
buf_size = 4 * eeprom_len + 256;
|
||||
|
||||
if (eeprom_len % 16)
|
||||
return -ENODATA;
|
||||
|
||||
ptr = priv->eeprom;
|
||||
ptr = priv->eeprom_blob;
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -322,11 +318,9 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
|
|||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, "
|
||||
"version: 0x%x\n",
|
||||
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
|
||||
? "OTP" : "EEPROM", eeprom_ver);
|
||||
eeprom_ver = priv->eeprom_data->eeprom_version;
|
||||
pos += scnprintf(buf + pos, buf_size - pos,
|
||||
"NVM version: 0x%x\n", eeprom_ver);
|
||||
for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
|
||||
pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
|
||||
hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
|
||||
|
@ -351,9 +345,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
|
|||
char *buf;
|
||||
ssize_t ret;
|
||||
|
||||
if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
@ -426,8 +417,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
|
|||
test_bit(STATUS_ALIVE, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
|
||||
test_bit(STATUS_READY, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
|
||||
|
@ -1341,17 +1330,17 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
|
|||
if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"tx power: (1/2 dB step)\n");
|
||||
if ((priv->hw_params.valid_tx_ant & ANT_A) &&
|
||||
if ((priv->eeprom_data->valid_tx_ant & ANT_A) &&
|
||||
tx->tx_power.ant_a)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
fmt_hex, "antenna A:",
|
||||
tx->tx_power.ant_a);
|
||||
if ((priv->hw_params.valid_tx_ant & ANT_B) &&
|
||||
if ((priv->eeprom_data->valid_tx_ant & ANT_B) &&
|
||||
tx->tx_power.ant_b)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
fmt_hex, "antenna B:",
|
||||
tx->tx_power.ant_b);
|
||||
if ((priv->hw_params.valid_tx_ant & ANT_C) &&
|
||||
if ((priv->eeprom_data->valid_tx_ant & ANT_C) &&
|
||||
tx->tx_power.ant_c)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
fmt_hex, "antenna C:",
|
|
@ -24,8 +24,8 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Please use this file (iwl-dev.h) for driver implementation definitions.
|
||||
* Please use iwl-commands.h for uCode API definitions.
|
||||
* Please use this file (dev.h) for driver implementation definitions.
|
||||
* Please use commands.h for uCode API definitions.
|
||||
*/
|
||||
|
||||
#ifndef __iwl_dev_h__
|
||||
|
@ -39,17 +39,20 @@
|
|||
#include <linux/mutex.h>
|
||||
|
||||
#include "iwl-fw.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-led.h"
|
||||
#include "iwl-power.h"
|
||||
#include "iwl-agn-rs.h"
|
||||
#include "iwl-agn-tt.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-notif-wait.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
#include "led.h"
|
||||
#include "power.h"
|
||||
#include "rs.h"
|
||||
#include "tt.h"
|
||||
|
||||
#include "iwl-test.h"
|
||||
|
||||
/* CT-KILL constants */
|
||||
#define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */
|
||||
|
@ -87,33 +90,6 @@
|
|||
|
||||
#define IWL_NUM_SCAN_RATES (2)
|
||||
|
||||
/*
|
||||
* One for each channel, holds all channel setup data
|
||||
* Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
|
||||
* with one another!
|
||||
*/
|
||||
struct iwl_channel_info {
|
||||
struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */
|
||||
struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for
|
||||
* HT40 channel */
|
||||
|
||||
u8 channel; /* channel number */
|
||||
u8 flags; /* flags copied from EEPROM */
|
||||
s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
|
||||
s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) limit */
|
||||
s8 min_power; /* always 0 */
|
||||
s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */
|
||||
|
||||
u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
|
||||
u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
|
||||
enum ieee80211_band band;
|
||||
|
||||
/* HT40 channel info */
|
||||
s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
|
||||
u8 ht40_flags; /* flags copied from EEPROM */
|
||||
u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
|
||||
};
|
||||
|
||||
/*
|
||||
* Minimum number of queues. MAX_NUM is defined in hw specific files.
|
||||
* Set the minimum to accommodate
|
||||
|
@ -153,29 +129,6 @@ union iwl_ht_rate_supp {
|
|||
};
|
||||
};
|
||||
|
||||
#define CFG_HT_RX_AMPDU_FACTOR_8K (0x0)
|
||||
#define CFG_HT_RX_AMPDU_FACTOR_16K (0x1)
|
||||
#define CFG_HT_RX_AMPDU_FACTOR_32K (0x2)
|
||||
#define CFG_HT_RX_AMPDU_FACTOR_64K (0x3)
|
||||
#define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K
|
||||
#define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K
|
||||
#define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K
|
||||
|
||||
/*
|
||||
* Maximal MPDU density for TX aggregation
|
||||
* 4 - 2us density
|
||||
* 5 - 4us density
|
||||
* 6 - 8us density
|
||||
* 7 - 16us density
|
||||
*/
|
||||
#define CFG_HT_MPDU_DENSITY_2USEC (0x4)
|
||||
#define CFG_HT_MPDU_DENSITY_4USEC (0x5)
|
||||
#define CFG_HT_MPDU_DENSITY_8USEC (0x6)
|
||||
#define CFG_HT_MPDU_DENSITY_16USEC (0x7)
|
||||
#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
|
||||
#define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC
|
||||
#define CFG_HT_MPDU_DENSITY_MIN (0x1)
|
||||
|
||||
struct iwl_ht_config {
|
||||
bool single_chain_sufficient;
|
||||
enum ieee80211_smps_mode smps; /* current smps mode */
|
||||
|
@ -445,23 +398,6 @@ enum {
|
|||
MEASUREMENT_ACTIVE = (1 << 1),
|
||||
};
|
||||
|
||||
enum iwl_nvm_type {
|
||||
NVM_DEVICE_TYPE_EEPROM = 0,
|
||||
NVM_DEVICE_TYPE_OTP,
|
||||
};
|
||||
|
||||
/*
|
||||
* Two types of OTP memory access modes
|
||||
* IWL_OTP_ACCESS_ABSOLUTE - absolute address mode,
|
||||
* based on physical memory addressing
|
||||
* IWL_OTP_ACCESS_RELATIVE - relative address mode,
|
||||
* based on logical memory addressing
|
||||
*/
|
||||
enum iwl_access_mode {
|
||||
IWL_OTP_ACCESS_ABSOLUTE,
|
||||
IWL_OTP_ACCESS_RELATIVE,
|
||||
};
|
||||
|
||||
/* reply_tx_statistics (for _agn devices) */
|
||||
struct reply_tx_error_statistics {
|
||||
u32 pp_delay;
|
||||
|
@ -632,10 +568,6 @@ enum iwl_scan_type {
|
|||
*
|
||||
* @tx_chains_num: Number of TX chains
|
||||
* @rx_chains_num: Number of RX chains
|
||||
* @valid_tx_ant: usable antennas for TX
|
||||
* @valid_rx_ant: usable antennas for RX
|
||||
* @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX)
|
||||
* @sku: sku read from EEPROM
|
||||
* @ct_kill_threshold: temperature threshold - in hw dependent unit
|
||||
* @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
|
||||
* relevant for 1000, 6000 and up
|
||||
|
@ -645,11 +577,7 @@ enum iwl_scan_type {
|
|||
struct iwl_hw_params {
|
||||
u8 tx_chains_num;
|
||||
u8 rx_chains_num;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u8 ht40_channel;
|
||||
bool use_rts_for_aggregation;
|
||||
u16 sku;
|
||||
u32 ct_kill_threshold;
|
||||
u32 ct_kill_exit_threshold;
|
||||
|
||||
|
@ -664,31 +592,10 @@ struct iwl_lib_ops {
|
|||
/* device specific configuration */
|
||||
void (*nic_config)(struct iwl_priv *priv);
|
||||
|
||||
/* eeprom operations (as defined in iwl-eeprom.h) */
|
||||
struct iwl_eeprom_ops eeprom_ops;
|
||||
|
||||
/* temperature */
|
||||
void (*temperature)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
||||
struct iwl_testmode_trace {
|
||||
u32 buff_size;
|
||||
u32 total_size;
|
||||
u32 num_chunks;
|
||||
u8 *cpu_addr;
|
||||
u8 *trace_addr;
|
||||
dma_addr_t dma_addr;
|
||||
bool trace_enabled;
|
||||
};
|
||||
struct iwl_testmode_mem {
|
||||
u32 buff_size;
|
||||
u32 num_chunks;
|
||||
u8 *buff_addr;
|
||||
bool read_in_progress;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct iwl_wipan_noa_data {
|
||||
struct rcu_head rcu_head;
|
||||
u32 length;
|
||||
|
@ -735,8 +642,6 @@ struct iwl_priv {
|
|||
|
||||
/* ieee device used by generic ieee processing code */
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_channel *ieee_channels;
|
||||
struct ieee80211_rate *ieee_rates;
|
||||
|
||||
struct list_head calib_results;
|
||||
|
||||
|
@ -747,16 +652,12 @@ struct iwl_priv {
|
|||
enum ieee80211_band band;
|
||||
u8 valid_contexts;
|
||||
|
||||
void (*pre_rx_handler)(struct iwl_priv *priv,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
struct iwl_notif_wait_data notif_wait;
|
||||
|
||||
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
|
||||
|
||||
/* spectrum measurement report caching */
|
||||
struct iwl_spectrum_notification measure_report;
|
||||
u8 measurement_status;
|
||||
|
@ -787,11 +688,6 @@ struct iwl_priv {
|
|||
bool ucode_loaded;
|
||||
bool init_ucode_run; /* Don't run init uCode again */
|
||||
|
||||
/* we allocate array of iwl_channel_info for NIC's valid channels.
|
||||
* Access via channel # using indirect index array */
|
||||
struct iwl_channel_info *channel_info; /* channel info array */
|
||||
u8 channel_count; /* # of channels */
|
||||
|
||||
u8 plcp_delta_threshold;
|
||||
|
||||
/* thermal calibration */
|
||||
|
@ -846,6 +742,7 @@ struct iwl_priv {
|
|||
struct iwl_station_entry stations[IWLAGN_STATION_COUNT];
|
||||
unsigned long ucode_key_table;
|
||||
struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
|
||||
atomic_t num_aux_in_flight;
|
||||
|
||||
u8 mac80211_registered;
|
||||
|
||||
|
@ -950,10 +847,8 @@ struct iwl_priv {
|
|||
|
||||
struct delayed_work scan_check;
|
||||
|
||||
/* TX Power */
|
||||
/* TX Power settings */
|
||||
s8 tx_power_user_lmt;
|
||||
s8 tx_power_device_lmt;
|
||||
s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
|
||||
s8 tx_power_next;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
@ -964,9 +859,10 @@ struct iwl_priv {
|
|||
void *wowlan_sram;
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
|
||||
/* eeprom -- this is in the card's little endian byte order */
|
||||
u8 *eeprom;
|
||||
enum iwl_nvm_type nvm_device_type;
|
||||
struct iwl_eeprom_data *eeprom_data;
|
||||
/* eeprom blob for debugfs/testmode */
|
||||
u8 *eeprom_blob;
|
||||
size_t eeprom_blob_size;
|
||||
|
||||
struct work_struct txpower_work;
|
||||
u32 calib_disabled;
|
||||
|
@ -979,9 +875,9 @@ struct iwl_priv {
|
|||
struct led_classdev led;
|
||||
unsigned long blink_on, blink_off;
|
||||
bool led_registered;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
||||
struct iwl_testmode_trace testmode_trace;
|
||||
struct iwl_testmode_mem testmode_mem;
|
||||
struct iwl_test tst;
|
||||
u32 tm_fixed_rate;
|
||||
#endif
|
||||
|
||||
|
@ -1001,8 +897,6 @@ struct iwl_priv {
|
|||
enum iwl_ucode_type cur_ucode;
|
||||
}; /*iwl_priv */
|
||||
|
||||
extern struct kmem_cache *iwl_tx_cmd_pool;
|
||||
|
||||
static inline struct iwl_rxon_context *
|
||||
iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
|
||||
{
|
||||
|
@ -1036,36 +930,4 @@ static inline int iwl_is_any_associated(struct iwl_priv *priv)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
|
||||
{
|
||||
if (ch_info == NULL)
|
||||
return 0;
|
||||
return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline int is_channel_radar(const struct iwl_channel_info *ch_info)
|
||||
{
|
||||
return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info)
|
||||
{
|
||||
return ch_info->band == IEEE80211_BAND_5GHZ;
|
||||
}
|
||||
|
||||
static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info)
|
||||
{
|
||||
return ch_info->band == IEEE80211_BAND_2GHZ;
|
||||
}
|
||||
|
||||
static inline int is_channel_passive(const struct iwl_channel_info *ch)
|
||||
{
|
||||
return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline int is_channel_ibss(const struct iwl_channel_info *ch)
|
||||
{
|
||||
return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
|
||||
}
|
||||
|
||||
#endif /* __iwl_dev_h__ */
|
|
@ -27,11 +27,14 @@
|
|||
/*
|
||||
* DVM device-specific data & functions
|
||||
*/
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
|
||||
#include "agn.h"
|
||||
#include "dev.h"
|
||||
#include "commands.h"
|
||||
|
||||
|
||||
/*
|
||||
* 1000 series
|
||||
|
@ -58,11 +61,6 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
|
|||
/* NIC configuration for 1000 series */
|
||||
static void iwl1000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
/* set CSR_HW_CONFIG_REG for uCode use */
|
||||
iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
|
||||
|
||||
/* Setting digital SVR for 1000 card to 1.32V */
|
||||
/* locking is acquired in iwl_set_bits_mask_prph() function */
|
||||
iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG,
|
||||
|
@ -170,16 +168,6 @@ static const struct iwl_sensitivity_ranges iwl1000_sensitivity = {
|
|||
|
||||
static void iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ);
|
||||
|
||||
priv->hw_params.tx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_tx_ant);
|
||||
if (priv->cfg->rx_with_siso_diversity)
|
||||
priv->hw_params.rx_chains_num = 1;
|
||||
else
|
||||
priv->hw_params.rx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_rx_ant);
|
||||
|
||||
iwl1000_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
|
@ -189,17 +177,6 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
struct iwl_lib_ops iwl1000_lib = {
|
||||
.set_hw_params = iwl1000_hw_set_hw_params,
|
||||
.nic_config = iwl1000_nic_config,
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
EEPROM_REG_BAND_2_CHANNELS,
|
||||
EEPROM_REG_BAND_3_CHANNELS,
|
||||
EEPROM_REG_BAND_4_CHANNELS,
|
||||
EEPROM_REG_BAND_5_CHANNELS,
|
||||
EEPROM_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REGULATORY_BAND_NO_HT40,
|
||||
},
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
|
@ -219,8 +196,6 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
|
|||
/* NIC configuration for 2000 series */
|
||||
static void iwl2000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_rf_config(priv);
|
||||
|
||||
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
|
||||
}
|
||||
|
@ -251,16 +226,6 @@ static const struct iwl_sensitivity_ranges iwl2000_sensitivity = {
|
|||
|
||||
static void iwl2000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ);
|
||||
|
||||
priv->hw_params.tx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_tx_ant);
|
||||
if (priv->cfg->rx_with_siso_diversity)
|
||||
priv->hw_params.rx_chains_num = 1;
|
||||
else
|
||||
priv->hw_params.rx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_rx_ant);
|
||||
|
||||
iwl2000_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
|
@ -270,36 +235,12 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
struct iwl_lib_ops iwl2000_lib = {
|
||||
.set_hw_params = iwl2000_hw_set_hw_params,
|
||||
.nic_config = iwl2000_nic_config,
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
EEPROM_REG_BAND_2_CHANNELS,
|
||||
EEPROM_REG_BAND_3_CHANNELS,
|
||||
EEPROM_REG_BAND_4_CHANNELS,
|
||||
EEPROM_REG_BAND_5_CHANNELS,
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REGULATORY_BAND_NO_HT40,
|
||||
},
|
||||
.enhanced_txpower = true,
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
struct iwl_lib_ops iwl2030_lib = {
|
||||
.set_hw_params = iwl2000_hw_set_hw_params,
|
||||
.nic_config = iwl2000_nic_config,
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
EEPROM_REG_BAND_2_CHANNELS,
|
||||
EEPROM_REG_BAND_3_CHANNELS,
|
||||
EEPROM_REG_BAND_4_CHANNELS,
|
||||
EEPROM_REG_BAND_5_CHANNELS,
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REGULATORY_BAND_NO_HT40,
|
||||
},
|
||||
.enhanced_txpower = true,
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
|
@ -309,19 +250,6 @@ struct iwl_lib_ops iwl2030_lib = {
|
|||
*/
|
||||
|
||||
/* NIC configuration for 5000 series */
|
||||
static void iwl5000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_rf_config(priv);
|
||||
|
||||
/* W/A : NIC is stuck in a reset state after Early PCIe power off
|
||||
* (PCIe power is lost before PERST# is asserted),
|
||||
* causing ME FW to lose ownership and not being able to obtain it back.
|
||||
*/
|
||||
iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
||||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
}
|
||||
|
||||
static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
|
||||
.min_nrg_cck = 100,
|
||||
.auto_corr_min_ofdm = 90,
|
||||
|
@ -376,11 +304,9 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
|
|||
static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
|
||||
{
|
||||
u16 temperature, voltage;
|
||||
__le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv,
|
||||
EEPROM_KELVIN_TEMPERATURE);
|
||||
|
||||
temperature = le16_to_cpu(temp_calib[0]);
|
||||
voltage = le16_to_cpu(temp_calib[1]);
|
||||
temperature = le16_to_cpu(priv->eeprom_data->kelvin_temperature);
|
||||
voltage = le16_to_cpu(priv->eeprom_data->kelvin_voltage);
|
||||
|
||||
/* offset = temp - volt / coeff */
|
||||
return (s32)(temperature -
|
||||
|
@ -404,14 +330,6 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
|
|||
|
||||
static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
|
||||
priv->hw_params.tx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_tx_ant);
|
||||
priv->hw_params.rx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_rx_ant);
|
||||
|
||||
iwl5000_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
|
@ -420,14 +338,6 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
|
||||
static void iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
|
||||
priv->hw_params.tx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_tx_ant);
|
||||
priv->hw_params.rx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_rx_ant);
|
||||
|
||||
iwl5150_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
|
@ -455,7 +365,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
|||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl5000_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
|
@ -505,14 +414,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
|||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd.switch_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, ch);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
ctx->active.channel, ch);
|
||||
return -EFAULT;
|
||||
}
|
||||
cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
|
||||
|
||||
return iwl_dvm_send_cmd(priv, &hcmd);
|
||||
}
|
||||
|
@ -520,36 +422,12 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
|||
struct iwl_lib_ops iwl5000_lib = {
|
||||
.set_hw_params = iwl5000_hw_set_hw_params,
|
||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||
.nic_config = iwl5000_nic_config,
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
EEPROM_REG_BAND_2_CHANNELS,
|
||||
EEPROM_REG_BAND_3_CHANNELS,
|
||||
EEPROM_REG_BAND_4_CHANNELS,
|
||||
EEPROM_REG_BAND_5_CHANNELS,
|
||||
EEPROM_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
struct iwl_lib_ops iwl5150_lib = {
|
||||
.set_hw_params = iwl5150_hw_set_hw_params,
|
||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||
.nic_config = iwl5000_nic_config,
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
EEPROM_REG_BAND_2_CHANNELS,
|
||||
EEPROM_REG_BAND_3_CHANNELS,
|
||||
EEPROM_REG_BAND_4_CHANNELS,
|
||||
EEPROM_REG_BAND_5_CHANNELS,
|
||||
EEPROM_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
},
|
||||
.temperature = iwl5150_temperature,
|
||||
};
|
||||
|
||||
|
@ -570,8 +448,6 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
|||
/* NIC configuration for 6000 series */
|
||||
static void iwl6000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_rf_config(priv);
|
||||
|
||||
switch (priv->cfg->device_family) {
|
||||
case IWL_DEVICE_FAMILY_6005:
|
||||
case IWL_DEVICE_FAMILY_6030:
|
||||
|
@ -584,13 +460,13 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
|
|||
break;
|
||||
case IWL_DEVICE_FAMILY_6050:
|
||||
/* Indicate calibration version to uCode. */
|
||||
if (iwl_eeprom_calib_version(priv) >= 6)
|
||||
if (priv->eeprom_data->calib_version >= 6)
|
||||
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
|
||||
break;
|
||||
case IWL_DEVICE_FAMILY_6150:
|
||||
/* Indicate calibration version to uCode. */
|
||||
if (iwl_eeprom_calib_version(priv) >= 6)
|
||||
if (priv->eeprom_data->calib_version >= 6)
|
||||
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
|
||||
iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
|
||||
|
@ -627,17 +503,6 @@ static const struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
|||
|
||||
static void iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
|
||||
priv->hw_params.tx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_tx_ant);
|
||||
if (priv->cfg->rx_with_siso_diversity)
|
||||
priv->hw_params.rx_chains_num = 1;
|
||||
else
|
||||
priv->hw_params.rx_chains_num =
|
||||
num_of_ant(priv->hw_params.valid_rx_ant);
|
||||
|
||||
iwl6000_set_ct_threshold(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
|
@ -654,7 +519,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
|||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl6000_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
|
@ -704,14 +568,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
|||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd.switch_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, ch);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
ctx->active.channel, ch);
|
||||
return -EFAULT;
|
||||
}
|
||||
cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
|
||||
|
||||
return iwl_dvm_send_cmd(priv, &hcmd);
|
||||
}
|
||||
|
@ -720,18 +577,6 @@ struct iwl_lib_ops iwl6000_lib = {
|
|||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.nic_config = iwl6000_nic_config,
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
EEPROM_REG_BAND_2_CHANNELS,
|
||||
EEPROM_REG_BAND_3_CHANNELS,
|
||||
EEPROM_REG_BAND_4_CHANNELS,
|
||||
EEPROM_REG_BAND_5_CHANNELS,
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.enhanced_txpower = true,
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
|
@ -739,17 +584,5 @@ struct iwl_lib_ops iwl6030_lib = {
|
|||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.nic_config = iwl6000_nic_config,
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_REG_BAND_1_CHANNELS,
|
||||
EEPROM_REG_BAND_2_CHANNELS,
|
||||
EEPROM_REG_BAND_3_CHANNELS,
|
||||
EEPROM_REG_BAND_4_CHANNELS,
|
||||
EEPROM_REG_BAND_5_CHANNELS,
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.enhanced_txpower = true,
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
|
@ -34,12 +34,11 @@
|
|||
#include <net/mac80211.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
|
||||
/* Throughput OFF time(ms) ON time (ms)
|
||||
* >300 25 25
|
|
@ -33,13 +33,14 @@
|
|||
#include <linux/sched.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-modparams.h"
|
||||
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
|
||||
int iwlagn_hw_valid_rtc_data_addr(u32 addr)
|
||||
{
|
||||
return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) &&
|
||||
|
@ -58,8 +59,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
|
|||
/* half dBm need to multiply */
|
||||
tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
|
||||
|
||||
if (priv->tx_power_lmt_in_half_dbm &&
|
||||
priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) {
|
||||
if (tx_power_cmd.global_lmt > priv->eeprom_data->max_tx_pwr_half_dbm) {
|
||||
/*
|
||||
* For the newer devices which using enhanced/extend tx power
|
||||
* table in EEPROM, the format is in half dBm. driver need to
|
||||
|
@ -71,7 +71,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
|
|||
* "tx_power_user_lmt" is higher than EEPROM value (in
|
||||
* half-dBm format), lower the tx power based on EEPROM
|
||||
*/
|
||||
tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm;
|
||||
tx_power_cmd.global_lmt =
|
||||
priv->eeprom_data->max_tx_pwr_half_dbm;
|
||||
}
|
||||
tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
|
||||
tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
|
||||
|
@ -159,7 +160,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
|
|||
IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
|
||||
IWL_PAN_SCD_MULTICAST_MSK;
|
||||
|
||||
if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
|
||||
|
@ -617,6 +618,11 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv,
|
|||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
int ave_rssi;
|
||||
|
||||
if (!ctx->vif || (ctx->vif->type != NL80211_IFTYPE_STATION)) {
|
||||
IWL_DEBUG_INFO(priv, "BSS ctx not active or not in sta mode\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ave_rssi = ieee80211_ave_rssi(ctx->vif);
|
||||
if (!ave_rssi) {
|
||||
/* no rssi data, no changes to reduce tx power */
|
||||
|
@ -818,7 +824,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|||
if (priv->chain_noise_data.active_chains)
|
||||
active_chains = priv->chain_noise_data.active_chains;
|
||||
else
|
||||
active_chains = priv->hw_params.valid_rx_ant;
|
||||
active_chains = priv->eeprom_data->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
|
@ -1259,7 +1265,7 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
|||
* the mutex, this ensures we don't try to send two
|
||||
* (or more) synchronous commands at a time.
|
||||
*/
|
||||
if (cmd->flags & CMD_SYNC)
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (priv->ucode_owner == IWL_OWNERSHIP_TM &&
|
|
@ -38,19 +38,20 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-modparams.h"
|
||||
|
||||
#include "dev.h"
|
||||
#include "calib.h"
|
||||
#include "agn.h"
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* mac80211 entry point functions
|
||||
|
@ -154,6 +155,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||
IEEE80211_HW_SCAN_WHILE_IDLE;
|
||||
|
||||
hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
|
||||
hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT;
|
||||
|
||||
/*
|
||||
* Including the following line will crash some AP's. This
|
||||
|
@ -162,7 +164,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||
hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
|
||||
*/
|
||||
|
||||
if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
||||
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
|
||||
|
||||
|
@ -237,12 +239,12 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||
|
||||
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
|
||||
|
||||
if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
|
||||
if (priv->eeprom_data->bands[IEEE80211_BAND_2GHZ].n_channels)
|
||||
priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
|
||||
&priv->bands[IEEE80211_BAND_2GHZ];
|
||||
if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
|
||||
&priv->eeprom_data->bands[IEEE80211_BAND_2GHZ];
|
||||
if (priv->eeprom_data->bands[IEEE80211_BAND_5GHZ].n_channels)
|
||||
priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
|
||||
&priv->bands[IEEE80211_BAND_5GHZ];
|
||||
&priv->eeprom_data->bands[IEEE80211_BAND_5GHZ];
|
||||
|
||||
hw->wiphy->hw_version = priv->trans->hw_id;
|
||||
|
||||
|
@ -341,7 +343,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void iwlagn_mac_stop(struct ieee80211_hw *hw)
|
||||
static void iwlagn_mac_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -369,9 +371,9 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw)
|
|||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_gtk_rekey_data *data)
|
||||
static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_gtk_rekey_data *data)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -397,7 +399,8 @@ void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
|
|||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
|
||||
struct cfg80211_wowlan *wowlan)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
@ -473,7 +476,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
|||
}
|
||||
|
||||
if (priv->wowlan_sram)
|
||||
_iwl_read_targ_mem_words(
|
||||
_iwl_read_targ_mem_dwords(
|
||||
priv->trans, 0x800000,
|
||||
priv->wowlan_sram,
|
||||
img->sec[IWL_UCODE_SECTION_DATA].len / 4);
|
||||
|
@ -508,7 +511,7 @@ static void iwlagn_mac_set_wakeup(struct ieee80211_hw *hw, bool enabled)
|
|||
}
|
||||
#endif
|
||||
|
||||
void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -519,21 +522,21 @@ void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 iv32, u16 *phase1key)
|
||||
static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 iv32, u16 *phase1key)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key);
|
||||
}
|
||||
|
||||
int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
@ -633,11 +636,11 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
|
||||
u8 buf_size)
|
||||
static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
|
||||
u8 buf_size)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
int ret = -EINVAL;
|
||||
|
@ -646,7 +649,7 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
|
||||
sta->addr, tid);
|
||||
|
||||
if (!(priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE))
|
||||
if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE))
|
||||
return -EACCES;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
@ -664,7 +667,7 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||
ret = iwl_sta_rx_agg_stop(priv, sta, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
if (!priv->trans->ops->tx_agg_setup)
|
||||
if (!priv->trans->ops->txq_enable)
|
||||
break;
|
||||
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
|
||||
break;
|
||||
|
@ -759,11 +762,11 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
enum ieee80211_sta_state old_state,
|
||||
enum ieee80211_sta_state new_state)
|
||||
static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
enum ieee80211_sta_state old_state,
|
||||
enum ieee80211_sta_state new_state)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
@ -842,11 +845,10 @@ int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
const struct iwl_channel_info *ch_info;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = ch_switch->channel;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
|
@ -883,12 +885,6 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
|||
if (le16_to_cpu(ctx->active.channel) == ch)
|
||||
goto out;
|
||||
|
||||
ch_info = iwl_get_channel_info(priv, channel->band, ch);
|
||||
if (!is_channel_valid(ch_info)) {
|
||||
IWL_DEBUG_MAC80211(priv, "invalid channel\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->current_ht_config.smps = conf->smps_mode;
|
||||
|
||||
/* Configure HT40 channels */
|
||||
|
@ -937,10 +933,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
|
|||
ieee80211_chswitch_done(ctx->vif, is_success);
|
||||
}
|
||||
|
||||
void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
u64 multicast)
|
||||
static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
u64 multicast)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
__le32 filter_or = 0, filter_nand = 0;
|
||||
|
@ -987,7 +983,7 @@ void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
|||
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
|
||||
}
|
||||
|
||||
void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -1040,8 +1036,18 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
|
|||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
/* mac80211 should not scan while ROC or ROC while scanning */
|
||||
if (WARN_ON_ONCE(priv->scan_type != IWL_SCAN_RADIO_RESET)) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
priv->hw_roc_channel = channel;
|
||||
|
@ -1114,7 +1120,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
|
|||
return err;
|
||||
}
|
||||
|
||||
int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
|
||||
static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -1131,8 +1137,8 @@ int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
||||
enum ieee80211_rssi_event rssi_event)
|
||||
static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
||||
enum ieee80211_rssi_event rssi_event)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -1156,8 +1162,8 @@ void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
|||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, bool set)
|
||||
static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta, bool set)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -1166,9 +1172,9 @@ int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
static 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 = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
@ -1210,7 +1216,7 @@ int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
|
||||
static int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
|
@ -1226,7 +1232,8 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|||
return iwlagn_commit_rxon(priv, ctx);
|
||||
}
|
||||
|
||||
int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
static int iwl_setup_interface(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
int err, ac;
|
||||
|
@ -1346,9 +1353,9 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
|
|||
return err;
|
||||
}
|
||||
|
||||
void iwl_teardown_interface(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
bool mode_change)
|
||||
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);
|
||||
|
||||
|
@ -1404,13 +1411,11 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum nl80211_iftype newtype, bool newp2p)
|
||||
struct ieee80211_vif *vif,
|
||||
enum nl80211_iftype newtype, bool newp2p)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
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;
|
||||
struct iwl_rxon_context *ctx, *tmp;
|
||||
enum nl80211_iftype newviftype = newtype;
|
||||
u32 interface_modes;
|
||||
int err;
|
||||
|
@ -1421,6 +1426,18 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
/*
|
||||
* To simplify this code, only support changes on the
|
||||
* BSS context. The PAN context is usually reassigned
|
||||
* by creating/removing P2P interfaces anyway.
|
||||
*/
|
||||
if (ctx->ctxid != IWL_RXON_CTX_BSS) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ctx->vif || !iwl_is_ready_rf(priv)) {
|
||||
/*
|
||||
* Huh? But wait ... this can maybe happen when
|
||||
|
@ -1430,32 +1447,19 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Check if the switch is supported in the same context */
|
||||
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)
|
||||
if (!tmp->is_active)
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
@ -1489,9 +1493,9 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
|
|||
return err;
|
||||
}
|
||||
|
||||
int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req)
|
||||
static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
int ret;
|
||||
|
@ -1546,10 +1550,10 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
|||
iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
|
||||
}
|
||||
|
||||
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
static 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 = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
|
@ -44,15 +44,19 @@
|
|||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-eeprom-read.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
#include "dev.h"
|
||||
#include "calib.h"
|
||||
#include "agn.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
|
@ -79,6 +83,8 @@ MODULE_VERSION(DRV_VERSION);
|
|||
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static const struct iwl_op_mode_ops iwl_dvm_ops;
|
||||
|
||||
void iwl_update_chain_flags(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
@ -179,7 +185,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
|
|||
rate = info->control.rates[0].idx;
|
||||
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
||||
priv->hw_params.valid_tx_ant);
|
||||
priv->eeprom_data->valid_tx_ant);
|
||||
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
|
||||
|
||||
/* In mac80211, rates for 5 GHz start at 0 */
|
||||
|
@ -402,7 +408,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
|
|||
|
||||
base = priv->device_pointers.log_event_table;
|
||||
if (iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
iwl_read_targ_mem_words(priv->trans, base, &read, sizeof(read));
|
||||
iwl_read_targ_mem_bytes(priv->trans, base, &read, sizeof(read));
|
||||
capacity = read.capacity;
|
||||
mode = read.mode;
|
||||
num_wraps = read.wrap_counter;
|
||||
|
@ -577,7 +583,7 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
|
|||
7, 6, 5, 4,
|
||||
};
|
||||
|
||||
void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
||||
static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -644,7 +650,7 @@ void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
|||
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
|
||||
}
|
||||
|
||||
void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
||||
static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_ct_kill_config cmd;
|
||||
struct iwl_ct_kill_throttling_config adv_cmd;
|
||||
|
@ -725,7 +731,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
|
|||
}
|
||||
}
|
||||
|
||||
void iwl_send_bt_config(struct iwl_priv *priv)
|
||||
static void iwl_send_bt_config(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_bt_cmd bt_cmd = {
|
||||
.lead_time = BT_LEAD_TIME_DEF,
|
||||
|
@ -813,7 +819,7 @@ int iwl_alive_start(struct iwl_priv *priv)
|
|||
ieee80211_wake_queues(priv->hw);
|
||||
|
||||
/* Configure Tx antenna selection based on H/W config */
|
||||
iwlagn_send_tx_ant_config(priv, priv->hw_params.valid_tx_ant);
|
||||
iwlagn_send_tx_ant_config(priv, priv->eeprom_data->valid_tx_ant);
|
||||
|
||||
if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
|
||||
struct iwl_rxon_cmd *active_rxon =
|
||||
|
@ -931,11 +937,12 @@ void iwl_down(struct iwl_priv *priv)
|
|||
priv->ucode_loaded = false;
|
||||
iwl_trans_stop_device(priv->trans);
|
||||
|
||||
/* Set num_aux_in_flight must be done after the transport is stopped */
|
||||
atomic_set(&priv->num_aux_in_flight, 0);
|
||||
|
||||
/* Clear out all status bits but a few that are stable across reset */
|
||||
priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
|
||||
STATUS_RF_KILL_HW |
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
||||
STATUS_GEO_CONFIGURED |
|
||||
test_bit(STATUS_FW_ERROR, &priv->status) <<
|
||||
STATUS_FW_ERROR |
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
|
||||
|
@ -1077,7 +1084,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
{
|
||||
priv->workqueue = create_singlethread_workqueue(DRV_NAME);
|
||||
|
||||
|
@ -1122,224 +1129,14 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
|||
del_timer_sync(&priv->ucode_trace);
|
||||
}
|
||||
|
||||
static void iwl_init_hw_rates(struct ieee80211_rate *rates)
|
||||
static int iwl_init_drv(struct iwl_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
|
||||
rates[i].bitrate = iwl_rates[i].ieee * 5;
|
||||
rates[i].hw_value = i; /* Rate scaling will work on indexes */
|
||||
rates[i].hw_value_short = i;
|
||||
rates[i].flags = 0;
|
||||
if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) {
|
||||
/*
|
||||
* If CCK != 1M then set short preamble rate flag.
|
||||
*/
|
||||
rates[i].flags |=
|
||||
(iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ?
|
||||
0 : IEEE80211_RATE_SHORT_PREAMBLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
|
||||
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
|
||||
static void iwl_init_ht_hw_capab(const struct iwl_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
u16 max_bit_rate = 0;
|
||||
u8 rx_chains_num = priv->hw_params.rx_chains_num;
|
||||
u8 tx_chains_num = priv->hw_params.tx_chains_num;
|
||||
|
||||
ht_info->cap = 0;
|
||||
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
|
||||
|
||||
ht_info->ht_supported = true;
|
||||
|
||||
if (priv->cfg->ht_params &&
|
||||
priv->cfg->ht_params->ht_greenfield_support)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
max_bit_rate = MAX_BIT_RATE_20_MHZ;
|
||||
if (priv->hw_params.ht40_channel & BIT(band)) {
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
|
||||
ht_info->mcs.rx_mask[4] = 0x01;
|
||||
max_bit_rate = MAX_BIT_RATE_40_MHZ;
|
||||
}
|
||||
|
||||
if (iwlwifi_mod_params.amsdu_size_8K)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
|
||||
ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
|
||||
|
||||
ht_info->mcs.rx_mask[0] = 0xFF;
|
||||
if (rx_chains_num >= 2)
|
||||
ht_info->mcs.rx_mask[1] = 0xFF;
|
||||
if (rx_chains_num >= 3)
|
||||
ht_info->mcs.rx_mask[2] = 0xFF;
|
||||
|
||||
/* Highest supported Rx data rate */
|
||||
max_bit_rate *= rx_chains_num;
|
||||
WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
|
||||
ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
|
||||
|
||||
/* Tx MCS capabilities */
|
||||
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
|
||||
if (tx_chains_num != rx_chains_num) {
|
||||
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
|
||||
ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
|
||||
*/
|
||||
static int iwl_init_geos(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_channel_info *ch;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_channel *channels;
|
||||
struct ieee80211_channel *geo_ch;
|
||||
struct ieee80211_rate *rates;
|
||||
int i = 0;
|
||||
s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN;
|
||||
|
||||
if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
|
||||
priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
|
||||
IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
|
||||
set_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
channels = kcalloc(priv->channel_count,
|
||||
sizeof(struct ieee80211_channel), GFP_KERNEL);
|
||||
if (!channels)
|
||||
return -ENOMEM;
|
||||
|
||||
rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate),
|
||||
GFP_KERNEL);
|
||||
if (!rates) {
|
||||
kfree(channels);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* 5.2GHz channels start after the 2.4GHz channels */
|
||||
sband = &priv->bands[IEEE80211_BAND_5GHZ];
|
||||
sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
|
||||
/* just OFDM */
|
||||
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
|
||||
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
|
||||
|
||||
if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
||||
IEEE80211_BAND_5GHZ);
|
||||
|
||||
sband = &priv->bands[IEEE80211_BAND_2GHZ];
|
||||
sband->channels = channels;
|
||||
/* OFDM & CCK */
|
||||
sband->bitrates = rates;
|
||||
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
|
||||
|
||||
if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
||||
IEEE80211_BAND_2GHZ);
|
||||
|
||||
priv->ieee_channels = channels;
|
||||
priv->ieee_rates = rates;
|
||||
|
||||
for (i = 0; i < priv->channel_count; i++) {
|
||||
ch = &priv->channel_info[i];
|
||||
|
||||
/* FIXME: might be removed if scan is OK */
|
||||
if (!is_channel_valid(ch))
|
||||
continue;
|
||||
|
||||
sband = &priv->bands[ch->band];
|
||||
|
||||
geo_ch = &sband->channels[sband->n_channels++];
|
||||
|
||||
geo_ch->center_freq =
|
||||
ieee80211_channel_to_frequency(ch->channel, ch->band);
|
||||
geo_ch->max_power = ch->max_power_avg;
|
||||
geo_ch->max_antenna_gain = 0xff;
|
||||
geo_ch->hw_value = ch->channel;
|
||||
|
||||
if (is_channel_valid(ch)) {
|
||||
if (!(ch->flags & EEPROM_CHANNEL_IBSS))
|
||||
geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
|
||||
|
||||
if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
|
||||
geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
|
||||
if (ch->flags & EEPROM_CHANNEL_RADAR)
|
||||
geo_ch->flags |= IEEE80211_CHAN_RADAR;
|
||||
|
||||
geo_ch->flags |= ch->ht40_extension_channel;
|
||||
|
||||
if (ch->max_power_avg > max_tx_power)
|
||||
max_tx_power = ch->max_power_avg;
|
||||
} else {
|
||||
geo_ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
|
||||
ch->channel, geo_ch->center_freq,
|
||||
is_channel_a_band(ch) ? "5.2" : "2.4",
|
||||
geo_ch->flags & IEEE80211_CHAN_DISABLED ?
|
||||
"restricted" : "valid",
|
||||
geo_ch->flags);
|
||||
}
|
||||
|
||||
priv->tx_power_device_lmt = max_tx_power;
|
||||
priv->tx_power_user_lmt = max_tx_power;
|
||||
priv->tx_power_next = max_tx_power;
|
||||
|
||||
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
|
||||
priv->hw_params.sku & EEPROM_SKU_CAP_BAND_52GHZ) {
|
||||
IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
|
||||
"Please send your %s to maintainer.\n",
|
||||
priv->trans->hw_id_str);
|
||||
priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
|
||||
}
|
||||
|
||||
if (iwlwifi_mod_params.disable_5ghz)
|
||||
priv->bands[IEEE80211_BAND_5GHZ].n_channels = 0;
|
||||
|
||||
IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
|
||||
priv->bands[IEEE80211_BAND_2GHZ].n_channels,
|
||||
priv->bands[IEEE80211_BAND_5GHZ].n_channels);
|
||||
|
||||
set_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_free_geos - undo allocations in iwl_init_geos
|
||||
*/
|
||||
static void iwl_free_geos(struct iwl_priv *priv)
|
||||
{
|
||||
kfree(priv->ieee_channels);
|
||||
kfree(priv->ieee_rates);
|
||||
clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
||||
}
|
||||
|
||||
int iwl_init_drv(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
spin_lock_init(&priv->sta_lock);
|
||||
|
||||
mutex_init(&priv->mutex);
|
||||
|
||||
INIT_LIST_HEAD(&priv->calib_results);
|
||||
|
||||
priv->ieee_channels = NULL;
|
||||
priv->ieee_rates = NULL;
|
||||
priv->band = IEEE80211_BAND_2GHZ;
|
||||
|
||||
priv->plcp_delta_threshold =
|
||||
|
@ -1370,31 +1167,11 @@ int iwl_init_drv(struct iwl_priv *priv)
|
|||
priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
|
||||
}
|
||||
|
||||
ret = iwl_init_channel_map(priv);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = iwl_init_geos(priv);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "initializing geos failed: %d\n", ret);
|
||||
goto err_free_channel_map;
|
||||
}
|
||||
iwl_init_hw_rates(priv->ieee_rates);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_channel_map:
|
||||
iwl_free_channel_map(priv);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_uninit_drv(struct iwl_priv *priv)
|
||||
static void iwl_uninit_drv(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_free_geos(priv);
|
||||
iwl_free_channel_map(priv);
|
||||
kfree(priv->scan_cmd);
|
||||
kfree(priv->beacon_cmd);
|
||||
kfree(rcu_dereference_raw(priv->noa_data));
|
||||
|
@ -1404,15 +1181,12 @@ void iwl_uninit_drv(struct iwl_priv *priv)
|
|||
#endif
|
||||
}
|
||||
|
||||
void iwl_set_hw_params(struct iwl_priv *priv)
|
||||
static void iwl_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->ht_params)
|
||||
priv->hw_params.use_rts_for_aggregation =
|
||||
priv->cfg->ht_params->use_rts_for_aggregation;
|
||||
|
||||
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
|
||||
priv->hw_params.sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
|
||||
|
||||
/* Device-specific setup */
|
||||
priv->lib->set_hw_params(priv);
|
||||
}
|
||||
|
@ -1420,7 +1194,7 @@ void iwl_set_hw_params(struct iwl_priv *priv)
|
|||
|
||||
|
||||
/* show what optional capabilities we have */
|
||||
void iwl_option_config(struct iwl_priv *priv)
|
||||
static void iwl_option_config(struct iwl_priv *priv)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n");
|
||||
|
@ -1453,6 +1227,42 @@ void iwl_option_config(struct iwl_priv *priv)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
u16 radio_cfg;
|
||||
|
||||
priv->eeprom_data->sku = priv->eeprom_data->sku;
|
||||
|
||||
if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
||||
!priv->cfg->ht_params) {
|
||||
IWL_ERR(priv, "Invalid 11n configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!priv->eeprom_data->sku) {
|
||||
IWL_ERR(priv, "Invalid device sku\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
|
||||
|
||||
radio_cfg = priv->eeprom_data->radio_cfg;
|
||||
|
||||
priv->hw_params.tx_chains_num =
|
||||
num_of_ant(priv->eeprom_data->valid_tx_ant);
|
||||
if (priv->cfg->rx_with_siso_diversity)
|
||||
priv->hw_params.rx_chains_num = 1;
|
||||
else
|
||||
priv->hw_params.rx_chains_num =
|
||||
num_of_ant(priv->eeprom_data->valid_rx_ant);
|
||||
|
||||
IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
|
||||
priv->eeprom_data->valid_tx_ant,
|
||||
priv->eeprom_data->valid_rx_ant);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_fw *fw)
|
||||
|
@ -1538,9 +1348,12 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
trans_cfg.queue_watchdog_timeout =
|
||||
priv->cfg->base_params->wd_timeout;
|
||||
else
|
||||
trans_cfg.queue_watchdog_timeout = IWL_WATCHHDOG_DISABLED;
|
||||
trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED;
|
||||
trans_cfg.command_names = iwl_dvm_cmd_strings;
|
||||
|
||||
WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
|
||||
priv->cfg->base_params->num_of_queues);
|
||||
|
||||
ucode_flags = fw->ucode_capa.flags;
|
||||
|
||||
#ifndef CONFIG_IWLWIFI_P2P
|
||||
|
@ -1598,25 +1411,33 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
goto out_free_hw;
|
||||
|
||||
/* Read the EEPROM */
|
||||
if (iwl_eeprom_init(priv, priv->trans->hw_rev)) {
|
||||
if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob,
|
||||
&priv->eeprom_blob_size)) {
|
||||
IWL_ERR(priv, "Unable to init EEPROM\n");
|
||||
goto out_free_hw;
|
||||
}
|
||||
|
||||
/* Reset chip to save power until we load uCode during "up". */
|
||||
iwl_trans_stop_hw(priv->trans, false);
|
||||
|
||||
if (iwl_eeprom_check_version(priv))
|
||||
priv->eeprom_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg,
|
||||
priv->eeprom_blob,
|
||||
priv->eeprom_blob_size);
|
||||
if (!priv->eeprom_data)
|
||||
goto out_free_eeprom_blob;
|
||||
|
||||
if (iwl_eeprom_check_version(priv->eeprom_data, priv->trans))
|
||||
goto out_free_eeprom;
|
||||
|
||||
if (iwl_eeprom_init_hw_params(priv))
|
||||
goto out_free_eeprom;
|
||||
|
||||
/* extract MAC Address */
|
||||
iwl_eeprom_get_mac(priv, priv->addresses[0].addr);
|
||||
memcpy(priv->addresses[0].addr, priv->eeprom_data->hw_addr, ETH_ALEN);
|
||||
IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
|
||||
priv->hw->wiphy->addresses = priv->addresses;
|
||||
priv->hw->wiphy->n_addresses = 1;
|
||||
num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS);
|
||||
num_mac = priv->eeprom_data->n_hw_addrs;
|
||||
if (num_mac > 1) {
|
||||
memcpy(priv->addresses[1].addr, priv->addresses[0].addr,
|
||||
ETH_ALEN);
|
||||
|
@ -1629,7 +1450,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
************************/
|
||||
iwl_set_hw_params(priv);
|
||||
|
||||
if (!(priv->hw_params.sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
|
||||
if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
|
||||
IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
|
||||
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||
/*
|
||||
|
@ -1710,8 +1531,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
destroy_workqueue(priv->workqueue);
|
||||
priv->workqueue = NULL;
|
||||
iwl_uninit_drv(priv);
|
||||
out_free_eeprom_blob:
|
||||
kfree(priv->eeprom_blob);
|
||||
out_free_eeprom:
|
||||
iwl_eeprom_free(priv);
|
||||
iwl_free_eeprom_data(priv->eeprom_data);
|
||||
out_free_hw:
|
||||
ieee80211_free_hw(priv->hw);
|
||||
out:
|
||||
|
@ -1719,7 +1542,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|||
return op_mode;
|
||||
}
|
||||
|
||||
void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
||||
static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
|
@ -1727,7 +1550,7 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
|||
|
||||
iwl_dbgfs_unregister(priv);
|
||||
|
||||
iwl_testmode_cleanup(priv);
|
||||
iwl_testmode_free(priv);
|
||||
iwlagn_mac_unregister(priv);
|
||||
|
||||
iwl_tt_exit(priv);
|
||||
|
@ -1736,7 +1559,8 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
|||
priv->ucode_loaded = false;
|
||||
iwl_trans_stop_device(priv->trans);
|
||||
|
||||
iwl_eeprom_free(priv);
|
||||
kfree(priv->eeprom_blob);
|
||||
iwl_free_eeprom_data(priv->eeprom_data);
|
||||
|
||||
/*netif_stop_queue(dev); */
|
||||
flush_workqueue(priv->workqueue);
|
||||
|
@ -1849,7 +1673,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
/*TODO: Update dbgfs with ISR error stats obtained below */
|
||||
iwl_read_targ_mem_words(trans, base, &table, sizeof(table));
|
||||
iwl_read_targ_mem_bytes(trans, base, &table, sizeof(table));
|
||||
|
||||
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
|
||||
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
|
||||
|
@ -2184,7 +2008,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
|||
}
|
||||
}
|
||||
|
||||
void iwl_nic_error(struct iwl_op_mode *op_mode)
|
||||
static void iwl_nic_error(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
|
@ -2197,7 +2021,7 @@ void iwl_nic_error(struct iwl_op_mode *op_mode)
|
|||
iwlagn_fw_error(priv, false);
|
||||
}
|
||||
|
||||
void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
|
||||
static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
|
@ -2207,11 +2031,60 @@ void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
|
|||
}
|
||||
}
|
||||
|
||||
void iwl_nic_config(struct iwl_op_mode *op_mode)
|
||||
#define EEPROM_RF_CONFIG_TYPE_MAX 0x3
|
||||
|
||||
static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
u16 radio_cfg = priv->eeprom_data->radio_cfg;
|
||||
|
||||
priv->lib->nic_config(priv);
|
||||
/* SKU Control */
|
||||
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
|
||||
(CSR_HW_REV_STEP(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
|
||||
(CSR_HW_REV_DASH(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
|
||||
|
||||
/* write radio config values to register */
|
||||
if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
|
||||
u32 reg_val =
|
||||
EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE |
|
||||
EEPROM_RF_CFG_STEP_MSK(radio_cfg) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_PHY_STEP |
|
||||
EEPROM_RF_CFG_DASH_MSK(radio_cfg) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
|
||||
|
||||
iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val);
|
||||
|
||||
IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
|
||||
EEPROM_RF_CFG_TYPE_MSK(radio_cfg),
|
||||
EEPROM_RF_CFG_STEP_MSK(radio_cfg),
|
||||
EEPROM_RF_CFG_DASH_MSK(radio_cfg));
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
/* set CSR_HW_CONFIG_REG for uCode use */
|
||||
iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
|
||||
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
|
||||
|
||||
/* W/A : NIC is stuck in a reset state after Early PCIe power off
|
||||
* (PCIe power is lost before PERST# is asserted),
|
||||
* causing ME FW to lose ownership and not being able to obtain it back.
|
||||
*/
|
||||
iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
||||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
|
||||
if (priv->lib->nic_config)
|
||||
priv->lib->nic_config(priv);
|
||||
}
|
||||
|
||||
static void iwl_wimax_active(struct iwl_op_mode *op_mode)
|
||||
|
@ -2222,7 +2095,7 @@ static void iwl_wimax_active(struct iwl_op_mode *op_mode)
|
|||
IWL_ERR(priv, "RF is used by WiMAX\n");
|
||||
}
|
||||
|
||||
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
||||
static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
int mq = priv->queue_to_mac80211[queue];
|
||||
|
@ -2241,7 +2114,7 @@ void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
|||
ieee80211_stop_queue(priv->hw, mq);
|
||||
}
|
||||
|
||||
void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
||||
static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
int mq = priv->queue_to_mac80211[queue];
|
||||
|
@ -2281,16 +2154,17 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
|
|||
priv->passive_no_rx = false;
|
||||
}
|
||||
|
||||
void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
|
||||
iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
||||
static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
|
@ -2302,7 +2176,7 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
|||
wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
|
||||
}
|
||||
|
||||
const struct iwl_op_mode_ops iwl_dvm_ops = {
|
||||
static const struct iwl_op_mode_ops iwl_dvm_ops = {
|
||||
.start = iwl_op_mode_dvm_start,
|
||||
.stop = iwl_op_mode_dvm_stop,
|
||||
.rx = iwl_rx_dispatch,
|
||||
|
@ -2321,9 +2195,6 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
|
|||
* driver and module entry point
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
struct kmem_cache *iwl_tx_cmd_pool;
|
||||
|
||||
static int __init iwl_init(void)
|
||||
{
|
||||
|
||||
|
@ -2331,29 +2202,18 @@ static int __init iwl_init(void)
|
|||
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
|
||||
pr_info(DRV_COPYRIGHT "\n");
|
||||
|
||||
iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd",
|
||||
sizeof(struct iwl_device_cmd),
|
||||
sizeof(void *), 0, NULL);
|
||||
if (!iwl_tx_cmd_pool)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = iwlagn_rate_control_register();
|
||||
if (ret) {
|
||||
pr_err("Unable to register rate control algorithm: %d\n", ret);
|
||||
goto error_rc_register;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops);
|
||||
if (ret) {
|
||||
pr_err("Unable to register op_mode: %d\n", ret);
|
||||
goto error_opmode_register;
|
||||
iwlagn_rate_control_unregister();
|
||||
}
|
||||
return ret;
|
||||
|
||||
error_opmode_register:
|
||||
iwlagn_rate_control_unregister();
|
||||
error_rc_register:
|
||||
kmem_cache_destroy(iwl_tx_cmd_pool);
|
||||
return ret;
|
||||
}
|
||||
module_init(iwl_init);
|
||||
|
@ -2362,6 +2222,5 @@ static void __exit iwl_exit(void)
|
|||
{
|
||||
iwl_opmode_deregister("iwldvm");
|
||||
iwlagn_rate_control_unregister();
|
||||
kmem_cache_destroy(iwl_tx_cmd_pool);
|
||||
}
|
||||
module_exit(iwl_exit);
|
|
@ -31,18 +31,15 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-power.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
#include "commands.h"
|
||||
#include "power.h"
|
||||
|
||||
/*
|
||||
* Setting power level allows the card to go to sleep when not busy.
|
|
@ -28,7 +28,7 @@
|
|||
#ifndef __iwl_power_setting_h__
|
||||
#define __iwl_power_setting_h__
|
||||
|
||||
#include "iwl-commands.h"
|
||||
#include "commands.h"
|
||||
|
||||
struct iwl_power_mgr {
|
||||
struct iwl_powertable_cmd sleep_cmd;
|
|
@ -35,10 +35,8 @@
|
|||
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
|
||||
#define RS_NAME "iwl-agn-rs"
|
||||
|
||||
|
@ -819,7 +817,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
|
|||
|
||||
if (num_of_ant(tbl->ant_type) > 1)
|
||||
tbl->ant_type =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
|
||||
tbl->is_ht40 = 0;
|
||||
tbl->is_SGI = 0;
|
||||
|
@ -1447,7 +1445,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
|
|||
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
|
||||
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
|
||||
u8 start_action;
|
||||
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
|
||||
u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant;
|
||||
u8 tx_chains_num = priv->hw_params.tx_chains_num;
|
||||
int ret = 0;
|
||||
u8 update_search_tbl_counter = 0;
|
||||
|
@ -1465,7 +1463,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
|
|||
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
|
||||
/* avoid antenna B and MIMO */
|
||||
valid_tx_ant =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 &&
|
||||
tbl->action != IWL_LEGACY_SWITCH_SISO)
|
||||
tbl->action = IWL_LEGACY_SWITCH_SISO;
|
||||
|
@ -1489,7 +1487,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
|
|||
else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
|
||||
tbl->action = IWL_LEGACY_SWITCH_SISO;
|
||||
valid_tx_ant =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
}
|
||||
|
||||
start_action = tbl->action;
|
||||
|
@ -1623,7 +1621,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
|
|||
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
|
||||
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
|
||||
u8 start_action;
|
||||
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
|
||||
u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant;
|
||||
u8 tx_chains_num = priv->hw_params.tx_chains_num;
|
||||
u8 update_search_tbl_counter = 0;
|
||||
int ret;
|
||||
|
@ -1641,7 +1639,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
|
|||
case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
|
||||
/* avoid antenna B and MIMO */
|
||||
valid_tx_ant =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
if (tbl->action != IWL_SISO_SWITCH_ANTENNA1)
|
||||
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
|
||||
break;
|
||||
|
@ -1659,7 +1657,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
|
|||
/* configure as 1x1 if bt full concurrency */
|
||||
if (priv->bt_full_concurrent) {
|
||||
valid_tx_ant =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2)
|
||||
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
|
||||
}
|
||||
|
@ -1795,7 +1793,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
|
|||
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
|
||||
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
|
||||
u8 start_action;
|
||||
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
|
||||
u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant;
|
||||
u8 tx_chains_num = priv->hw_params.tx_chains_num;
|
||||
u8 update_search_tbl_counter = 0;
|
||||
int ret;
|
||||
|
@ -1965,7 +1963,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
|
|||
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
|
||||
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
|
||||
u8 start_action;
|
||||
u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
|
||||
u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant;
|
||||
u8 tx_chains_num = priv->hw_params.tx_chains_num;
|
||||
int ret;
|
||||
u8 update_search_tbl_counter = 0;
|
||||
|
@ -2699,7 +2697,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
|
|||
|
||||
i = lq_sta->last_txrate_idx;
|
||||
|
||||
valid_tx_ant = priv->hw_params.valid_tx_ant;
|
||||
valid_tx_ant = priv->eeprom_data->valid_tx_ant;
|
||||
|
||||
if (!lq_sta->search_better_tbl)
|
||||
active_tbl = lq_sta->active_tbl;
|
||||
|
@ -2893,15 +2891,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
|
|||
|
||||
/* These values will be overridden later */
|
||||
lq_sta->lq.general_params.single_stream_ant_msk =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
lq_sta->lq.general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant &
|
||||
~first_antenna(priv->hw_params.valid_tx_ant);
|
||||
priv->eeprom_data->valid_tx_ant &
|
||||
~first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
|
||||
lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
|
||||
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
|
||||
} else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) {
|
||||
lq_sta->lq.general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant;
|
||||
priv->eeprom_data->valid_tx_ant;
|
||||
}
|
||||
|
||||
/* as default allow aggregation for all tids */
|
||||
|
@ -2947,7 +2945,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
|
|||
if (priv && priv->bt_full_concurrent) {
|
||||
/* 1x1 only */
|
||||
tbl_type.ant_type =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
}
|
||||
|
||||
/* How many times should we repeat the initial rate? */
|
||||
|
@ -2979,7 +2977,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
|
|||
if (priv->bt_full_concurrent)
|
||||
valid_tx_ant = ANT_A;
|
||||
else
|
||||
valid_tx_ant = priv->hw_params.valid_tx_ant;
|
||||
valid_tx_ant = priv->eeprom_data->valid_tx_ant;
|
||||
}
|
||||
|
||||
/* Fill rest of rate table */
|
||||
|
@ -3013,7 +3011,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
|
|||
if (priv && priv->bt_full_concurrent) {
|
||||
/* 1x1 only */
|
||||
tbl_type.ant_type =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
}
|
||||
|
||||
/* Indicate to uCode which entries might be MIMO.
|
||||
|
@ -3100,7 +3098,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
|
|||
u8 ant_sel_tx;
|
||||
|
||||
priv = lq_sta->drv;
|
||||
valid_tx_ant = priv->hw_params.valid_tx_ant;
|
||||
valid_tx_ant = priv->eeprom_data->valid_tx_ant;
|
||||
if (lq_sta->dbg_fixed_rate) {
|
||||
ant_sel_tx =
|
||||
((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
|
||||
|
@ -3171,9 +3169,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
|
|||
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
|
||||
lq_sta->dbg_fixed_rate);
|
||||
desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
|
||||
(priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
|
||||
(priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
|
||||
(priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : "");
|
||||
(priv->eeprom_data->valid_tx_ant & ANT_A) ? "ANT_A," : "",
|
||||
(priv->eeprom_data->valid_tx_ant & ANT_B) ? "ANT_B," : "",
|
||||
(priv->eeprom_data->valid_tx_ant & ANT_C) ? "ANT_C" : "");
|
||||
desc += sprintf(buff+desc, "lq type %s\n",
|
||||
(is_legacy(tbl->lq_type)) ? "legacy" : "HT");
|
||||
if (is_Ht(tbl->lq_type)) {
|
|
@ -29,9 +29,10 @@
|
|||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-config.h"
|
||||
|
||||
#include "commands.h"
|
||||
|
||||
struct iwl_rate_info {
|
||||
u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
|
||||
u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
|
|
@ -32,12 +32,10 @@
|
|||
#include <linux/sched.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "dev.h"
|
||||
#include "calib.h"
|
||||
#include "agn.h"
|
||||
|
||||
#define IWL_CMD_ENTRY(x) [x] = #x
|
||||
|
||||
|
@ -1012,6 +1010,8 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
|
|||
rx_status.flag |= RX_FLAG_40MHZ;
|
||||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
rx_status.flag |= RX_FLAG_SHORT_GI;
|
||||
if (rate_n_flags & RATE_MCS_GF_MSK)
|
||||
rx_status.flag |= RX_FLAG_HT_GF;
|
||||
|
||||
iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status,
|
||||
rxb, &rx_status);
|
||||
|
@ -1124,8 +1124,6 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
|
|||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
void (*pre_rx_handler)(struct iwl_priv *,
|
||||
struct iwl_rx_cmd_buffer *);
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
|
@ -1135,19 +1133,19 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
|
|||
*/
|
||||
iwl_notification_wait_notify(&priv->notif_wait, pkt);
|
||||
|
||||
/* RX data may be forwarded to userspace (using pre_rx_handler) in one
|
||||
* of two cases: the first, that the user owns the uCode through
|
||||
* testmode - in such case the pre_rx_handler is set and no further
|
||||
* processing takes place. The other case is when the user want to
|
||||
* monitor the rx w/o affecting the regular flow - the pre_rx_handler
|
||||
* will be set but the ownership flag != IWL_OWNERSHIP_TM and the flow
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
||||
/*
|
||||
* RX data may be forwarded to userspace in one
|
||||
* of two cases: the user owns the fw through testmode or when
|
||||
* the user requested to monitor the rx w/o affecting the regular flow.
|
||||
* In these cases the iwl_test object will handle forwarding the rx
|
||||
* data to user space.
|
||||
* Note that if the ownership flag != IWL_OWNERSHIP_TM the flow
|
||||
* continues.
|
||||
* We need to use ACCESS_ONCE to prevent a case where the handler
|
||||
* changes between the check and the call.
|
||||
*/
|
||||
pre_rx_handler = ACCESS_ONCE(priv->pre_rx_handler);
|
||||
if (pre_rx_handler)
|
||||
pre_rx_handler(priv, rxb);
|
||||
iwl_test_rx(&priv->tst, rxb);
|
||||
#endif
|
||||
|
||||
if (priv->ucode_owner != IWL_OWNERSHIP_TM) {
|
||||
/* Based on type of command response or notification,
|
||||
* handle those that need handling via function in
|
|
@ -25,11 +25,11 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
#include "calib.h"
|
||||
|
||||
/*
|
||||
* initialize rxon structure with default values from eeprom
|
||||
|
@ -37,8 +37,6 @@
|
|||
void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
const struct iwl_channel_info *ch_info;
|
||||
|
||||
memset(&ctx->staging, 0, sizeof(ctx->staging));
|
||||
|
||||
if (!ctx->vif) {
|
||||
|
@ -80,14 +78,8 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
|||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
#endif
|
||||
|
||||
ch_info = iwl_get_channel_info(priv, priv->band,
|
||||
le16_to_cpu(ctx->active.channel));
|
||||
|
||||
if (!ch_info)
|
||||
ch_info = &priv->channel_info[0];
|
||||
|
||||
ctx->staging.channel = cpu_to_le16(ch_info->channel);
|
||||
priv->band = ch_info->band;
|
||||
ctx->staging.channel = cpu_to_le16(priv->hw->conf.channel->hw_value);
|
||||
priv->band = priv->hw->conf.channel->band;
|
||||
|
||||
iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
|
||||
|
||||
|
@ -175,7 +167,8 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
static void iwlagn_update_qos(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -202,8 +195,8 @@ void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|||
IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n");
|
||||
}
|
||||
|
||||
int iwlagn_update_beacon(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
static int iwlagn_update_beacon(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
|
@ -215,7 +208,7 @@ int iwlagn_update_beacon(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
struct iwl_rxon_assoc_cmd rxon_assoc;
|
||||
|
@ -427,10 +420,10 @@ static int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tx_power > priv->tx_power_device_lmt) {
|
||||
if (tx_power > DIV_ROUND_UP(priv->eeprom_data->max_tx_pwr_half_dbm, 2)) {
|
||||
IWL_WARN(priv,
|
||||
"Requested user TXPOWER %d above upper limit %d.\n",
|
||||
tx_power, priv->tx_power_device_lmt);
|
||||
tx_power, priv->eeprom_data->max_tx_pwr_half_dbm);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -863,8 +856,8 @@ static int iwl_check_rxon_cmd(struct iwl_priv *priv,
|
|||
* or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
|
||||
* a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
|
||||
*/
|
||||
int iwl_full_rxon_required(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
static int iwl_full_rxon_required(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
const struct iwl_rxon_cmd *staging = &ctx->staging;
|
||||
const struct iwl_rxon_cmd *active = &ctx->active;
|
||||
|
@ -1189,7 +1182,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
|||
struct iwl_rxon_context *ctx;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = conf->channel;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
int ret = 0;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed);
|
||||
|
@ -1223,14 +1215,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
|||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
ch_info = iwl_get_channel_info(priv, channel->band,
|
||||
channel->hw_value);
|
||||
if (!is_channel_valid(ch_info)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
/* Configure HT40 channels */
|
||||
if (ctx->ht.enabled != conf_is_ht(conf))
|
||||
|
@ -1294,9 +1278,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void iwlagn_check_needed_chains(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
static void iwlagn_check_needed_chains(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
struct iwl_rxon_context *tmp;
|
||||
|
@ -1388,7 +1372,7 @@ void iwlagn_check_needed_chains(struct iwl_priv *priv,
|
|||
ht_conf->single_chain_sufficient = !need_multiple;
|
||||
}
|
||||
|
||||
void iwlagn_chain_noise_reset(struct iwl_priv *priv)
|
||||
static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_chain_noise_data *data = &priv->chain_noise_data;
|
||||
int ret;
|
|
@ -30,11 +30,8 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
|
||||
/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
|
||||
* sending probe req. This should be set long enough to hear probe responses
|
||||
|
@ -54,6 +51,9 @@
|
|||
#define IWL_CHANNEL_TUNE_TIME 5
|
||||
#define MAX_SCAN_CHANNEL 50
|
||||
|
||||
/* For reset radio, need minimal dwell time only */
|
||||
#define IWL_RADIO_RESET_DWELL_TIME 5
|
||||
|
||||
static int iwl_send_scan_abort(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
@ -67,7 +67,6 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
|
|||
* to receive scan abort command or it does not perform
|
||||
* hardware scan currently */
|
||||
if (!test_bit(STATUS_READY, &priv->status) ||
|
||||
!test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
|
||||
!test_bit(STATUS_SCAN_HW, &priv->status) ||
|
||||
test_bit(STATUS_FW_ERROR, &priv->status))
|
||||
return -EIO;
|
||||
|
@ -101,11 +100,8 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
|
|||
ieee80211_scan_completed(priv->hw, aborted);
|
||||
}
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_ROC) {
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
priv->hw_roc_channel = NULL;
|
||||
schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
|
||||
}
|
||||
if (priv->scan_type == IWL_SCAN_ROC)
|
||||
iwl_scan_roc_expired(priv);
|
||||
|
||||
priv->scan_type = IWL_SCAN_NORMAL;
|
||||
priv->scan_vif = NULL;
|
||||
|
@ -134,11 +130,8 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
|
|||
goto out_settings;
|
||||
}
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_ROC) {
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
priv->hw_roc_channel = NULL;
|
||||
schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
|
||||
}
|
||||
if (priv->scan_type == IWL_SCAN_ROC)
|
||||
iwl_scan_roc_expired(priv);
|
||||
|
||||
if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
|
||||
int err;
|
||||
|
@ -453,27 +446,17 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
|
|||
|
||||
/* Return valid, unused, channel for a passive scan to reset the RF */
|
||||
static u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
||||
enum ieee80211_band band)
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
const struct iwl_channel_info *ch_info;
|
||||
int i;
|
||||
u8 channel = 0;
|
||||
u8 min, max;
|
||||
struct ieee80211_supported_band *sband = priv->hw->wiphy->bands[band];
|
||||
struct iwl_rxon_context *ctx;
|
||||
int i;
|
||||
|
||||
if (band == IEEE80211_BAND_5GHZ) {
|
||||
min = 14;
|
||||
max = priv->channel_count;
|
||||
} else {
|
||||
min = 0;
|
||||
max = 14;
|
||||
}
|
||||
|
||||
for (i = min; i < max; i++) {
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
bool busy = false;
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
busy = priv->channel_info[i].channel ==
|
||||
busy = sband->channels[i].hw_value ==
|
||||
le16_to_cpu(ctx->staging.channel);
|
||||
if (busy)
|
||||
break;
|
||||
|
@ -482,54 +465,46 @@ static u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
|||
if (busy)
|
||||
continue;
|
||||
|
||||
channel = priv->channel_info[i].channel;
|
||||
ch_info = iwl_get_channel_info(priv, band, channel);
|
||||
if (is_channel_valid(ch_info))
|
||||
break;
|
||||
if (!(sband->channels[i].flags & IEEE80211_CHAN_DISABLED))
|
||||
return sband->channels[i].hw_value;
|
||||
}
|
||||
|
||||
return channel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_band band,
|
||||
struct iwl_scan_channel *scan_ch)
|
||||
static int iwl_get_channel_for_reset_scan(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_band band,
|
||||
struct iwl_scan_channel *scan_ch)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u16 passive_dwell = 0;
|
||||
u16 active_dwell = 0;
|
||||
int added = 0;
|
||||
u16 channel = 0;
|
||||
u16 channel;
|
||||
|
||||
sband = iwl_get_hw_mode(priv, band);
|
||||
if (!sband) {
|
||||
IWL_ERR(priv, "invalid band\n");
|
||||
return added;
|
||||
return 0;
|
||||
}
|
||||
|
||||
active_dwell = iwl_get_active_dwell_time(priv, band, 0);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band);
|
||||
|
||||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
||||
channel = iwl_get_single_channel_number(priv, band);
|
||||
if (channel) {
|
||||
scan_ch->channel = cpu_to_le16(channel);
|
||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||
scan_ch->active_dwell = cpu_to_le16(active_dwell);
|
||||
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
|
||||
scan_ch->active_dwell =
|
||||
cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
|
||||
scan_ch->passive_dwell =
|
||||
cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
|
||||
/* Set txpower levels to defaults */
|
||||
scan_ch->dsp_atten = 110;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
|
||||
else
|
||||
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
|
||||
added++;
|
||||
} else
|
||||
IWL_ERR(priv, "no valid channel found\n");
|
||||
return added;
|
||||
return 1;
|
||||
}
|
||||
|
||||
IWL_ERR(priv, "no valid channel found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
||||
|
@ -540,7 +515,6 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
|||
{
|
||||
struct ieee80211_channel *chan;
|
||||
const struct ieee80211_supported_band *sband;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
u16 passive_dwell = 0;
|
||||
u16 active_dwell = 0;
|
||||
int added, i;
|
||||
|
@ -565,16 +539,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
|||
channel = chan->hw_value;
|
||||
scan_ch->channel = cpu_to_le16(channel);
|
||||
|
||||
ch_info = iwl_get_channel_info(priv, band, channel);
|
||||
if (!is_channel_valid(ch_info)) {
|
||||
IWL_DEBUG_SCAN(priv,
|
||||
"Channel %d is INVALID for this band.\n",
|
||||
channel);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_active || is_channel_passive(ch_info) ||
|
||||
(chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
|
||||
if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
|
||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||
else
|
||||
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
|
||||
|
@ -678,12 +643,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
u16 rx_chain = 0;
|
||||
enum ieee80211_band band;
|
||||
u8 n_probes = 0;
|
||||
u8 rx_ant = priv->hw_params.valid_rx_ant;
|
||||
u8 rx_ant = priv->eeprom_data->valid_rx_ant;
|
||||
u8 rate;
|
||||
bool is_active = false;
|
||||
int chan_mod;
|
||||
u8 active_chains;
|
||||
u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
|
||||
u8 scan_tx_antennas = priv->eeprom_data->valid_tx_ant;
|
||||
int ret;
|
||||
int scan_cmd_size = sizeof(struct iwl_scan_cmd) +
|
||||
MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) +
|
||||
|
@ -755,6 +720,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
|
||||
/*
|
||||
* Override quiet time as firmware checks that active
|
||||
* dwell is >= quiet; since we use passive scan it'll
|
||||
* not actually be used.
|
||||
*/
|
||||
scan->quiet_time = cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
|
||||
break;
|
||||
case IWL_SCAN_NORMAL:
|
||||
if (priv->scan_request->n_ssids) {
|
||||
|
@ -893,7 +864,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
|
||||
/* MIMO is not used here, but value is required */
|
||||
rx_chain |=
|
||||
priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
|
||||
priv->eeprom_data->valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
|
||||
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
|
||||
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
|
||||
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
|
||||
|
@ -928,7 +899,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
scan->channel_count =
|
||||
iwl_get_single_channel_for_scan(priv, vif, band,
|
||||
iwl_get_channel_for_reset_scan(priv, vif, band,
|
||||
(void *)&scan->data[cmd_len]);
|
||||
break;
|
||||
case IWL_SCAN_NORMAL:
|
||||
|
@ -994,8 +965,10 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
set_bit(STATUS_SCAN_HW, &priv->status);
|
||||
|
||||
ret = iwlagn_set_pan_params(priv);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
clear_bit(STATUS_SCAN_HW, &priv->status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_dvm_send_cmd(priv, &cmd);
|
||||
if (ret) {
|
||||
|
@ -1008,7 +981,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
|||
|
||||
void iwl_init_scan_params(struct iwl_priv *priv)
|
||||
{
|
||||
u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
|
||||
u8 ant_idx = fls(priv->eeprom_data->valid_tx_ant) - 1;
|
||||
if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
|
||||
priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
|
||||
if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
|
||||
|
@ -1158,3 +1131,40 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
|
|||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_scan_roc_expired(struct iwl_priv *priv)
|
||||
{
|
||||
/*
|
||||
* The status bit should be set here, to prevent a race
|
||||
* where the atomic_read returns 1, but before the execution continues
|
||||
* iwl_scan_offchannel_skb_status() checks if the status bit is set
|
||||
*/
|
||||
set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
|
||||
|
||||
if (atomic_read(&priv->num_aux_in_flight) == 0) {
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
priv->hw_roc_channel = NULL;
|
||||
schedule_delayed_work(&priv->hw_roc_disable_work,
|
||||
10 * HZ);
|
||||
|
||||
clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status);
|
||||
} else {
|
||||
IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n",
|
||||
atomic_read(&priv->num_aux_in_flight));
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_scan_offchannel_skb(struct iwl_priv *priv)
|
||||
{
|
||||
WARN_ON(!priv->hw_roc_start_notified);
|
||||
atomic_inc(&priv->num_aux_in_flight);
|
||||
}
|
||||
|
||||
void iwl_scan_offchannel_skb_status(struct iwl_priv *priv)
|
||||
{
|
||||
if (atomic_dec_return(&priv->num_aux_in_flight) == 0 &&
|
||||
test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n");
|
||||
iwl_scan_roc_expired(priv);
|
||||
}
|
||||
}
|
|
@ -28,10 +28,9 @@
|
|||
*****************************************************************************/
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
|
||||
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
|
@ -171,26 +170,6 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
|||
return cmd.handler_status;
|
||||
}
|
||||
|
||||
static bool iwl_is_channel_extension(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
u16 channel, u8 extension_chan_offset)
|
||||
{
|
||||
const struct iwl_channel_info *ch_info;
|
||||
|
||||
ch_info = iwl_get_channel_info(priv, band, channel);
|
||||
if (!is_channel_valid(ch_info))
|
||||
return false;
|
||||
|
||||
if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
|
||||
return !(ch_info->ht40_extension_channel &
|
||||
IEEE80211_CHAN_NO_HT40PLUS);
|
||||
else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
|
||||
return !(ch_info->ht40_extension_channel &
|
||||
IEEE80211_CHAN_NO_HT40MINUS);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_sta_ht_cap *ht_cap)
|
||||
|
@ -198,21 +177,25 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
|||
if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
|
||||
* the bit will not set if it is pure 40MHz case
|
||||
*/
|
||||
if (ht_cap && !ht_cap->ht_supported)
|
||||
return false;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (priv->disable_ht40)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return iwl_is_channel_extension(priv, priv->band,
|
||||
le16_to_cpu(ctx->staging.channel),
|
||||
ctx->ht.extension_chan_offset);
|
||||
/*
|
||||
* Remainder of this function checks ht_cap, but if it's
|
||||
* NULL then we can do HT40 (special case for RXON)
|
||||
*/
|
||||
if (!ht_cap)
|
||||
return true;
|
||||
|
||||
if (!ht_cap->ht_supported)
|
||||
return false;
|
||||
|
||||
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
|
||||
|
@ -650,23 +633,23 @@ static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
|||
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
|
||||
rate_flags |= RATE_MCS_CCK_MSK;
|
||||
|
||||
rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
|
||||
rate_flags |= first_antenna(priv->eeprom_data->valid_tx_ant) <<
|
||||
RATE_MCS_ANT_POS;
|
||||
rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
|
||||
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
|
||||
link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
|
||||
|
||||
link_cmd->general_params.single_stream_ant_msk =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
|
||||
link_cmd->general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant &
|
||||
~first_antenna(priv->hw_params.valid_tx_ant);
|
||||
priv->eeprom_data->valid_tx_ant &
|
||||
~first_antenna(priv->eeprom_data->valid_tx_ant);
|
||||
if (!link_cmd->general_params.dual_stream_ant_msk) {
|
||||
link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
|
||||
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
|
||||
} else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) {
|
||||
link_cmd->general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant;
|
||||
priv->eeprom_data->valid_tx_ant;
|
||||
}
|
||||
|
||||
link_cmd->agg_params.agg_dis_start_th =
|
||||
|
@ -1268,7 +1251,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
|||
key_flags |= STA_KEY_MULTICAST_MSK;
|
||||
|
||||
sta_cmd.key.key_flags = key_flags;
|
||||
sta_cmd.key.key_offset = WEP_INVALID_OFFSET;
|
||||
sta_cmd.key.key_offset = keyconf->hw_key_idx;
|
||||
sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
|
||||
sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
|
||||
|
471
drivers/net/wireless/iwlwifi/dvm/testmode.c
Normal file
471
drivers/net/wireless/iwlwifi/dvm/testmode.c
Normal file
|
@ -0,0 +1,471 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
#include "iwl-test.h"
|
||||
#include "iwl-testmode.h"
|
||||
|
||||
static int iwl_testmode_send_cmd(struct iwl_op_mode *op_mode,
|
||||
struct iwl_host_cmd *cmd)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
return iwl_dvm_send_cmd(priv, cmd);
|
||||
}
|
||||
|
||||
static bool iwl_testmode_valid_hw_addr(u32 addr)
|
||||
{
|
||||
if (iwlagn_hw_valid_rtc_data_addr(addr))
|
||||
return true;
|
||||
|
||||
if (IWLAGN_RTC_INST_LOWER_BOUND <= addr &&
|
||||
addr < IWLAGN_RTC_INST_UPPER_BOUND)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u32 iwl_testmode_get_fw_ver(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
return priv->fw->ucode_ver;
|
||||
}
|
||||
|
||||
static struct sk_buff*
|
||||
iwl_testmode_alloc_reply(struct iwl_op_mode *op_mode, int len)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
return cfg80211_testmode_alloc_reply_skb(priv->hw->wiphy, len);
|
||||
}
|
||||
|
||||
static int iwl_testmode_reply(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
{
|
||||
return cfg80211_testmode_reply(skb);
|
||||
}
|
||||
|
||||
static struct sk_buff *iwl_testmode_alloc_event(struct iwl_op_mode *op_mode,
|
||||
int len)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
return cfg80211_testmode_alloc_event_skb(priv->hw->wiphy, len,
|
||||
GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static void iwl_testmode_event(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
{
|
||||
return cfg80211_testmode_event(skb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static struct iwl_test_ops tst_ops = {
|
||||
.send_cmd = iwl_testmode_send_cmd,
|
||||
.valid_hw_addr = iwl_testmode_valid_hw_addr,
|
||||
.get_fw_ver = iwl_testmode_get_fw_ver,
|
||||
.alloc_reply = iwl_testmode_alloc_reply,
|
||||
.reply = iwl_testmode_reply,
|
||||
.alloc_event = iwl_testmode_alloc_event,
|
||||
.event = iwl_testmode_event,
|
||||
};
|
||||
|
||||
void iwl_testmode_init(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_test_init(&priv->tst, priv->trans, &tst_ops);
|
||||
}
|
||||
|
||||
void iwl_testmode_free(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_test_free(&priv->tst);
|
||||
}
|
||||
|
||||
static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_notification_wait calib_wait;
|
||||
static const u8 calib_complete[] = {
|
||||
CALIBRATION_COMPLETE_NOTIFICATION
|
||||
};
|
||||
int ret;
|
||||
|
||||
iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
|
||||
calib_complete, ARRAY_SIZE(calib_complete),
|
||||
NULL, NULL);
|
||||
ret = iwl_init_alive_start(priv);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Fail init calibration: %d\n", ret);
|
||||
goto cfg_init_calib_error;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Error detecting"
|
||||
" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
|
||||
return ret;
|
||||
|
||||
cfg_init_calib_error:
|
||||
iwl_remove_notification(&priv->notif_wait, &calib_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the user application commands for driver.
|
||||
*
|
||||
* It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
|
||||
* handlers respectively.
|
||||
*
|
||||
* If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
|
||||
* value of the actual command execution is replied to the user application.
|
||||
*
|
||||
* If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP
|
||||
* is used for carry the message while IWL_TM_ATTR_COMMAND must set to
|
||||
* IWL_TM_CMD_DEV2APP_SYNC_RSP.
|
||||
*
|
||||
* @hw: ieee80211_hw object that represents the device
|
||||
* @tb: gnl message fields from the user space
|
||||
*/
|
||||
static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_trans *trans = priv->trans;
|
||||
struct sk_buff *skb;
|
||||
unsigned char *rsp_data_ptr = NULL;
|
||||
int status = 0, rsp_data_len = 0;
|
||||
u32 inst_size = 0, data_size = 0;
|
||||
const struct fw_img *img;
|
||||
|
||||
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
|
||||
case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
|
||||
rsp_data_ptr = (unsigned char *)priv->cfg->name;
|
||||
rsp_data_len = strlen(priv->cfg->name);
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
||||
rsp_data_len + 20);
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
|
||||
IWL_TM_CMD_DEV2APP_SYNC_RSP) ||
|
||||
nla_put(skb, IWL_TM_ATTR_SYNC_RSP,
|
||||
rsp_data_len, rsp_data_ptr))
|
||||
goto nla_put_failure;
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
|
||||
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
|
||||
if (status)
|
||||
IWL_ERR(priv, "Error loading init ucode: %d\n", status);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
|
||||
iwl_testmode_cfg_init_calib(priv);
|
||||
priv->ucode_loaded = false;
|
||||
iwl_trans_stop_device(trans);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
|
||||
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
|
||||
if (status) {
|
||||
IWL_ERR(priv,
|
||||
"Error loading runtime ucode: %d\n", status);
|
||||
break;
|
||||
}
|
||||
status = iwl_alive_start(priv);
|
||||
if (status)
|
||||
IWL_ERR(priv,
|
||||
"Error starting the device: %d\n", status);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
priv->ucode_loaded = false;
|
||||
iwl_trans_stop_device(trans);
|
||||
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
|
||||
if (status) {
|
||||
IWL_ERR(priv,
|
||||
"Error loading WOWLAN ucode: %d\n", status);
|
||||
break;
|
||||
}
|
||||
status = iwl_alive_start(priv);
|
||||
if (status)
|
||||
IWL_ERR(priv,
|
||||
"Error starting the device: %d\n", status);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_GET_EEPROM:
|
||||
if (priv->eeprom_blob) {
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
||||
priv->eeprom_blob_size + 20);
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
|
||||
IWL_TM_CMD_DEV2APP_EEPROM_RSP) ||
|
||||
nla_put(skb, IWL_TM_ATTR_EEPROM,
|
||||
priv->eeprom_blob_size,
|
||||
priv->eeprom_blob))
|
||||
goto nla_put_failure;
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_ERR(priv, "Error sending msg : %d\n",
|
||||
status);
|
||||
} else
|
||||
return -ENODATA;
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
|
||||
if (!tb[IWL_TM_ATTR_FIXRATE]) {
|
||||
IWL_ERR(priv, "Missing fixrate setting\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8);
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!priv->ucode_loaded) {
|
||||
IWL_ERR(priv, "No uCode has not been loaded\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
img = &priv->fw->img[priv->cur_ucode];
|
||||
inst_size = img->sec[IWL_UCODE_SECTION_INST].len;
|
||||
data_size = img->sec[IWL_UCODE_SECTION_DATA].len;
|
||||
}
|
||||
if (nla_put_u32(skb, IWL_TM_ATTR_FW_TYPE, priv->cur_ucode) ||
|
||||
nla_put_u32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size) ||
|
||||
nla_put_u32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size))
|
||||
goto nla_put_failure;
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
break;
|
||||
|
||||
default:
|
||||
IWL_ERR(priv, "Unknown testmode driver command ID\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
return status;
|
||||
|
||||
nla_put_failure:
|
||||
kfree_skb(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the user application switch ucode ownership.
|
||||
*
|
||||
* It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and
|
||||
* decide who the current owner of the uCode
|
||||
*
|
||||
* If the current owner is OWNERSHIP_TM, then the only host command
|
||||
* can deliver to uCode is from testmode, all the other host commands
|
||||
* will dropped.
|
||||
*
|
||||
* default driver is the owner of uCode in normal operational mode
|
||||
*
|
||||
* @hw: ieee80211_hw object that represents the device
|
||||
* @tb: gnl message fields from the user space
|
||||
*/
|
||||
static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
u8 owner;
|
||||
|
||||
if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
|
||||
IWL_ERR(priv, "Missing ucode owner\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
|
||||
if (owner == IWL_OWNERSHIP_DRIVER) {
|
||||
priv->ucode_owner = owner;
|
||||
iwl_test_enable_notifications(&priv->tst, false);
|
||||
} else if (owner == IWL_OWNERSHIP_TM) {
|
||||
priv->ucode_owner = owner;
|
||||
iwl_test_enable_notifications(&priv->tst, true);
|
||||
} else {
|
||||
IWL_ERR(priv, "Invalid owner\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The testmode gnl message handler that takes the gnl message from the
|
||||
* user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
|
||||
* invoke the corresponding handlers.
|
||||
*
|
||||
* This function is invoked when there is user space application sending
|
||||
* gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated
|
||||
* by nl80211.
|
||||
*
|
||||
* It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before
|
||||
* dispatching it to the corresponding handler.
|
||||
*
|
||||
* If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application;
|
||||
* -ENOSYS is replied to the user application if the command is unknown;
|
||||
* Otherwise, the command is dispatched to the respective handler.
|
||||
*
|
||||
* @hw: ieee80211_hw object that represents the device
|
||||
* @data: pointer to user space message
|
||||
* @len: length in byte of @data
|
||||
*/
|
||||
int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
{
|
||||
struct nlattr *tb[IWL_TM_ATTR_MAX];
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
int result;
|
||||
|
||||
result = iwl_test_parse(&priv->tst, tb, data, len);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
/* in case multiple accesses to the device happens */
|
||||
mutex_lock(&priv->mutex);
|
||||
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
|
||||
case IWL_TM_CMD_APP2DEV_UCODE:
|
||||
case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
|
||||
case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
|
||||
case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
|
||||
case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
|
||||
case IWL_TM_CMD_APP2DEV_END_TRACE:
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
|
||||
case IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
|
||||
case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
|
||||
case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
|
||||
result = iwl_test_handle_cmd(&priv->tst, tb);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
|
||||
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
|
||||
case IWL_TM_CMD_APP2DEV_GET_EEPROM:
|
||||
case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
|
||||
case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
|
||||
IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
|
||||
result = iwl_testmode_driver(hw, tb);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_OWNERSHIP:
|
||||
IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n");
|
||||
result = iwl_testmode_ownership(hw, tb);
|
||||
break;
|
||||
|
||||
default:
|
||||
IWL_ERR(priv, "Unknown testmode command\n");
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
if (result)
|
||||
IWL_ERR(priv, "Test cmd failed result=%d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct netlink_callback *cb,
|
||||
void *data, int len)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
int result;
|
||||
u32 cmd;
|
||||
|
||||
if (cb->args[3]) {
|
||||
/* offset by 1 since commands start at 0 */
|
||||
cmd = cb->args[3] - 1;
|
||||
} else {
|
||||
struct nlattr *tb[IWL_TM_ATTR_MAX];
|
||||
|
||||
result = iwl_test_parse(&priv->tst, tb, data, len);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
|
||||
cb->args[3] = cmd + 1;
|
||||
}
|
||||
|
||||
/* in case multiple accesses to the device happens */
|
||||
mutex_lock(&priv->mutex);
|
||||
result = iwl_test_dump(&priv->tst, cmd, skb, cb);
|
||||
mutex_unlock(&priv->mutex);
|
||||
return result;
|
||||
}
|
|
@ -31,17 +31,14 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-agn-tt.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "agn.h"
|
||||
#include "dev.h"
|
||||
#include "commands.h"
|
||||
#include "tt.h"
|
||||
|
||||
/* default Thermal Throttling transaction table
|
||||
* Current state | Throttling Down | Throttling Up
|
|
@ -28,7 +28,7 @@
|
|||
#ifndef __iwl_tt_setting_h__
|
||||
#define __iwl_tt_setting_h__
|
||||
|
||||
#include "iwl-commands.h"
|
||||
#include "commands.h"
|
||||
|
||||
#define IWL_ABSOLUTE_ZERO 0
|
||||
#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
|
|
@ -32,12 +32,11 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ieee80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
|
||||
static const u8 tid_to_ac[] = {
|
||||
IEEE80211_AC_BE,
|
||||
|
@ -187,7 +186,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
|
|||
rate_idx = info->control.rates[0].idx;
|
||||
if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS ||
|
||||
(rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY))
|
||||
rate_idx = rate_lowest_index(&priv->bands[info->band],
|
||||
rate_idx = rate_lowest_index(
|
||||
&priv->eeprom_data->bands[info->band],
|
||||
info->control.sta);
|
||||
/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
|
||||
if (info->band == IEEE80211_BAND_5GHZ)
|
||||
|
@ -207,10 +207,11 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
|
|||
priv->bt_full_concurrent) {
|
||||
/* operated as 1x1 in full concurrency mode */
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
||||
first_antenna(priv->hw_params.valid_tx_ant));
|
||||
first_antenna(priv->eeprom_data->valid_tx_ant));
|
||||
} else
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
||||
priv->hw_params.valid_tx_ant);
|
||||
priv->mgmt_tx_ant = iwl_toggle_tx_ant(
|
||||
priv, priv->mgmt_tx_ant,
|
||||
priv->eeprom_data->valid_tx_ant);
|
||||
rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
|
||||
|
||||
/* Set the rate in the TX cmd */
|
||||
|
@ -296,7 +297,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl_station_priv *sta_priv = NULL;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl_device_cmd *dev_cmd = NULL;
|
||||
struct iwl_device_cmd *dev_cmd;
|
||||
struct iwl_tx_cmd *tx_cmd;
|
||||
__le16 fc;
|
||||
u8 hdr_len;
|
||||
|
@ -378,7 +379,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
is_agg = true;
|
||||
|
||||
dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC);
|
||||
dev_cmd = iwl_trans_alloc_tx_cmd(priv->trans);
|
||||
|
||||
if (unlikely(!dev_cmd))
|
||||
goto drop_unlock_priv;
|
||||
|
@ -402,6 +403,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
|
||||
info->driver_data[0] = ctx;
|
||||
info->driver_data[1] = dev_cmd;
|
||||
/* From now on, we cannot access info->control */
|
||||
|
||||
spin_lock(&priv->sta_lock);
|
||||
|
||||
|
@ -486,11 +488,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
if (sta_priv && sta_priv->client && !is_agg)
|
||||
atomic_inc(&sta_priv->pending_frames);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
|
||||
iwl_scan_offchannel_skb(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
drop_unlock_sta:
|
||||
if (dev_cmd)
|
||||
kmem_cache_free(iwl_tx_cmd_pool, dev_cmd);
|
||||
iwl_trans_free_tx_cmd(priv->trans, dev_cmd);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
drop_unlock_priv:
|
||||
return -1;
|
||||
|
@ -597,7 +602,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||
* time, or we hadn't time to drain the AC queues.
|
||||
*/
|
||||
if (agg_state == IWL_AGG_ON)
|
||||
iwl_trans_tx_agg_disable(priv->trans, txq_id);
|
||||
iwl_trans_txq_disable(priv->trans, txq_id);
|
||||
else
|
||||
IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n",
|
||||
agg_state);
|
||||
|
@ -686,9 +691,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
|||
|
||||
fifo = ctx->ac_to_fifo[tid_to_ac[tid]];
|
||||
|
||||
iwl_trans_tx_agg_setup(priv->trans, q, fifo,
|
||||
sta_priv->sta_id, tid,
|
||||
buf_size, ssn);
|
||||
iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid,
|
||||
buf_size, ssn);
|
||||
|
||||
/*
|
||||
* If the limit is 0, then it wasn't initialised yet,
|
||||
|
@ -753,8 +757,8 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
|
|||
IWL_DEBUG_TX_QUEUES(priv,
|
||||
"Can continue DELBA flow ssn = next_recl ="
|
||||
" %d", tid_data->next_reclaimed);
|
||||
iwl_trans_tx_agg_disable(priv->trans,
|
||||
tid_data->agg.txq_id);
|
||||
iwl_trans_txq_disable(priv->trans,
|
||||
tid_data->agg.txq_id);
|
||||
iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id);
|
||||
tid_data->agg.state = IWL_AGG_OFF;
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
|
||||
|
@ -1136,6 +1140,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
|||
struct sk_buff *skb;
|
||||
struct iwl_rxon_context *ctx;
|
||||
bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
|
||||
bool is_offchannel_skb;
|
||||
|
||||
tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
|
||||
IWLAGN_TX_RES_TID_POS;
|
||||
|
@ -1149,6 +1154,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
|||
|
||||
__skb_queue_head_init(&skbs);
|
||||
|
||||
is_offchannel_skb = false;
|
||||
|
||||
if (tx_resp->frame_count == 1) {
|
||||
u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
|
||||
next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10);
|
||||
|
@ -1176,7 +1183,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
|||
}
|
||||
|
||||
/*we can free until ssn % q.n_bd not inclusive */
|
||||
WARN_ON(iwl_reclaim(priv, sta_id, tid, txq_id, ssn, &skbs));
|
||||
WARN_ON_ONCE(iwl_reclaim(priv, sta_id, tid,
|
||||
txq_id, ssn, &skbs));
|
||||
iwlagn_check_ratid_empty(priv, sta_id, tid);
|
||||
freed = 0;
|
||||
|
||||
|
@ -1189,8 +1197,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
|||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
ctx = info->driver_data[0];
|
||||
kmem_cache_free(iwl_tx_cmd_pool,
|
||||
(info->driver_data[1]));
|
||||
iwl_trans_free_tx_cmd(priv->trans,
|
||||
info->driver_data[1]);
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
|
@ -1225,10 +1233,19 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
|||
if (!is_agg)
|
||||
iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
|
||||
|
||||
is_offchannel_skb =
|
||||
(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);
|
||||
freed++;
|
||||
}
|
||||
|
||||
WARN_ON(!is_agg && freed != 1);
|
||||
|
||||
/*
|
||||
* An offchannel frame can be send only on the AUX queue, where
|
||||
* there is no aggregation (and reordering) so it only is single
|
||||
* skb is expected to be processed.
|
||||
*/
|
||||
WARN_ON(is_offchannel_skb && freed != 1);
|
||||
}
|
||||
|
||||
iwl_check_abort_status(priv, tx_resp->frame_count, status);
|
||||
|
@ -1239,6 +1256,9 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
|||
ieee80211_tx_status(priv->hw, skb);
|
||||
}
|
||||
|
||||
if (is_offchannel_skb)
|
||||
iwl_scan_offchannel_skb_status(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1341,7 +1361,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
WARN_ON_ONCE(1);
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
|
||||
iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
|
||||
|
||||
if (freed == 1) {
|
||||
/* this is the first skb we deliver in this batch */
|
|
@ -30,15 +30,16 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "iwl-op-mode.h"
|
||||
|
||||
#include "dev.h"
|
||||
#include "agn.h"
|
||||
#include "calib.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* uCode download functions
|
||||
|
@ -60,8 +61,7 @@ iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type)
|
|||
static int iwl_set_Xtal_calib(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_xtal_freq_cmd cmd;
|
||||
__le16 *xtal_calib =
|
||||
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
|
||||
__le16 *xtal_calib = priv->eeprom_data->xtal_calib;
|
||||
|
||||
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
|
||||
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
|
||||
|
@ -72,12 +72,10 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv)
|
|||
static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_temperature_offset_cmd cmd;
|
||||
__le16 *offset_calib =
|
||||
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
|
||||
memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib));
|
||||
cmd.radio_sensor_offset = priv->eeprom_data->raw_temperature;
|
||||
if (!(cmd.radio_sensor_offset))
|
||||
cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||
|
||||
|
@ -89,27 +87,17 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
|
|||
static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_temperature_offset_v2_cmd cmd;
|
||||
__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv,
|
||||
EEPROM_KELVIN_TEMPERATURE);
|
||||
__le16 *offset_calib_low =
|
||||
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
|
||||
struct iwl_eeprom_calib_hdr *hdr;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
|
||||
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
|
||||
EEPROM_CALIB_ALL);
|
||||
memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
|
||||
sizeof(*offset_calib_high));
|
||||
memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
|
||||
sizeof(*offset_calib_low));
|
||||
if (!(cmd.radio_sensor_offset_low)) {
|
||||
cmd.radio_sensor_offset_high = priv->eeprom_data->kelvin_temperature;
|
||||
cmd.radio_sensor_offset_low = priv->eeprom_data->raw_temperature;
|
||||
if (!cmd.radio_sensor_offset_low) {
|
||||
IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
|
||||
cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||
cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||
}
|
||||
memcpy(&cmd.burntVoltageRef, &hdr->voltage,
|
||||
sizeof(hdr->voltage));
|
||||
cmd.burntVoltageRef = priv->eeprom_data->calib_voltage;
|
||||
|
||||
IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
|
||||
le16_to_cpu(cmd.radio_sensor_offset_high));
|
||||
|
@ -177,7 +165,7 @@ int iwl_init_alive_start(struct iwl_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iwl_send_wimax_coex(struct iwl_priv *priv)
|
||||
static int iwl_send_wimax_coex(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_wimax_coex_cmd coex_cmd;
|
||||
|
|
@ -113,7 +113,7 @@ enum iwl_led_mode {
|
|||
#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE 0
|
||||
|
||||
/* TX queue watchdog timeouts in mSecs */
|
||||
#define IWL_WATCHHDOG_DISABLED 0
|
||||
#define IWL_WATCHDOG_DISABLED 0
|
||||
#define IWL_DEF_WD_TIMEOUT 2000
|
||||
#define IWL_LONG_WD_TIMEOUT 10000
|
||||
#define IWL_MAX_WD_TIMEOUT 120000
|
||||
|
@ -182,13 +182,34 @@ struct iwl_bt_params {
|
|||
bool bt_sco_disable;
|
||||
bool bt_session_2;
|
||||
};
|
||||
|
||||
/*
|
||||
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
|
||||
* @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40
|
||||
*/
|
||||
struct iwl_ht_params {
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
const bool ht_greenfield_support; /* if used set to true */
|
||||
bool use_rts_for_aggregation;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
u8 ht40_bands;
|
||||
};
|
||||
|
||||
/*
|
||||
* information on how to parse the EEPROM
|
||||
*/
|
||||
#define EEPROM_REG_BAND_1_CHANNELS 0x08
|
||||
#define EEPROM_REG_BAND_2_CHANNELS 0x26
|
||||
#define EEPROM_REG_BAND_3_CHANNELS 0x42
|
||||
#define EEPROM_REG_BAND_4_CHANNELS 0x5C
|
||||
#define EEPROM_REG_BAND_5_CHANNELS 0x74
|
||||
#define EEPROM_REG_BAND_24_HT40_CHANNELS 0x82
|
||||
#define EEPROM_REG_BAND_52_HT40_CHANNELS 0x92
|
||||
#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80
|
||||
#define EEPROM_REGULATORY_BAND_NO_HT40 0
|
||||
|
||||
struct iwl_eeprom_params {
|
||||
const u8 regulatory_bands[7];
|
||||
bool enhanced_txpower;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -243,6 +264,7 @@ struct iwl_cfg {
|
|||
/* params likely to change within a device family */
|
||||
const struct iwl_ht_params *ht_params;
|
||||
const struct iwl_bt_params *bt_params;
|
||||
const struct iwl_eeprom_params *eeprom_params;
|
||||
const bool need_temp_offset_calib; /* if used set to true */
|
||||
const bool no_xtal_calib;
|
||||
enum iwl_led_mode led_mode;
|
||||
|
|
|
@ -97,13 +97,10 @@
|
|||
/*
|
||||
* Hardware revision info
|
||||
* Bit fields:
|
||||
* 31-8: Reserved
|
||||
* 7-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions
|
||||
* 31-16: Reserved
|
||||
* 15-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions
|
||||
* 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
|
||||
* 1-0: "Dash" (-) value, as in A-1, etc.
|
||||
*
|
||||
* NOTE: Revision step affects calculation of CCK txpower for 4965.
|
||||
* NOTE: See also CSR_HW_REV_WA_REG (work-around for bug in 4965).
|
||||
*/
|
||||
#define CSR_HW_REV (CSR_BASE+0x028)
|
||||
|
||||
|
@ -155,9 +152,21 @@
|
|||
#define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250)
|
||||
|
||||
/* Bits for CSR_HW_IF_CONFIG_REG */
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE (0x00000C00)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH (0x00003000)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP (0x0000C000)
|
||||
|
||||
#define CSR_HW_IF_CONFIG_REG_POS_MAC_DASH (0)
|
||||
#define CSR_HW_IF_CONFIG_REG_POS_MAC_STEP (2)
|
||||
#define CSR_HW_IF_CONFIG_REG_POS_BOARD_VER (6)
|
||||
#define CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE (10)
|
||||
#define CSR_HW_IF_CONFIG_REG_POS_PHY_DASH (12)
|
||||
#define CSR_HW_IF_CONFIG_REG_POS_PHY_STEP (14)
|
||||
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
|
||||
|
@ -270,7 +279,10 @@
|
|||
|
||||
|
||||
/* HW REV */
|
||||
#define CSR_HW_REV_TYPE_MSK (0x00001F0)
|
||||
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
|
||||
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
|
||||
|
||||
#define CSR_HW_REV_TYPE_MSK (0x000FFF0)
|
||||
#define CSR_HW_REV_TYPE_5300 (0x0000020)
|
||||
#define CSR_HW_REV_TYPE_5350 (0x0000030)
|
||||
#define CSR_HW_REV_TYPE_5100 (0x0000050)
|
||||
|
|
|
@ -45,6 +45,7 @@ void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3);
|
|||
|
||||
/* No matter what is m (priv, bus, trans), this will work */
|
||||
#define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a)
|
||||
#define IWL_ERR_DEV(d, f, a...) __iwl_err((d), false, false, f, ## a)
|
||||
#define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a)
|
||||
#define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a)
|
||||
#define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a)
|
||||
|
@ -69,6 +70,8 @@ do { \
|
|||
|
||||
#define IWL_DEBUG(m, level, fmt, args...) \
|
||||
__iwl_dbg((m)->dev, level, false, __func__, fmt, ##args)
|
||||
#define IWL_DEBUG_DEV(dev, level, fmt, args...) \
|
||||
__iwl_dbg((dev), level, false, __func__, fmt, ##args)
|
||||
#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \
|
||||
__iwl_dbg((m)->dev, level, true, __func__, fmt, ##args)
|
||||
|
||||
|
@ -153,7 +156,7 @@ do { \
|
|||
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a)
|
||||
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
|
||||
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
|
||||
#define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a)
|
||||
#define IWL_DEBUG_EEPROM(d, f, a...) IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a)
|
||||
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
|
||||
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
|
||||
#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define __IWLWIFI_DEVICE_TRACE
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
|
||||
#if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue