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

John Linville says:

====================
This is a sizeable batch of updates intended for 3.6...

The bulk of the changes here are Bluetooth.  Gustavo says:

	Here goes the first Bluetooth pull request for 3.6, we have
	queued quite a lot of work. Andrei Emeltchenko added the AMP
	Manager code, a lot of work is needed, but the first bit are
	already there. This code is disabled by default.  Mat Martineau
	changed the whole L2CAP ERTM state machine code, replacing
	the old one with a new implementation. Besides that we had
	lot of coding style fixes (to follow net rules), more l2cap
	core separation from socket and many clean ups and fixed all
	over the tree.

Along with the above, there is a healthy dose of ath9k, iwlwifi,
and other driver updates.  There is also another pull from the
wireless tree to resolve some merge issues.  I also fixed-up some
merge discrepencies between net-next and wireless-next.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2012-06-19 14:37:15 -07:00
86 changed files with 4849 additions and 3072 deletions
+5 -5
View File
@@ -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));
+1 -1
View File
@@ -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) {
+2 -2
View File
@@ -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;
+3
View File
@@ -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 },
+2 -2
View File
@@ -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));
+3 -11
View File
@@ -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) {
+2 -2
View File
@@ -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));
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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;
+3 -3
View File
@@ -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);
+5 -2
View File
@@ -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);
+170 -160
View File
@@ -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;
@@ -893,13 +891,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,38 +1011,32 @@ 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);
REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
REG_SET_BIT(ah, AR_MCI_TX_CTRL,
AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL,
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);
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 +1164,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 +1179,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 +1191,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 +1199,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 +1223,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 +1230,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);
@@ -1404,3 +1263,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);
+17 -15
View File
@@ -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
@@ -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},
+1
View File
@@ -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;
+5 -5
View File
@@ -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,
+9 -2
View File
@@ -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)
+8
View File
@@ -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);
+4 -18
View File
@@ -150,6 +150,9 @@ 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
cancel_work_sync(&sc->mci_work);
#endif
}
static void ath_cancel_work(struct ath_softc *sc)
@@ -1033,15 +1036,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 +1060,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 +1243,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;
}

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