Commit ae3568ad authored by John W. Linville's avatar John W. Linville
Browse files

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
parents 7f3e01fe b7753c8c
......@@ -3671,7 +3671,7 @@ F: include/linux/mv643xx.h
MARVELL MWL8K WIRELESS DRIVER
M: Lennert Buytenhek <buytenh@wantstofly.org>
L: linux-wireless@vger.kernel.org
S: Maintained
S: Odd Fixes
F: drivers/net/wireless/mwl8k.c
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
......@@ -4522,7 +4522,7 @@ PRISM54 WIRELESS DRIVER
M: "Luis R. Rodriguez" <mcgrof@gmail.com>
L: linux-wireless@vger.kernel.org
W: http://prism54.org
S: Maintained
S: Obsolete
F: drivers/net/wireless/prism54/
PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
......@@ -4712,9 +4712,8 @@ S: Maintained
F: drivers/rapidio/
RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
M: Corey Thomas <coreythomas@charter.net>
L: linux-wireless@vger.kernel.org
S: Maintained
S: Orphan
F: drivers/net/wireless/ray*
RCUTORTURE MODULE
......@@ -6037,10 +6036,9 @@ F: Documentation/video4linux/zc0301.txt
F: drivers/media/video/zc0301/
USB ZD1201 DRIVER
M: Jeroen Vreeken <pe1rxq@amsat.org>
L: linux-usb@vger.kernel.org
L: linux-wireless@vger.kernel.org
W: http://linux-lc100020.sourceforge.net
S: Maintained
S: Orphan
F: drivers/net/wireless/zd1201.*
USB ZR364XX DRIVER
......@@ -6226,14 +6224,6 @@ F: Documentation/watchdog/
F: drivers/watchdog/
F: include/linux/watchdog.h
WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS
M: Jean Tourrilhes <jt@hpl.hp.com>
L: linux-wireless@vger.kernel.org
W: http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
S: Maintained
F: Documentation/networking/wavelan.txt
F: drivers/staging/wavelan/
WD7000 SCSI DRIVER
M: Miroslav Zagorac <zaga@fly.cc.fer.hr>
L: linux-scsi@vger.kernel.org
......
......@@ -58,6 +58,18 @@ config BT_HCIUART_BCSP
Say Y here to compile support for HCI BCSP protocol.
config BT_HCIUART_ATH3K
bool "Atheros AR300x serial support"
depends on BT_HCIUART
help
HCIATH3K (HCI Atheros AR300x) is a serial protocol for
communication between host and Atheros AR300x Bluetooth devices.
This protocol enables AR300x chips to be enabled with
power management support.
Enable this if you have Atheros AR300x serial Bluetooth device.
Say Y here to compile support for HCI UART ATH3K protocol.
config BT_HCIUART_LL
bool "HCILL protocol support"
depends on BT_HCIUART
......
......@@ -26,4 +26,5 @@ hci_uart-y := hci_ldisc.o
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o
hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o
hci_uart-objs := $(hci_uart-y)
......@@ -224,7 +224,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
if (!data->fw_data) {
BT_ERR("Can't allocate memory for firmware image");
release_firmware(firmware);
......@@ -234,7 +234,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
return -ENOMEM;
}
memcpy(data->fw_data, firmware->data, firmware->size);
data->fw_size = firmware->size;
data->fw_sent = 0;
......
......@@ -62,7 +62,7 @@ struct hci_vendor_hdr {
__u8 type;
__le16 snum;
__le16 dlen;
} __attribute__ ((packed));
} __packed;
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
{
......
......@@ -216,7 +216,7 @@ static const struct file_operations btmrvl_gpiogap_fops = {
static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct btmrvl_private *priv = (struct btmrvl_private *) file->private_data;
struct btmrvl_private *priv = file->private_data;
char buf[16];
long result, ret;
......
......@@ -76,6 +76,7 @@ struct btmrvl_private {
int (*hw_host_to_card) (struct btmrvl_private *priv,
u8 *payload, u16 nb);
int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
int (*hw_process_int_status) (struct btmrvl_private *priv);
spinlock_t driver_lock; /* spinlock used by driver */
#ifdef CONFIG_DEBUG_FS
void *debugfs_data;
......@@ -118,13 +119,13 @@ struct btmrvl_cmd {
__le16 ocf_ogf;
u8 length;
u8 data[4];
} __attribute__ ((packed));
} __packed;
struct btmrvl_event {
u8 ec; /* event counter */
u8 length;
u8 data[4];
} __attribute__ ((packed));
} __packed;
/* Prototype of global function */
......
......@@ -502,14 +502,17 @@ static int btmrvl_service_main_thread(void *data)
spin_lock_irqsave(&priv->driver_lock, flags);
if (adapter->int_count) {
adapter->int_count = 0;
spin_unlock_irqrestore(&priv->driver_lock, flags);
priv->hw_process_int_status(priv);
} else if (adapter->ps_state == PS_SLEEP &&
!skb_queue_empty(&adapter->tx_queue)) {
spin_unlock_irqrestore(&priv->driver_lock, flags);
adapter->wakeup_tries++;
priv->hw_wakeup_firmware(priv);
continue;
} else {
spin_unlock_irqrestore(&priv->driver_lock, flags);
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
if (adapter->ps_state == PS_SLEEP)
continue;
......
......@@ -47,6 +47,7 @@
* module_exit function is called.
*/
static u8 user_rmmod;
static u8 sdio_ireg;
static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
.helper = "sd8688_helper.bin",
......@@ -83,10 +84,10 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
*dat = 0;
fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret);
if (ret)
return -EIO;
if (!ret)
fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
if (ret)
return -EIO;
......@@ -216,7 +217,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL);
if (!tmphlprbuf) {
BT_ERR("Unable to allocate buffer for helper."
" Terminating download");
......@@ -224,8 +225,6 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
goto done;
}
memset(tmphlprbuf, 0, tmphlprbufsz);
helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
/* Perform helper data transfer */
......@@ -318,7 +317,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
if (!tmpfwbuf) {
BT_ERR("Unable to allocate buffer for firmware."
" Terminating download");
......@@ -326,8 +325,6 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
goto done;
}
memset(tmpfwbuf, 0, tmpfwbufsz);
/* Ensure aligned firmware buffer */
fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
......@@ -555,78 +552,79 @@ exit:
return ret;
}
static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg)
static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
{
int ret;
u8 sdio_ireg = 0;
ulong flags;
u8 ireg;
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
*ireg = 0;
sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
if (ret) {
BT_ERR("sdio_readb: read int status register failed");
ret = -EIO;
goto done;
}
if (sdio_ireg != 0) {
/*
* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
* Clear the interrupt status register and re-enable the
* interrupt.
*/
BT_DBG("sdio_ireg = 0x%x", sdio_ireg);
sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS |
UP_LD_HOST_INT_STATUS),
HOST_INTSTATUS_REG, &ret);
if (ret) {
BT_ERR("sdio_writeb: clear int status register "
"failed");
ret = -EIO;
goto done;
}
}
spin_lock_irqsave(&priv->driver_lock, flags);
ireg = sdio_ireg;
sdio_ireg = 0;
spin_unlock_irqrestore(&priv->driver_lock, flags);
if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
sdio_claim_host(card->func);
if (ireg & DN_LD_HOST_INT_STATUS) {
if (priv->btmrvl_dev.tx_dnld_rdy)
BT_DBG("tx_done already received: "
" int_status=0x%x", sdio_ireg);
" int_status=0x%x", ireg);
else
priv->btmrvl_dev.tx_dnld_rdy = true;
}
if (sdio_ireg & UP_LD_HOST_INT_STATUS)
if (ireg & UP_LD_HOST_INT_STATUS)
btmrvl_sdio_card_to_host(priv);
*ireg = sdio_ireg;
ret = 0;
sdio_release_host(card->func);
done:
return ret;
return 0;
}
static void btmrvl_sdio_interrupt(struct sdio_func *func)
{
struct btmrvl_private *priv;
struct hci_dev *hcidev;
struct btmrvl_sdio_card *card;
ulong flags;
u8 ireg = 0;
int ret;
card = sdio_get_drvdata(func);
if (card && card->priv) {
priv = card->priv;
hcidev = priv->btmrvl_dev.hcidev;
if (!card || !card->priv) {
BT_ERR("sbi_interrupt(%p) card or priv is "
"NULL, card=%p\n", func, card);
return;
}
if (btmrvl_sdio_get_int_status(priv, &ireg))
BT_ERR("reading HOST_INT_STATUS_REG failed");
else
BT_DBG("HOST_INT_STATUS_REG %#x", ireg);
priv = card->priv;
ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
if (ret) {
BT_ERR("sdio_readb: read int status register failed");
return;
}
if (ireg != 0) {
/*
* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
* Clear the interrupt status register and re-enable the
* interrupt.
*/
BT_DBG("ireg = 0x%x", ireg);
btmrvl_interrupt(priv);
sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
UP_LD_HOST_INT_STATUS),
HOST_INTSTATUS_REG, &ret);
if (ret) {
BT_ERR("sdio_writeb: clear int status register failed");
return;
}
}
spin_lock_irqsave(&priv->driver_lock, flags);
sdio_ireg |= ireg;
spin_unlock_irqrestore(&priv->driver_lock, flags);
btmrvl_interrupt(priv);
}
static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
......@@ -930,6 +928,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
/* Initialize the interface specific function pointers */
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
priv->hw_process_int_status = btmrvl_sdio_process_int_status;
if (btmrvl_register_hdev(priv)) {
BT_ERR("Register hdev failed!");
......
......@@ -59,6 +59,9 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Apple iMac11,1 */
{ USB_DEVICE(0x05ac, 0x8215) },
/* AVM BlueFRITZ! USB v2.0 */
{ USB_DEVICE(0x057c, 0x3800) },
......@@ -146,6 +149,7 @@ static struct usb_device_id blacklist_table[] = {
#define BTUSB_BULK_RUNNING 1
#define BTUSB_ISOC_RUNNING 2
#define BTUSB_SUSPENDING 3
#define BTUSB_DID_ISO_RESUME 4
struct btusb_data {
struct hci_dev *hdev;
......@@ -179,7 +183,6 @@ struct btusb_data {
unsigned int sco_num;
int isoc_altsetting;
int suspend_count;
int did_iso_resume:1;
};
static int inc_tx(struct btusb_data *data)
......@@ -807,7 +810,7 @@ static void btusb_work(struct work_struct *work)
int err;
if (hdev->conn_hash.sco_num > 0) {
if (!data->did_iso_resume) {
if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
err = usb_autopm_get_interface(data->isoc);
if (err < 0) {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
......@@ -815,7 +818,7 @@ static void btusb_work(struct work_struct *work)
return;
}
data->did_iso_resume = 1;
set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
}
if (data->isoc_altsetting != 2) {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
......@@ -836,10 +839,8 @@ static void btusb_work(struct work_struct *work)
usb_kill_anchored_urbs(&data->isoc_anchor);
__set_isoc_interface(hdev, 0);
if (data->did_iso_resume) {
data->did_iso_resume = 0;
if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
usb_autopm_put_interface(data->isoc);
}
}
}
......
......@@ -104,7 +104,7 @@ typedef struct {
u8 type;
u8 zero;
u16 len;
} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */
} __packed nsh_t; /* Nokia Specific Header */
#define NSHL 4 /* Nokia Specific Header Length */
......
/*
* Atheros Communication Bluetooth HCIATH3K UART protocol
*
* HCIATH3K (HCI Atheros AR300x Protocol) is a Atheros Communication's
* power management protocol extension to H4 to support AR300x Bluetooth Chip.
*
* Copyright (c) 2009-2010 Atheros Communications Inc.
*
* Acknowledgements:
* This file is based on hci_h4.c, which was written
* by Maxim Krasnyansky and Marcel Holtmann.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/skbuff.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "hci_uart.h"
struct ath_struct {
struct hci_uart *hu;
unsigned int cur_sleep;
struct sk_buff_head txq;
struct work_struct ctxtsw;
};
static int ath_wakeup_ar3k(struct tty_struct *tty)
{
struct termios settings;
int status = tty->driver->ops->tiocmget(tty, NULL);
if (status & TIOCM_CTS)
return status;
/* Disable Automatic RTSCTS */
n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
settings.c_cflag &= ~CRTSCTS;
n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
/* Clear RTS first */
status = tty->driver->ops->tiocmget(tty, NULL);
tty->driver->ops->tiocmset(tty, NULL, 0x00, TIOCM_RTS);
mdelay(20);
/* Set RTS, wake up board */
status = tty->driver->ops->tiocmget(tty, NULL);
tty->driver->ops->tiocmset(tty, NULL, TIOCM_RTS, 0x00);
mdelay(20);
status = tty->driver->ops->tiocmget(tty, NULL);
n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
settings.c_cflag |= CRTSCTS;
n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
return status;
}
static void ath_hci_uart_work(struct work_struct *work)
{
int status;
struct ath_struct *ath;
struct hci_uart *hu;
struct tty_struct *tty;
ath = container_of(work, struct ath_struct, ctxtsw);
hu = ath->hu;
tty = hu->tty;
/* verify and wake up controller */
if (ath->cur_sleep) {
status = ath_wakeup_ar3k(tty);
if (!(status & TIOCM_CTS))
return;
}
/* Ready to send Data */
clear_bit(HCI_UART_SENDING, &hu->tx_state);
hci_uart_tx_wakeup(hu);
}
/* Initialize protocol */
static int ath_open(struct hci_uart *hu)
{
struct ath_struct *ath;
BT_DBG("hu %p", hu);
ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
if (!ath)
return -ENOMEM;
skb_queue_head_init(&ath->txq);
hu->priv = ath;
ath->hu = hu;
INIT_WORK(&ath->ctxtsw, ath_hci_uart_work);
return 0;
}
/* Flush protocol data */
static int ath_flush(struct hci_uart *hu)
{
struct ath_struct *ath = hu->priv;
BT_DBG("hu %p", hu);
skb_queue_purge(&ath->txq);
return 0;
}
/* Close protocol */
static int ath_close(struct hci_uart *hu)
{
struct ath_struct *ath = hu->priv;
BT_DBG("hu %p", hu);
skb_queue_purge(&ath->txq);
cancel_work_sync(&ath->ctxtsw);
hu->priv = NULL;
kfree(ath);
return 0;
}
#define HCI_OP_ATH_SLEEP 0xFC04
/* Enqueue frame for transmittion */
static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct ath_struct *ath = hu->priv;
if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
kfree_skb(skb);
return 0;
}
/*
* Update power management enable flag with parameters of
* HCI sleep enable vendor specific HCI command.
*/
if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
struct hci_command_hdr *hdr = (void *)skb->data;
if (__le16_to_cpu(hdr->opcode) == HCI_OP_ATH_SLEEP)
ath->cur_sleep = skb->data[HCI_COMMAND_HDR_SIZE];
}
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&ath->txq, skb);
set_bit(HCI_UART_SENDING, &hu->tx_state);
schedule_work(&ath->ctxtsw);
return 0;
}
static struct sk_buff *ath_dequeue(struct hci_uart *hu)
{
struct ath_struct *ath = hu->priv;
return skb_dequeue(&ath->txq);
}
/* Recv data */
static int ath_recv(struct hci_uart *hu, void *data, int count)
{
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
BT_ERR("Frame Reassembly Failed");