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

Commit 4309e092 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (94 commits)
  pkt_sched: Prevent livelock in TX queue running.
  Revert "pkt_sched: Add BH protection for qdisc_stab_lock."
  Revert "pkt_sched: Protect gen estimators under est_lock."
  pkt_sched: remove bogus block (cleanup)
  nf_nat: use secure_ipv4_port_ephemeral() for NAT port randomization
  netfilter: ctnetlink: sleepable allocation with spin lock bh
  netfilter: ctnetlink: fix sleep in read-side lock section
  netfilter: ctnetlink: fix double helper assignation for NAT'ed conntracks
  netfilter: ipt_addrtype: Fix matching of inverted destination address type
  dccp: Fix panic caused by too early termination of retransmission mechanism
  pkt_sched: Don't hold qdisc lock over qdisc_destroy().
  pkt_sched: Add lockdep annotation for qdisc locks
  pkt_sched: Never schedule non-root qdiscs.
  removed unused #include <version.h>
  rt2x00: Fix txdone_entry_desc_flags
  b43: Fix for another Bluetooth Coexistence SPROM Programming error for BCM4306
  mac80211: remove kdoc references to IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE
  p54u: reset skb's data/tail pointer on requeue
  p54: move p54_vdcf_init to the right place.
  iwlwifi: fix printk newlines
  ...
parents 1fca2542 195648bb
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -363,6 +363,11 @@ This rule exists because users of the rfkill subsystem expect to get (and set,
when possible) the overall transmitter rfkill state, not of a particular rfkill
line.

5. During suspend, the rfkill class will attempt to soft-block the radio
through a call to rfkill->toggle_radio, and will try to restore its previous
state during resume.  After a rfkill class is suspended, it will *not* call
rfkill->toggle_radio until it is resumed.

Example of a WLAN wireless driver connected to the rfkill subsystem:
--------------------------------------------------------------------

+6 −81
Original line number Diff line number Diff line
@@ -942,94 +942,19 @@ M: joern@lazybastard.org
L:	linux-mtd@lists.infradead.org
S:	Maintained

BLUETOOTH SUBSYSTEM
BLUETOOTH DRIVERS
P:	Marcel Holtmann
M:	marcel@holtmann.org
P:	Maxim Krasnyansky
M:	maxk@qualcomm.com
L:	linux-bluetooth@vger.kernel.org
W:	http://bluez.sf.net
W:	http://www.bluez.org
W:	http://www.holtmann.org/linux/bluetooth/
T:	git kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git
S:	Maintained

BLUETOOTH RFCOMM LAYER
P:	Marcel Holtmann
M:	marcel@holtmann.org
P:	Maxim Krasnyansky
M:	maxk@qualcomm.com
S:	Maintained

BLUETOOTH BNEP LAYER
P:	Marcel Holtmann
M:	marcel@holtmann.org
P:	Maxim Krasnyansky
M:	maxk@qualcomm.com
S:	Maintained

BLUETOOTH CMTP LAYER
P:	Marcel Holtmann
M:	marcel@holtmann.org
W:	http://www.bluez.org/
S:	Maintained

BLUETOOTH HIDP LAYER
P:	Marcel Holtmann
M:	marcel@holtmann.org
S:	Maintained

BLUETOOTH HCI UART DRIVER
P:	Marcel Holtmann
M:	marcel@holtmann.org
P:	Maxim Krasnyansky
M:	maxk@qualcomm.com
S:	Maintained

BLUETOOTH HCI USB DRIVER
P:	Marcel Holtmann
M:	marcel@holtmann.org
P:	Maxim Krasnyansky
M:	maxk@qualcomm.com
S:	Maintained

BLUETOOTH HCI BCM203X DRIVER
P:	Marcel Holtmann
M:	marcel@holtmann.org
S:	Maintained

BLUETOOTH HCI BPA10X DRIVER
P:	Marcel Holtmann
M:	marcel@holtmann.org
S:	Maintained

BLUETOOTH HCI BFUSB DRIVER
P:	Marcel Holtmann
M:	marcel@holtmann.org
S:	Maintained

BLUETOOTH HCI DTL1 DRIVER
P:	Marcel Holtmann
M:	marcel@holtmann.org
S:	Maintained

BLUETOOTH HCI BLUECARD DRIVER
P:	Marcel Holtmann
M:	marcel@holtmann.org
S:	Maintained

BLUETOOTH HCI BT3C DRIVER
P:	Marcel Holtmann
M:	marcel@holtmann.org
S:	Maintained

BLUETOOTH HCI BTUART DRIVER
BLUETOOTH SUBSYSTEM
P:	Marcel Holtmann
M:	marcel@holtmann.org
S:	Maintained

BLUETOOTH HCI VHCI DRIVER
P:	Maxim Krasnyansky
M:	maxk@qualcomm.com
L:	linux-bluetooth@vger.kernel.org
W:	http://www.bluez.org/
T:	git kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git
S:	Maintained

BONDING DRIVER
+4 −6
Original line number Diff line number Diff line
@@ -3,8 +3,8 @@ menu "Bluetooth device drivers"
	depends on BT

config BT_HCIUSB
	tristate "HCI USB driver"
	depends on USB
	tristate "HCI USB driver (old version)"
	depends on USB && BT_HCIBTUSB=n
	help
	  Bluetooth HCI USB driver.
	  This driver is required if you want to use Bluetooth devices with
@@ -23,15 +23,13 @@ config BT_HCIUSB_SCO
	  Say Y here to compile support for SCO over HCI USB.

config BT_HCIBTUSB
	tristate "HCI USB driver (alternate version)"
	depends on USB && EXPERIMENTAL && BT_HCIUSB=n
	tristate "HCI USB driver"
	depends on USB
	help
	  Bluetooth HCI USB driver.
	  This driver is required if you want to use Bluetooth devices with
	  USB interface.

          This driver is still experimental and has no SCO support.

	  Say Y here to compile support for Bluetooth USB devices into the
	  kernel or say M to compile it as module (btusb).

+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@
/* ======================== Module parameters ======================== */


MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>");
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("BT3CPCC.bin");
+268 −14
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 *
 *  Generic Bluetooth USB driver
 *
 *  Copyright (C) 2005-2007  Marcel Holtmann <marcel@holtmann.org>
 *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@
#define BT_DBG(D...)
#endif

#define VERSION "0.2"
#define VERSION "0.3"

static int ignore_dga;
static int ignore_csr;
@@ -160,12 +160,16 @@ static struct usb_device_id blacklist_table[] = {
	{ }	/* Terminating entry */
};

#define BTUSB_MAX_ISOC_FRAMES	10

#define BTUSB_INTR_RUNNING	0
#define BTUSB_BULK_RUNNING	1
#define BTUSB_ISOC_RUNNING	2

struct btusb_data {
	struct hci_dev       *hdev;
	struct usb_device    *udev;
	struct usb_interface *isoc;

	spinlock_t lock;

@@ -176,10 +180,15 @@ struct btusb_data {
	struct usb_anchor tx_anchor;
	struct usb_anchor intr_anchor;
	struct usb_anchor bulk_anchor;
	struct usb_anchor isoc_anchor;

	struct usb_endpoint_descriptor *intr_ep;
	struct usb_endpoint_descriptor *bulk_tx_ep;
	struct usb_endpoint_descriptor *bulk_rx_ep;
	struct usb_endpoint_descriptor *isoc_tx_ep;
	struct usb_endpoint_descriptor *isoc_rx_ep;

	int isoc_altsetting;
};

static void btusb_intr_complete(struct urb *urb)
@@ -195,6 +204,8 @@ static void btusb_intr_complete(struct urb *urb)
		return;

	if (urb->status == 0) {
		hdev->stat.byte_rx += urb->actual_length;

		if (hci_recv_fragment(hdev, HCI_EVENT_PKT,
						urb->transfer_buffer,
						urb->actual_length) < 0) {
@@ -216,7 +227,7 @@ static void btusb_intr_complete(struct urb *urb)
	}
}

static inline int btusb_submit_intr_urb(struct hci_dev *hdev)
static int btusb_submit_intr_urb(struct hci_dev *hdev)
{
	struct btusb_data *data = hdev->driver_data;
	struct urb *urb;
@@ -226,6 +237,9 @@ static inline int btusb_submit_intr_urb(struct hci_dev *hdev)

	BT_DBG("%s", hdev->name);

	if (!data->intr_ep)
		return -ENODEV;

	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb)
		return -ENOMEM;
@@ -274,6 +288,8 @@ static void btusb_bulk_complete(struct urb *urb)
		return;

	if (urb->status == 0) {
		hdev->stat.byte_rx += urb->actual_length;

		if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT,
						urb->transfer_buffer,
						urb->actual_length) < 0) {
@@ -295,7 +311,7 @@ static void btusb_bulk_complete(struct urb *urb)
	}
}

static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
static int btusb_submit_bulk_urb(struct hci_dev *hdev)
{
	struct btusb_data *data = hdev->driver_data;
	struct urb *urb;
@@ -305,6 +321,9 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)

	BT_DBG("%s", hdev->name);

	if (!data->bulk_rx_ep)
		return -ENODEV;

	urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!urb)
		return -ENOMEM;
@@ -339,6 +358,127 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev)
	return err;
}

static void btusb_isoc_complete(struct urb *urb)
{
	struct hci_dev *hdev = urb->context;
	struct btusb_data *data = hdev->driver_data;
	int i, err;

	BT_DBG("%s urb %p status %d count %d", hdev->name,
					urb, urb->status, urb->actual_length);

	if (!test_bit(HCI_RUNNING, &hdev->flags))
		return;

	if (urb->status == 0) {
		for (i = 0; i < urb->number_of_packets; i++) {
			unsigned int offset = urb->iso_frame_desc[i].offset;
			unsigned int length = urb->iso_frame_desc[i].actual_length;

			if (urb->iso_frame_desc[i].status)
				continue;

			hdev->stat.byte_rx += length;

			if (hci_recv_fragment(hdev, HCI_SCODATA_PKT,
						urb->transfer_buffer + offset,
								length) < 0) {
				BT_ERR("%s corrupted SCO packet", hdev->name);
				hdev->stat.err_rx++;
			}
		}
	}

	if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
		return;

	usb_anchor_urb(urb, &data->isoc_anchor);

	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (err < 0) {
		BT_ERR("%s urb %p failed to resubmit (%d)",
						hdev->name, urb, -err);
		usb_unanchor_urb(urb);
	}
}

static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
{
	int i, offset = 0;

	BT_DBG("len %d mtu %d", len, mtu);

	for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu;
					i++, offset += mtu, len -= mtu) {
		urb->iso_frame_desc[i].offset = offset;
		urb->iso_frame_desc[i].length = mtu;
	}

	if (len && i < BTUSB_MAX_ISOC_FRAMES) {
		urb->iso_frame_desc[i].offset = offset;
		urb->iso_frame_desc[i].length = len;
		i++;
	}

	urb->number_of_packets = i;
}

static int btusb_submit_isoc_urb(struct hci_dev *hdev)
{
	struct btusb_data *data = hdev->driver_data;
	struct urb *urb;
	unsigned char *buf;
	unsigned int pipe;
	int err, size;

	BT_DBG("%s", hdev->name);

	if (!data->isoc_rx_ep)
		return -ENODEV;

	urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
	if (!urb)
		return -ENOMEM;

	size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) *
						BTUSB_MAX_ISOC_FRAMES;

	buf = kmalloc(size, GFP_KERNEL);
	if (!buf) {
		usb_free_urb(urb);
		return -ENOMEM;
	}

	pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);

	urb->dev      = data->udev;
	urb->pipe     = pipe;
	urb->context  = hdev;
	urb->complete = btusb_isoc_complete;
	urb->interval = data->isoc_rx_ep->bInterval;

	urb->transfer_flags  = URB_FREE_BUFFER | URB_ISO_ASAP;
	urb->transfer_buffer = buf;
	urb->transfer_buffer_length = size;

	__fill_isoc_descriptor(urb, size,
			le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));

	usb_anchor_urb(urb, &data->isoc_anchor);

	err = usb_submit_urb(urb, GFP_KERNEL);
	if (err < 0) {
		BT_ERR("%s urb %p submission failed (%d)",
						hdev->name, urb, -err);
		usb_unanchor_urb(urb);
		kfree(buf);
	}

	usb_free_urb(urb);

	return err;
}

static void btusb_tx_complete(struct urb *urb)
{
	struct sk_buff *skb = urb->context;
@@ -392,6 +532,9 @@ static int btusb_close(struct hci_dev *hdev)
	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
		return 0;

	clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
	usb_kill_anchored_urbs(&data->intr_anchor);

	clear_bit(BTUSB_BULK_RUNNING, &data->flags);
	usb_kill_anchored_urbs(&data->bulk_anchor);

@@ -453,6 +596,9 @@ static int btusb_send_frame(struct sk_buff *skb)
		break;

	case HCI_ACLDATA_PKT:
		if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1)
			return -ENODEV;

		urb = usb_alloc_urb(0, GFP_ATOMIC);
		if (!urb)
			return -ENOMEM;
@@ -467,9 +613,31 @@ static int btusb_send_frame(struct sk_buff *skb)
		break;

	case HCI_SCODATA_PKT:
		if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1)
			return -ENODEV;

		urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC);
		if (!urb)
			return -ENOMEM;

		pipe = usb_sndisocpipe(data->udev,
					data->isoc_tx_ep->bEndpointAddress);

		urb->dev      = data->udev;
		urb->pipe     = pipe;
		urb->context  = skb;
		urb->complete = btusb_tx_complete;
		urb->interval = data->isoc_tx_ep->bInterval;

		urb->transfer_flags  = URB_ISO_ASAP;
		urb->transfer_buffer = skb->data;
		urb->transfer_buffer_length = skb->len;

		__fill_isoc_descriptor(urb, skb->len,
				le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));

		hdev->stat.sco_tx++;
		kfree_skb(skb);
		return 0;
		break;

	default:
		return -EILSEQ;
@@ -508,22 +676,86 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
		schedule_work(&data->work);
}

static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
{
	struct btusb_data *data = hdev->driver_data;
	struct usb_interface *intf = data->isoc;
	struct usb_endpoint_descriptor *ep_desc;
	int i, err;

	if (!data->isoc)
		return -ENODEV;

	err = usb_set_interface(data->udev, 1, altsetting);
	if (err < 0) {
		BT_ERR("%s setting interface failed (%d)", hdev->name, -err);
		return err;
	}

	data->isoc_altsetting = altsetting;

	data->isoc_tx_ep = NULL;
	data->isoc_rx_ep = NULL;

	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
		ep_desc = &intf->cur_altsetting->endpoint[i].desc;

		if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
			data->isoc_tx_ep = ep_desc;
			continue;
		}

		if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
			data->isoc_rx_ep = ep_desc;
			continue;
		}
	}

	if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
		BT_ERR("%s invalid SCO descriptors", hdev->name);
		return -ENODEV;
	}

	return 0;
}

static void btusb_work(struct work_struct *work)
{
	struct btusb_data *data = container_of(work, struct btusb_data, work);
	struct hci_dev *hdev = data->hdev;

	if (hdev->conn_hash.acl_num == 0) {
	if (hdev->conn_hash.acl_num > 0) {
		if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
			if (btusb_submit_bulk_urb(hdev) < 0)
				clear_bit(BTUSB_BULK_RUNNING, &data->flags);
			else
				btusb_submit_bulk_urb(hdev);
		}
	} else {
		clear_bit(BTUSB_BULK_RUNNING, &data->flags);
		usb_kill_anchored_urbs(&data->bulk_anchor);
	}

	if (hdev->conn_hash.sco_num > 0) {
		if (data->isoc_altsetting != 2) {
			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
			usb_kill_anchored_urbs(&data->isoc_anchor);

			if (__set_isoc_interface(hdev, 2) < 0)
				return;
		}

	if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) {
		if (btusb_submit_bulk_urb(hdev) < 0)
			clear_bit(BTUSB_BULK_RUNNING, &data->flags);
		if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
			if (btusb_submit_isoc_urb(hdev) < 0)
				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
			else
			btusb_submit_bulk_urb(hdev);
				btusb_submit_isoc_urb(hdev);
		}
	} else {
		clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
		usb_kill_anchored_urbs(&data->isoc_anchor);

		__set_isoc_interface(hdev, 0);
	}
}

@@ -597,6 +829,7 @@ static int btusb_probe(struct usb_interface *intf,
	init_usb_anchor(&data->tx_anchor);
	init_usb_anchor(&data->intr_anchor);
	init_usb_anchor(&data->bulk_anchor);
	init_usb_anchor(&data->isoc_anchor);

	hdev = hci_alloc_dev();
	if (!hdev) {
@@ -620,6 +853,9 @@ static int btusb_probe(struct usb_interface *intf,

	hdev->owner = THIS_MODULE;

	/* interface numbers are hardcoded in the spec */
	data->isoc = usb_ifnum_to_if(data->udev, 1);

	if (reset || id->driver_info & BTUSB_RESET)
		set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);

@@ -628,11 +864,16 @@ static int btusb_probe(struct usb_interface *intf,
			set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
	}

	if (id->driver_info & BTUSB_BROKEN_ISOC)
		data->isoc = NULL;

	if (id->driver_info & BTUSB_SNIFFER) {
		struct usb_device *udev = interface_to_usbdev(intf);
		struct usb_device *udev = data->udev;

		if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
			set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);

		data->isoc = NULL;
	}

	if (id->driver_info & BTUSB_BCM92035) {
@@ -646,6 +887,16 @@ static int btusb_probe(struct usb_interface *intf,
		}
	}

	if (data->isoc) {
		err = usb_driver_claim_interface(&btusb_driver,
							data->isoc, NULL);
		if (err < 0) {
			hci_free_dev(hdev);
			kfree(data);
			return err;
		}
	}

	err = hci_register_dev(hdev);
	if (err < 0) {
		hci_free_dev(hdev);
@@ -670,6 +921,9 @@ static void btusb_disconnect(struct usb_interface *intf)

	hdev = data->hdev;

	if (data->isoc)
		usb_driver_release_interface(&btusb_driver, data->isoc);

	usb_set_intfdata(intf, NULL);

	hci_unregister_dev(hdev);
Loading