Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

Merge branch 'for-upstream' of...

parents 574a7930 9c238ca8
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -201,7 +201,7 @@ config BT_MRVL
	  The core driver to support Marvell Bluetooth devices.

	  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
	  into the kernel or say M to compile it as module.
@@ -214,7 +214,7 @@ config BT_MRVL_SDIO
	  The driver for Marvell Bluetooth chipsets with SDIO interface.

	  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.

	  Say Y here to compile support for Marvell BT-over-SDIO driver
+34 −2
Original line number Diff line number Diff line
@@ -84,7 +84,27 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
	.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,
	.host_int_mask = 0x02,
	.host_intstatus = 0x03,
@@ -128,10 +148,18 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
	.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 = {
	.helper		= NULL,
	.firmware	= "mrvl/sd8897_uapsta.bin",
	.reg		= &btmrvl_reg_88xx,
	.reg		= &btmrvl_reg_8897,
	.support_pscan_win_report = true,
	.sd_blksz_fw_dl	= 256,
};
@@ -149,6 +177,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
	/* Marvell SD8797 Bluetooth device */
	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
			.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 */
	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
			.driver_data = (unsigned long) &btmrvl_sdio_sd8897 },
@@ -1280,4 +1311,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
MODULE_FIRMWARE("mrvl/sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
+0 −4
Original line number Diff line number Diff line
@@ -268,8 +268,6 @@ struct btusb_data {
	struct usb_interface *intf;
	struct usb_interface *isoc;

	spinlock_t lock;

	unsigned long flags;

	struct work_struct work;
@@ -2002,8 +2000,6 @@ static int btusb_probe(struct usb_interface *intf,
	data->udev = interface_to_usbdev(intf);
	data->intf = intf;

	spin_lock_init(&data->lock);

	INIT_WORK(&data->work, btusb_work);
	INIT_WORK(&data->waker, btusb_waker);
	init_usb_anchor(&data->deferred);
+95 −50
Original line number Diff line number Diff line
@@ -426,38 +426,33 @@ static void convert_dest_bdaddr(struct in6_addr *ip6_daddr,
	*addr_type = get_addr_type_from_eui64(addr->b[5]);
}

static int header_create(struct sk_buff *skb, struct net_device *netdev,
		         unsigned short type, const void *_daddr,
		         const void *_saddr, unsigned int len)
static int setup_header(struct sk_buff *skb, struct net_device *netdev,
			bdaddr_t *peer_addr, u8 *peer_addr_type)
{
	struct ipv6hdr *hdr;
	struct in6_addr ipv6_daddr;
	struct lowpan_dev *dev;
	struct lowpan_peer *peer;
	bdaddr_t addr, *any = BDADDR_ANY;
	u8 *saddr, *daddr = any->b;
	u8 addr_type;

	if (type != ETH_P_IPV6)
		return -EINVAL;

	hdr = ipv6_hdr(skb);
	u8 *daddr = any->b;
	int err, status = 0;

	dev = lowpan_dev(netdev);

	if (ipv6_addr_is_multicast(&hdr->daddr)) {
		memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
		       sizeof(struct in6_addr));
	memcpy(&ipv6_daddr, &lowpan_cb(skb)->addr, sizeof(ipv6_daddr));

	if (ipv6_addr_is_multicast(&ipv6_daddr)) {
		lowpan_cb(skb)->chan = NULL;
	} else {
		unsigned long flags;
		u8 addr_type;

		/* Get destination BT device from skb.
		 * 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,
		       addr_type, &hdr->daddr);
		       addr_type, &ipv6_daddr);

		read_lock_irqsave(&devices_lock, flags);
		peer = peer_lookup_ba(dev, &addr, addr_type);
@@ -470,7 +465,7 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
			 * the destination address.
			 */
			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);
			if (!peer) {
				BT_DBG("no such peer %pMR found", &addr);
@@ -479,15 +474,37 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
		}

		daddr = peer->eui64_addr;

		memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
		       sizeof(struct in6_addr));
		*peer_addr = addr;
		*peer_addr_type = addr_type;
		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 */
@@ -529,11 +546,12 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb,
	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 lowpan_dev *entry, *tmp;
	unsigned long flags;
	int err = 0;

	read_lock_irqsave(&devices_lock, flags);

@@ -547,57 +565,77 @@ static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
		dev = lowpan_dev(entry->netdev);

		list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) {
			int ret;

			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);
		}
	}

	read_unlock_irqrestore(&devices_lock, flags);

	return err;
}

static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
{
	int err = 0;
	struct lowpan_dev *dev;
	struct lowpan_peer *peer;
	bdaddr_t addr;
	u8 addr_type;
	struct sk_buff *tmpskb;

	if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) {
		/* We need to send the packet to every device
		 * behind this interface.
	/* We must take a copy of the skb before we modify/replace the ipv6
	 * header as the header could be used elsewhere
	 */
		send_mcast_pkt(skb, netdev);
	} else {
		unsigned long flags;

		convert_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
		dev = lowpan_dev(netdev);
	tmpskb = skb_unshare(skb, GFP_ATOMIC);
	if (!tmpskb) {
		kfree_skb(skb);
		return NET_XMIT_DROP;
	}
	skb = tmpskb;

		read_lock_irqsave(&devices_lock, flags);
		peer = peer_lookup_ba(dev, &addr, addr_type);
		if (!peer)
			peer = peer_lookup_dst(dev, &lowpan_cb(skb)->addr, skb);
		read_unlock_irqrestore(&devices_lock, flags);
	/* Return values from setup_header()
	 *  <0 - error, packet is dropped
	 *   0 - this is a multicast packet
	 *   1 - this is unicast packet
	 */
	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,
		       &lowpan_cb(skb)->addr, peer);

		if (peer && peer->chan)
			err = send_pkt(peer->chan, skb, netdev);
		else
			       &lowpan_cb(skb)->addr, lowpan_cb(skb)->chan);
			err = send_pkt(lowpan_cb(skb)->chan, skb, netdev);
		} else {
			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);

	if (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 = {
@@ -617,7 +655,8 @@ static void netdev_setup(struct net_device *dev)
	dev->needed_tailroom	= 0;
	dev->mtu		= IPV6_MIN_MTU;
	dev->tx_queue_len	= 0;
	dev->flags		= IFF_RUNNING | IFF_POINTOPOINT;
	dev->flags		= IFF_RUNNING | IFF_POINTOPOINT |
				  IFF_MULTICAST;
	dev->watchdog_timeo	= 0;

	dev->netdev_ops		= &netdev_ops;
@@ -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);

	if (!skb)
		return;

	lowpan_cb(skb)->status = -EAGAIN;
}

@@ -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);

	if (!skb)
		return;

	lowpan_cb(skb)->status = 0;
}

+8 −5
Original line number Diff line number Diff line
@@ -6980,8 +6980,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,

	hci_dev_lock(hdev);

	l2cap_chan_lock(chan);

	if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
	    chan->chan_type != L2CAP_CHAN_RAW) {
		err = -EINVAL;
@@ -7078,17 +7076,20 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
		goto done;
	}

	mutex_lock(&conn->chan_lock);
	l2cap_chan_lock(chan);

	if (cid && __l2cap_get_chan_by_dcid(conn, cid)) {
		hci_conn_drop(hcon);
		err = -EBUSY;
		goto done;
		goto chan_unlock;
	}

	/* Update source addr of the socket */
	bacpy(&chan->src, &hcon->src);
	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 */
	hci_conn_drop(hcon);
@@ -7114,8 +7115,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,

	err = 0;

done:
chan_unlock:
	l2cap_chan_unlock(chan);
	mutex_unlock(&conn->chan_lock);
done:
	hci_dev_unlock(hdev);
	hci_dev_put(hdev);
	return err;