Commit f6cd0718 authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents 574a7930 9c238ca8
...@@ -201,7 +201,7 @@ config BT_MRVL ...@@ -201,7 +201,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices. The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787/8797/8897. Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897.
Say Y here to compile Marvell Bluetooth driver Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module. into the kernel or say M to compile it as module.
...@@ -214,7 +214,7 @@ config BT_MRVL_SDIO ...@@ -214,7 +214,7 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface. The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8897 devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897
chipsets are supported. chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver Say Y here to compile support for Marvell BT-over-SDIO driver
......
...@@ -84,7 +84,27 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { ...@@ -84,7 +84,27 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
.int_read_to_clear = false, .int_read_to_clear = false,
}; };
static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = { static const struct btmrvl_sdio_card_reg btmrvl_reg_8887 = {
.cfg = 0x00,
.host_int_mask = 0x08,
.host_intstatus = 0x0C,
.card_status = 0x5C,
.sq_read_base_addr_a0 = 0x6C,
.sq_read_base_addr_a1 = 0x6D,
.card_revision = 0xC8,
.card_fw_status0 = 0x88,
.card_fw_status1 = 0x89,
.card_rx_len = 0x8A,
.card_rx_unit = 0x8B,
.io_port_0 = 0xE4,
.io_port_1 = 0xE5,
.io_port_2 = 0xE6,
.int_read_to_clear = true,
.host_int_rsr = 0x04,
.card_misc_cfg = 0xD8,
};
static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
.cfg = 0x00, .cfg = 0x00,
.host_int_mask = 0x02, .host_int_mask = 0x02,
.host_intstatus = 0x03, .host_intstatus = 0x03,
...@@ -128,10 +148,18 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { ...@@ -128,10 +148,18 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
.helper = NULL,
.firmware = "mrvl/sd8887_uapsta.bin",
.reg = &btmrvl_reg_8887,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin", .firmware = "mrvl/sd8897_uapsta.bin",
.reg = &btmrvl_reg_88xx, .reg = &btmrvl_reg_8897,
.support_pscan_win_report = true, .support_pscan_win_report = true,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -149,6 +177,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { ...@@ -149,6 +177,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8797 Bluetooth device */ /* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, .driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
/* Marvell SD8887 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136),
.driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
/* Marvell SD8897 Bluetooth device */ /* Marvell SD8897 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
.driver_data = (unsigned long) &btmrvl_sdio_sd8897 }, .driver_data = (unsigned long) &btmrvl_sdio_sd8897 },
...@@ -1280,4 +1311,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); ...@@ -1280,4 +1311,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
MODULE_FIRMWARE("mrvl/sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
...@@ -268,8 +268,6 @@ struct btusb_data { ...@@ -268,8 +268,6 @@ struct btusb_data {
struct usb_interface *intf; struct usb_interface *intf;
struct usb_interface *isoc; struct usb_interface *isoc;
spinlock_t lock;
unsigned long flags; unsigned long flags;
struct work_struct work; struct work_struct work;
...@@ -2002,8 +2000,6 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -2002,8 +2000,6 @@ static int btusb_probe(struct usb_interface *intf,
data->udev = interface_to_usbdev(intf); data->udev = interface_to_usbdev(intf);
data->intf = intf; data->intf = intf;
spin_lock_init(&data->lock);
INIT_WORK(&data->work, btusb_work); INIT_WORK(&data->work, btusb_work);
INIT_WORK(&data->waker, btusb_waker); INIT_WORK(&data->waker, btusb_waker);
init_usb_anchor(&data->deferred); init_usb_anchor(&data->deferred);
......
...@@ -426,38 +426,33 @@ static void convert_dest_bdaddr(struct in6_addr *ip6_daddr, ...@@ -426,38 +426,33 @@ static void convert_dest_bdaddr(struct in6_addr *ip6_daddr,
*addr_type = get_addr_type_from_eui64(addr->b[5]); *addr_type = get_addr_type_from_eui64(addr->b[5]);
} }
static int header_create(struct sk_buff *skb, struct net_device *netdev, static int setup_header(struct sk_buff *skb, struct net_device *netdev,
unsigned short type, const void *_daddr, bdaddr_t *peer_addr, u8 *peer_addr_type)
const void *_saddr, unsigned int len)
{ {
struct ipv6hdr *hdr; struct in6_addr ipv6_daddr;
struct lowpan_dev *dev; struct lowpan_dev *dev;
struct lowpan_peer *peer; struct lowpan_peer *peer;
bdaddr_t addr, *any = BDADDR_ANY; bdaddr_t addr, *any = BDADDR_ANY;
u8 *saddr, *daddr = any->b; u8 *daddr = any->b;
u8 addr_type; int err, status = 0;
if (type != ETH_P_IPV6)
return -EINVAL;
hdr = ipv6_hdr(skb);
dev = lowpan_dev(netdev); dev = lowpan_dev(netdev);
if (ipv6_addr_is_multicast(&hdr->daddr)) { memcpy(&ipv6_daddr, &lowpan_cb(skb)->addr, sizeof(ipv6_daddr));
memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
sizeof(struct in6_addr)); if (ipv6_addr_is_multicast(&ipv6_daddr)) {
lowpan_cb(skb)->chan = NULL; lowpan_cb(skb)->chan = NULL;
} else { } else {
unsigned long flags; unsigned long flags;
u8 addr_type;
/* Get destination BT device from skb. /* Get destination BT device from skb.
* If there is no such peer then discard the packet. * If there is no such peer then discard the packet.
*/ */
convert_dest_bdaddr(&hdr->daddr, &addr, &addr_type); convert_dest_bdaddr(&ipv6_daddr, &addr, &addr_type);
BT_DBG("dest addr %pMR type %d IP %pI6c", &addr, BT_DBG("dest addr %pMR type %d IP %pI6c", &addr,
addr_type, &hdr->daddr); addr_type, &ipv6_daddr);
read_lock_irqsave(&devices_lock, flags); read_lock_irqsave(&devices_lock, flags);
peer = peer_lookup_ba(dev, &addr, addr_type); peer = peer_lookup_ba(dev, &addr, addr_type);
...@@ -470,7 +465,7 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev, ...@@ -470,7 +465,7 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
* the destination address. * the destination address.
*/ */
read_lock_irqsave(&devices_lock, flags); read_lock_irqsave(&devices_lock, flags);
peer = peer_lookup_dst(dev, &hdr->daddr, skb); peer = peer_lookup_dst(dev, &ipv6_daddr, skb);
read_unlock_irqrestore(&devices_lock, flags); read_unlock_irqrestore(&devices_lock, flags);
if (!peer) { if (!peer) {
BT_DBG("no such peer %pMR found", &addr); BT_DBG("no such peer %pMR found", &addr);
...@@ -479,15 +474,37 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev, ...@@ -479,15 +474,37 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
} }
daddr = peer->eui64_addr; daddr = peer->eui64_addr;
*peer_addr = addr;
memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, *peer_addr_type = addr_type;
sizeof(struct in6_addr));
lowpan_cb(skb)->chan = peer->chan; lowpan_cb(skb)->chan = peer->chan;
status = 1;
} }
saddr = dev->netdev->dev_addr; lowpan_header_compress(skb, netdev, ETH_P_IPV6, daddr,
dev->netdev->dev_addr, skb->len);
err = dev_hard_header(skb, netdev, ETH_P_IPV6, NULL, NULL, 0);
if (err < 0)
return err;
return lowpan_header_compress(skb, netdev, type, daddr, saddr, len); return status;
}
static int header_create(struct sk_buff *skb, struct net_device *netdev,
unsigned short type, const void *_daddr,
const void *_saddr, unsigned int len)
{
struct ipv6hdr *hdr;
if (type != ETH_P_IPV6)
return -EINVAL;
hdr = ipv6_hdr(skb);
memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, sizeof(struct in6_addr));
return 0;
} }
/* Packet to BT LE device */ /* Packet to BT LE device */
...@@ -529,11 +546,12 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb, ...@@ -529,11 +546,12 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb,
return err; return err;
} }
static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
{ {
struct sk_buff *local_skb; struct sk_buff *local_skb;
struct lowpan_dev *entry, *tmp; struct lowpan_dev *entry, *tmp;
unsigned long flags; unsigned long flags;
int err = 0;
read_lock_irqsave(&devices_lock, flags); read_lock_irqsave(&devices_lock, flags);
...@@ -547,57 +565,77 @@ static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) ...@@ -547,57 +565,77 @@ static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
dev = lowpan_dev(entry->netdev); dev = lowpan_dev(entry->netdev);
list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) { list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) {
int ret;
local_skb = skb_clone(skb, GFP_ATOMIC); local_skb = skb_clone(skb, GFP_ATOMIC);
send_pkt(pentry->chan, local_skb, netdev); BT_DBG("xmit %s to %pMR type %d IP %pI6c chan %p",
netdev->name,
&pentry->chan->dst, pentry->chan->dst_type,
&pentry->peer_addr, pentry->chan);
ret = send_pkt(pentry->chan, local_skb, netdev);
if (ret < 0)
err = ret;
kfree_skb(local_skb); kfree_skb(local_skb);
} }
} }
read_unlock_irqrestore(&devices_lock, flags); read_unlock_irqrestore(&devices_lock, flags);
return err;
} }
static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
{ {
int err = 0; int err = 0;
struct lowpan_dev *dev;
struct lowpan_peer *peer;
bdaddr_t addr; bdaddr_t addr;
u8 addr_type; u8 addr_type;
struct sk_buff *tmpskb;
if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) { /* We must take a copy of the skb before we modify/replace the ipv6
/* We need to send the packet to every device * header as the header could be used elsewhere
* behind this interface.
*/ */
send_mcast_pkt(skb, netdev); tmpskb = skb_unshare(skb, GFP_ATOMIC);
} else { if (!tmpskb) {
unsigned long flags; kfree_skb(skb);
return NET_XMIT_DROP;
convert_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type); }
dev = lowpan_dev(netdev); skb = tmpskb;
read_lock_irqsave(&devices_lock, flags); /* Return values from setup_header()
peer = peer_lookup_ba(dev, &addr, addr_type); * <0 - error, packet is dropped
if (!peer) * 0 - this is a multicast packet
peer = peer_lookup_dst(dev, &lowpan_cb(skb)->addr, skb); * 1 - this is unicast packet
read_unlock_irqrestore(&devices_lock, flags); */
err = setup_header(skb, netdev, &addr, &addr_type);
if (err < 0) {
kfree_skb(skb);
return NET_XMIT_DROP;
}
BT_DBG("xmit %s to %pMR type %d IP %pI6c peer %p", if (err) {
if (lowpan_cb(skb)->chan) {
BT_DBG("xmit %s to %pMR type %d IP %pI6c chan %p",
netdev->name, &addr, addr_type, netdev->name, &addr, addr_type,
&lowpan_cb(skb)->addr, peer); &lowpan_cb(skb)->addr, lowpan_cb(skb)->chan);
err = send_pkt(lowpan_cb(skb)->chan, skb, netdev);
if (peer && peer->chan) } else {
err = send_pkt(peer->chan, skb, netdev);
else
err = -ENOENT; err = -ENOENT;
} }
} else {
/* We need to send the packet to every device behind this
* interface.
*/
err = send_mcast_pkt(skb, netdev);
}
dev_kfree_skb(skb); dev_kfree_skb(skb);
if (err) if (err)
BT_DBG("ERROR: xmit failed (%d)", err); BT_DBG("ERROR: xmit failed (%d)", err);
return (err < 0) ? NET_XMIT_DROP : err; return err < 0 ? NET_XMIT_DROP : err;
} }
static const struct net_device_ops netdev_ops = { static const struct net_device_ops netdev_ops = {
...@@ -617,7 +655,8 @@ static void netdev_setup(struct net_device *dev) ...@@ -617,7 +655,8 @@ static void netdev_setup(struct net_device *dev)
dev->needed_tailroom = 0; dev->needed_tailroom = 0;
dev->mtu = IPV6_MIN_MTU; dev->mtu = IPV6_MIN_MTU;
dev->tx_queue_len = 0; dev->tx_queue_len = 0;
dev->flags = IFF_RUNNING | IFF_POINTOPOINT; dev->flags = IFF_RUNNING | IFF_POINTOPOINT |
IFF_MULTICAST;
dev->watchdog_timeo = 0; dev->watchdog_timeo = 0;
dev->netdev_ops = &netdev_ops; dev->netdev_ops = &netdev_ops;
...@@ -950,6 +989,9 @@ static void chan_suspend_cb(struct l2cap_chan *chan) ...@@ -950,6 +989,9 @@ static void chan_suspend_cb(struct l2cap_chan *chan)
BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb); BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb);
if (!skb)
return;
lowpan_cb(skb)->status = -EAGAIN; lowpan_cb(skb)->status = -EAGAIN;
} }
...@@ -959,6 +1001,9 @@ static void chan_resume_cb(struct l2cap_chan *chan) ...@@ -959,6 +1001,9 @@ static void chan_resume_cb(struct l2cap_chan *chan)
BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb); BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb);
if (!skb)
return;
lowpan_cb(skb)->status = 0; lowpan_cb(skb)->status = 0;
} }
......
...@@ -6980,8 +6980,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, ...@@ -6980,8 +6980,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
hci_dev_lock(hdev); hci_dev_lock(hdev);
l2cap_chan_lock(chan);
if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
chan->chan_type != L2CAP_CHAN_RAW) { chan->chan_type != L2CAP_CHAN_RAW) {
err = -EINVAL; err = -EINVAL;
...@@ -7078,17 +7076,20 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, ...@@ -7078,17 +7076,20 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
goto done; goto done;
} }
mutex_lock(&conn->chan_lock);
l2cap_chan_lock(chan);
if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
hci_conn_drop(hcon); hci_conn_drop(hcon);
err = -EBUSY; err = -EBUSY;
goto done; goto chan_unlock;
} }
/* Update source addr of the socket */ /* Update source addr of the socket */
bacpy(&chan->src, &hcon->src); bacpy(&chan->src, &hcon->src);
chan->src_type = bdaddr_type(hcon, hcon->src_type); chan->src_type = bdaddr_type(hcon, hcon->src_type);
l2cap_chan_add(conn, chan); __l2cap_chan_add(conn, chan);
/* l2cap_chan_add takes its own ref so we can drop this one */ /* l2cap_chan_add takes its own ref so we can drop this one */
hci_conn_drop(hcon); hci_conn_drop(hcon);
...@@ -7114,8 +7115,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, ...@@ -7114,8 +7115,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
err = 0; err = 0;
done: chan_unlock:
l2cap_chan_unlock(chan); l2cap_chan_unlock(chan);
mutex_unlock(&conn->chan_lock);
done:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment