diff options
Diffstat (limited to 'drivers/bluetooth')
| -rw-r--r-- | drivers/bluetooth/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/bluetooth/Makefile | 2 | ||||
| -rw-r--r-- | drivers/bluetooth/ath3k.c | 98 | ||||
| -rw-r--r-- | drivers/bluetooth/bfusb.c | 45 | ||||
| -rw-r--r-- | drivers/bluetooth/bluecard_cs.c | 41 | ||||
| -rw-r--r-- | drivers/bluetooth/bpa10x.c | 11 | ||||
| -rw-r--r-- | drivers/bluetooth/bt3c_cs.c | 37 | ||||
| -rw-r--r-- | drivers/bluetooth/btmrvl_drv.h | 29 | ||||
| -rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 273 | ||||
| -rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 117 | ||||
| -rw-r--r-- | drivers/bluetooth/btmrvl_sdio.h | 3 | ||||
| -rw-r--r-- | drivers/bluetooth/btsdio.c | 12 | ||||
| -rw-r--r-- | drivers/bluetooth/btuart_cs.c | 36 | ||||
| -rw-r--r-- | drivers/bluetooth/btusb.c | 280 | ||||
| -rw-r--r-- | drivers/bluetooth/btwilink.c | 9 | ||||
| -rw-r--r-- | drivers/bluetooth/dtl1_cs.c | 39 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_bcsp.c | 36 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_h4.c | 31 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_h5.c | 13 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 45 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_ll.c | 14 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_uart.h | 1 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_vhci.c | 203 | 
23 files changed, 837 insertions, 541 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 11a6104a1e4..f5ce64e03fd 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -241,5 +241,6 @@ config BT_WILINK  	  core driver to communicate with the BT core of the combo chip.  	  Say Y here to compile support for Texas Instrument's WiLink7 driver -	  into the kernel or say M to compile it as module. +	  into the kernel or say M to compile it as module (btwilink). +  endmenu diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 4afae20df51..9fe8a875a82 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -30,3 +30,5 @@ hci_uart-$(CONFIG_BT_HCIUART_LL)	+= hci_ll.o  hci_uart-$(CONFIG_BT_HCIUART_ATH3K)	+= hci_ath.o  hci_uart-$(CONFIG_BT_HCIUART_3WIRE)	+= hci_h5.o  hci_uart-objs				:= $(hci_uart-y) + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 0a327f4154a..f50dffc0374 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -57,52 +57,59 @@ struct ath3k_version {  	unsigned char	reserved[0x07];  }; -static struct usb_device_id ath3k_table[] = { +static const struct usb_device_id ath3k_table[] = {  	/* Atheros AR3011 */  	{ USB_DEVICE(0x0CF3, 0x3000) },  	/* Atheros AR3011 with sflash firmware*/ +	{ USB_DEVICE(0x0489, 0xE027) }, +	{ USB_DEVICE(0x0489, 0xE03D) }, +	{ USB_DEVICE(0x0930, 0x0215) },  	{ USB_DEVICE(0x0CF3, 0x3002) },  	{ USB_DEVICE(0x0CF3, 0xE019) },  	{ USB_DEVICE(0x13d3, 0x3304) }, -	{ USB_DEVICE(0x0930, 0x0215) }, -	{ USB_DEVICE(0x0489, 0xE03D) }, -	{ USB_DEVICE(0x0489, 0xE027) },  	/* Atheros AR9285 Malbec with sflash firmware */  	{ USB_DEVICE(0x03F0, 0x311D) },  	/* Atheros AR3012 with sflash firmware*/ +	{ USB_DEVICE(0x0489, 0xe04d) }, +	{ USB_DEVICE(0x0489, 0xe04e) }, +	{ USB_DEVICE(0x0489, 0xe057) }, +	{ USB_DEVICE(0x0489, 0xe056) }, +	{ USB_DEVICE(0x0489, 0xe05f) }, +	{ USB_DEVICE(0x04c5, 0x1330) }, +	{ USB_DEVICE(0x04CA, 0x3004) }, +	{ USB_DEVICE(0x04CA, 0x3005) }, +	{ USB_DEVICE(0x04CA, 0x3006) }, +	{ USB_DEVICE(0x04CA, 0x3007) }, +	{ USB_DEVICE(0x04CA, 0x3008) }, +	{ USB_DEVICE(0x04CA, 0x300b) }, +	{ USB_DEVICE(0x0930, 0x0219) }, +	{ USB_DEVICE(0x0930, 0x0220) }, +	{ USB_DEVICE(0x0b05, 0x17d0) },  	{ USB_DEVICE(0x0CF3, 0x0036) },  	{ USB_DEVICE(0x0CF3, 0x3004) },  	{ USB_DEVICE(0x0CF3, 0x3008) },  	{ USB_DEVICE(0x0CF3, 0x311D) }, +	{ USB_DEVICE(0x0CF3, 0x311E) }, +	{ USB_DEVICE(0x0CF3, 0x311F) }, +	{ USB_DEVICE(0x0cf3, 0x3121) },  	{ USB_DEVICE(0x0CF3, 0x817a) }, -	{ USB_DEVICE(0x13d3, 0x3375) }, -	{ USB_DEVICE(0x04CA, 0x3004) }, -	{ USB_DEVICE(0x04CA, 0x3005) }, -	{ USB_DEVICE(0x04CA, 0x3006) }, -	{ USB_DEVICE(0x04CA, 0x3008) }, -	{ USB_DEVICE(0x13d3, 0x3362) }, +	{ USB_DEVICE(0x0cf3, 0xe003) },  	{ USB_DEVICE(0x0CF3, 0xE004) },  	{ USB_DEVICE(0x0CF3, 0xE005) }, -	{ USB_DEVICE(0x0930, 0x0219) }, -	{ USB_DEVICE(0x0489, 0xe057) }, +	{ USB_DEVICE(0x13d3, 0x3362) }, +	{ USB_DEVICE(0x13d3, 0x3375) },  	{ USB_DEVICE(0x13d3, 0x3393) }, -	{ USB_DEVICE(0x0489, 0xe04e) }, -	{ USB_DEVICE(0x0489, 0xe056) }, -	{ USB_DEVICE(0x0489, 0xe04d) }, -	{ USB_DEVICE(0x04c5, 0x1330) },  	{ USB_DEVICE(0x13d3, 0x3402) }, -	{ USB_DEVICE(0x0cf3, 0x3121) }, -	{ USB_DEVICE(0x0cf3, 0xe003) },  	/* Atheros AR5BBU12 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xE02C) },  	/* Atheros AR5BBU22 with sflash firmware */ -	{ USB_DEVICE(0x0489, 0xE03C) },  	{ USB_DEVICE(0x0489, 0xE036) }, +	{ USB_DEVICE(0x0489, 0xE03C) },  	{ }	/* Terminating entry */  }; @@ -112,36 +119,43 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);  #define BTUSB_ATH3012		0x80  /* This table is to load patch and sysconfig files   * for AR3012 */ -static struct usb_device_id ath3k_blist_tbl[] = { +static const struct usb_device_id ath3k_blist_tbl[] = {  	/* Atheros AR3012 with sflash firmware*/ +	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },  	/* Atheros AR5BBU22 with sflash firmware */ -	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },  	{ }	/* Terminating entry */  }; @@ -168,19 +182,19 @@ static int ath3k_load_firmware(struct usb_device *udev,  	}  	memcpy(send_buf, firmware->data, 20); -	if ((err = usb_control_msg(udev, pipe, -				USB_REQ_DFU_DNLOAD, -				USB_TYPE_VENDOR, 0, 0, -				send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { +	err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR, +			      0, 0, send_buf, 20, USB_CTRL_SET_TIMEOUT); +	if (err < 0) {  		BT_ERR("Can't change to loading configuration err");  		goto error;  	}  	sent += 20;  	count -= 20; +	pipe = usb_sndbulkpipe(udev, 0x02); +  	while (count) {  		size = min_t(uint, count, BULK_SIZE); -		pipe = usb_sndbulkpipe(udev, 0x02);  		memcpy(send_buf, firmware->data + sent, size);  		err = usb_bulk_msg(udev, pipe, send_buf, size, @@ -354,7 +368,7 @@ static int ath3k_load_patch(struct usb_device *udev)  	}  	snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", -		fw_version.rom_version); +		le32_to_cpu(fw_version.rom_version));  	ret = request_firmware(&firmware, filename, &udev->dev);  	if (ret < 0) { @@ -416,7 +430,7 @@ static int ath3k_load_syscfg(struct usb_device *udev)  	}  	snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", -		fw_version.rom_version, clk_value, ".dfu"); +		le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");  	ret = request_firmware(&firmware, filename, &udev->dev);  	if (ret < 0) { diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 995aee9cba2..b2e7e94a677 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -42,7 +42,7 @@  static struct usb_driver bfusb_driver; -static struct usb_device_id bfusb_table[] = { +static const struct usb_device_id bfusb_table[] = {  	/* AVM BlueFRITZ! USB */  	{ USB_DEVICE(0x057c, 0x2200) }, @@ -131,8 +131,11 @@ static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)  	BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len); -	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC))) -		return -ENOMEM; +	if (!urb) { +		urb = usb_alloc_urb(0, GFP_ATOMIC); +		if (!urb) +			return -ENOMEM; +	}  	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep); @@ -218,8 +221,11 @@ static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)  	BT_DBG("bfusb %p urb %p", data, urb); -	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC))) -		return -ENOMEM; +	if (!urb) { +		urb = usb_alloc_urb(0, GFP_ATOMIC); +		if (!urb) +			return -ENOMEM; +	}  	skb = bt_skb_alloc(size, GFP_ATOMIC);  	if (!skb) { @@ -318,7 +324,6 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch  			return -ENOMEM;  		} -		skb->dev = (void *) data->hdev;  		bt_cb(skb)->pkt_type = pkt_type;  		data->reassembly = skb; @@ -333,7 +338,7 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch  		memcpy(skb_put(data->reassembly, len), buf, len);  	if (hdr & 0x08) { -		hci_recv_frame(data->reassembly); +		hci_recv_frame(data->hdev, data->reassembly);  		data->reassembly = NULL;  	} @@ -465,26 +470,18 @@ static int bfusb_close(struct hci_dev *hdev)  	return 0;  } -static int bfusb_send_frame(struct sk_buff *skb) +static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	struct hci_dev *hdev = (struct hci_dev *) skb->dev; -	struct bfusb_data *data; +	struct bfusb_data *data = hci_get_drvdata(hdev);  	struct sk_buff *nskb;  	unsigned char buf[3];  	int sent = 0, size, count;  	BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len); -	if (!hdev) { -		BT_ERR("Frame for unknown HCI device (hdev=NULL)"); -		return -ENODEV; -	} -  	if (!test_bit(HCI_RUNNING, &hdev->flags))  		return -EBUSY; -	data = hci_get_drvdata(hdev); -  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT:  		hdev->stat.cmd_tx++; @@ -544,11 +541,6 @@ static int bfusb_send_frame(struct sk_buff *skb)  	return 0;  } -static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) -{ -	return -ENOIOCTLCMD; -} -  static int bfusb_load_firmware(struct bfusb_data *data,  			       const unsigned char *firmware, int count)  { @@ -699,11 +691,10 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i  	hci_set_drvdata(hdev, data);  	SET_HCIDEV_DEV(hdev, &intf->dev); -	hdev->open     = bfusb_open; -	hdev->close    = bfusb_close; -	hdev->flush    = bfusb_flush; -	hdev->send     = bfusb_send_frame; -	hdev->ioctl    = bfusb_ioctl; +	hdev->open  = bfusb_open; +	hdev->close = bfusb_close; +	hdev->flush = bfusb_flush; +	hdev->send  = bfusb_send_frame;  	if (hci_register_dev(hdev) < 0) {  		BT_ERR("Can't register HCI device"); diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 6c3e3d43c71..dfa5043e68b 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -257,7 +257,8 @@ static void bluecard_write_wakeup(bluecard_info_t *info)  			ready_bit = XMIT_BUF_ONE_READY;  		} -		if (!(skb = skb_dequeue(&(info->txq)))) +		skb = skb_dequeue(&(info->txq)); +		if (!skb)  			break;  		if (bt_cb(skb)->pkt_type & 0x80) { @@ -391,7 +392,8 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)  		if (info->rx_skb == NULL) {  			info->rx_state = RECV_WAIT_PACKET_TYPE;  			info->rx_count = 0; -			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { +			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); +			if (!info->rx_skb) {  				BT_ERR("Can't allocate mem for new packet");  				return;  			} @@ -399,7 +401,6 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)  		if (info->rx_state == RECV_WAIT_PACKET_TYPE) { -			info->rx_skb->dev = (void *) info->hdev;  			bt_cb(info->rx_skb)->pkt_type = buf[i];  			switch (bt_cb(info->rx_skb)->pkt_type) { @@ -477,7 +478,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)  					break;  				case RECV_WAIT_DATA: -					hci_recv_frame(info->rx_skb); +					hci_recv_frame(info->hdev, info->rx_skb);  					info->rx_skb = NULL;  					break; @@ -567,7 +568,8 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)  	/* Ericsson baud rate command */  	unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; -	if (!(skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { +	skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); +	if (!skb) {  		BT_ERR("Can't allocate mem for new packet");  		return -1;  	} @@ -659,17 +661,9 @@ static int bluecard_hci_close(struct hci_dev *hdev)  } -static int bluecard_hci_send_frame(struct sk_buff *skb) +static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	bluecard_info_t *info; -	struct hci_dev *hdev = (struct hci_dev *)(skb->dev); - -	if (!hdev) { -		BT_ERR("Frame for unknown HCI device (hdev=NULL)"); -		return -ENODEV; -	} - -	info = hci_get_drvdata(hdev); +	bluecard_info_t *info = hci_get_drvdata(hdev);  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT: @@ -693,12 +687,6 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)  } -static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -  /* ======================== Card services HCI interaction ======================== */ @@ -734,11 +722,10 @@ static int bluecard_open(bluecard_info_t *info)  	hci_set_drvdata(hdev, info);  	SET_HCIDEV_DEV(hdev, &info->p_dev->dev); -	hdev->open     = bluecard_hci_open; -	hdev->close    = bluecard_hci_close; -	hdev->flush    = bluecard_hci_flush; -	hdev->send     = bluecard_hci_send_frame; -	hdev->ioctl    = bluecard_hci_ioctl; +	hdev->open  = bluecard_hci_open; +	hdev->close = bluecard_hci_close; +	hdev->flush = bluecard_hci_flush; +	hdev->send  = bluecard_hci_send_frame;  	id = inb(iobase + 0x30); @@ -914,7 +901,7 @@ static void bluecard_release(struct pcmcia_device *link)  	bluecard_close(info); -	del_timer(&(info->timer)); +	del_timer_sync(&(info->timer));  	pcmcia_disable_device(link);  } diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 2fe4a803134..8a319913c9a 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -37,7 +37,7 @@  #define VERSION "0.10" -static struct usb_device_id bpa10x_table[] = { +static const struct usb_device_id bpa10x_table[] = {  	/* Tektronix BPA 100/105 (Digianswer) */  	{ USB_DEVICE(0x08fd, 0x0002) }, @@ -129,8 +129,6 @@ static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)  				return -ENOMEM;  			} -			skb->dev = (void *) hdev; -  			data->rx_skb[queue] = skb;  			scb = (void *) skb->cb; @@ -155,7 +153,7 @@ static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)  			data->rx_skb[queue] = NULL;  			bt_cb(skb)->pkt_type = scb->type; -			hci_recv_frame(skb); +			hci_recv_frame(hdev, skb);  		}  		count -= len; buf += len; @@ -352,9 +350,8 @@ static int bpa10x_flush(struct hci_dev *hdev)  	return 0;  } -static int bpa10x_send_frame(struct sk_buff *skb) +static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	struct hci_dev *hdev = (struct hci_dev *) skb->dev;  	struct bpa10x_data *data = hci_get_drvdata(hdev);  	struct usb_ctrlrequest *dr;  	struct urb *urb; @@ -366,6 +363,8 @@ static int bpa10x_send_frame(struct sk_buff *skb)  	if (!test_bit(HCI_RUNNING, &hdev->flags))  		return -EBUSY; +	skb->dev = (void *) hdev; +  	urb = usb_alloc_urb(0, GFP_ATOMIC);  	if (!urb)  		return -ENOMEM; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index a1aaa3ba2a4..1d82721cf9c 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -193,8 +193,8 @@ static void bt3c_write_wakeup(bt3c_info_t *info)  		if (!pcmcia_dev_present(info->p_dev))  			break; - -		if (!(skb = skb_dequeue(&(info->txq)))) { +		skb = skb_dequeue(&(info->txq)); +		if (!skb) {  			clear_bit(XMIT_SENDING, &(info->tx_state));  			break;  		} @@ -238,7 +238,8 @@ static void bt3c_receive(bt3c_info_t *info)  		if (info->rx_skb == NULL) {  			info->rx_state = RECV_WAIT_PACKET_TYPE;  			info->rx_count = 0; -			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { +			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); +			if (!info->rx_skb) {  				BT_ERR("Can't allocate mem for new packet");  				return;  			} @@ -247,7 +248,6 @@ static void bt3c_receive(bt3c_info_t *info)  		if (info->rx_state == RECV_WAIT_PACKET_TYPE) { -			info->rx_skb->dev = (void *) info->hdev;  			bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L);  			inb(iobase + DATA_H);  			//printk("bt3c: PACKET_TYPE=%02x\n", bt_cb(info->rx_skb)->pkt_type); @@ -318,7 +318,7 @@ static void bt3c_receive(bt3c_info_t *info)  					break;  				case RECV_WAIT_DATA: -					hci_recv_frame(info->rx_skb); +					hci_recv_frame(info->hdev, info->rx_skb);  					info->rx_skb = NULL;  					break; @@ -416,19 +416,11 @@ static int bt3c_hci_close(struct hci_dev *hdev)  } -static int bt3c_hci_send_frame(struct sk_buff *skb) +static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	bt3c_info_t *info; -	struct hci_dev *hdev = (struct hci_dev *)(skb->dev); +	bt3c_info_t *info = hci_get_drvdata(hdev);  	unsigned long flags; -	if (!hdev) { -		BT_ERR("Frame for unknown HCI device (hdev=NULL)"); -		return -ENODEV; -	} - -	info = hci_get_drvdata(hdev); -  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT:  		hdev->stat.cmd_tx++; @@ -455,12 +447,6 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)  } -static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -  /* ======================== Card services HCI interaction ======================== */ @@ -577,11 +563,10 @@ static int bt3c_open(bt3c_info_t *info)  	hci_set_drvdata(hdev, info);  	SET_HCIDEV_DEV(hdev, &info->p_dev->dev); -	hdev->open     = bt3c_hci_open; -	hdev->close    = bt3c_hci_close; -	hdev->flush    = bt3c_hci_flush; -	hdev->send     = bt3c_hci_send_frame; -	hdev->ioctl    = bt3c_hci_ioctl; +	hdev->open  = bt3c_hci_open; +	hdev->close = bt3c_hci_close; +	hdev->flush = bt3c_hci_flush; +	hdev->send  = bt3c_hci_send_frame;  	/* Load firmware */  	err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev); diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 27068d14938..dc79f88f871 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -59,6 +59,8 @@ struct btmrvl_device {  };  struct btmrvl_adapter { +	void *hw_regs_buf; +	u8 *hw_regs;  	u32 int_count;  	struct sk_buff_head tx_queue;  	u8 psmode; @@ -86,11 +88,12 @@ struct btmrvl_private {  #define MRVL_VENDOR_PKT			0xFE -/* Bluetooth commands  */ -#define BT_CMD_AUTO_SLEEP_MODE		0x23 -#define BT_CMD_HOST_SLEEP_CONFIG	0x59 -#define BT_CMD_HOST_SLEEP_ENABLE	0x5A -#define BT_CMD_MODULE_CFG_REQ		0x5B +/* Vendor specific Bluetooth commands */ +#define BT_CMD_AUTO_SLEEP_MODE		0xFC23 +#define BT_CMD_HOST_SLEEP_CONFIG	0xFC59 +#define BT_CMD_HOST_SLEEP_ENABLE	0xFC5A +#define BT_CMD_MODULE_CFG_REQ		0xFC5B +#define BT_CMD_LOAD_CONFIG_DATA		0xFC61  /* Sub-commands: Module Bringup/Shutdown Request/Response */  #define MODULE_BRINGUP_REQ		0xF1 @@ -99,6 +102,11 @@ struct btmrvl_private {  #define MODULE_SHUTDOWN_REQ		0xF2 +/* Vendor specific Bluetooth events */ +#define BT_EVENT_AUTO_SLEEP_MODE	0x23 +#define BT_EVENT_HOST_SLEEP_CONFIG	0x59 +#define BT_EVENT_HOST_SLEEP_ENABLE	0x5A +#define BT_EVENT_MODULE_CFG_REQ		0x5B  #define BT_EVENT_POWER_STATE		0x20  /* Bluetooth Power States */ @@ -106,8 +114,6 @@ struct btmrvl_private {  #define BT_PS_DISABLE			0x03  #define BT_PS_SLEEP			0x01 -#define OGF				0x3F -  /* Host Sleep states */  #define HS_ACTIVATED			0x01  #define HS_DEACTIVATED			0x00 @@ -116,11 +122,8 @@ struct btmrvl_private {  #define PS_SLEEP			0x01  #define PS_AWAKE			0x00 -struct btmrvl_cmd { -	__le16 ocf_ogf; -	u8 length; -	u8 data[4]; -} __packed; +#define BT_CAL_HDR_LEN			4 +#define BT_CAL_DATA_SIZE		28  struct btmrvl_event {  	u8 ec;		/* event counter */ @@ -139,7 +142,7 @@ void btmrvl_interrupt(struct btmrvl_private *priv);  bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);  int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); -int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd); +int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd);  int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);  int btmrvl_enable_ps(struct btmrvl_private *priv);  int btmrvl_prepare_command(struct btmrvl_private *priv); diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 9a9f51875df..e9dbddb0b8f 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -19,11 +19,12 @@   **/  #include <linux/module.h> - +#include <linux/of.h>  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h>  #include "btmrvl_drv.h" +#include "btmrvl_sdio.h"  #define VERSION "1.0" @@ -50,25 +51,22 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)  	if (hdr->evt == HCI_EV_CMD_COMPLETE) {  		struct hci_ev_cmd_complete *ec; -		u16 opcode, ocf, ogf; +		u16 opcode;  		ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);  		opcode = __le16_to_cpu(ec->opcode); -		ocf = hci_opcode_ocf(opcode); -		ogf = hci_opcode_ogf(opcode); -		if (ocf == BT_CMD_MODULE_CFG_REQ && -					priv->btmrvl_dev.sendcmdflag) { +		if (priv->btmrvl_dev.sendcmdflag) {  			priv->btmrvl_dev.sendcmdflag = false;  			priv->adapter->cmd_complete = true;  			wake_up_interruptible(&priv->adapter->cmd_wait_q); -		} -		if (ogf == OGF) { -			BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x", -			       ogf, ocf); -			kfree_skb(skb); -			return false; +			if (hci_opcode_ogf(opcode) == 0x3F) { +				BT_DBG("vendor event skipped: opcode=%#4.4x", +				       opcode); +				kfree_skb(skb); +				return false; +			}  		}  	} @@ -90,7 +88,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)  	}  	switch (event->data[0]) { -	case BT_CMD_AUTO_SLEEP_MODE: +	case BT_EVENT_AUTO_SLEEP_MODE:  		if (!event->data[2]) {  			if (event->data[1] == BT_PS_ENABLE)  				adapter->psmode = 1; @@ -103,7 +101,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)  		}  		break; -	case BT_CMD_HOST_SLEEP_CONFIG: +	case BT_EVENT_HOST_SLEEP_CONFIG:  		if (!event->data[3])  			BT_DBG("gpio=%x, gap=%x", event->data[1],  							event->data[2]); @@ -111,19 +109,18 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)  			BT_DBG("HSCFG command failed");  		break; -	case BT_CMD_HOST_SLEEP_ENABLE: +	case BT_EVENT_HOST_SLEEP_ENABLE:  		if (!event->data[1]) {  			adapter->hs_state = HS_ACTIVATED;  			if (adapter->psmode)  				adapter->ps_state = PS_SLEEP; -			wake_up_interruptible(&adapter->cmd_wait_q);  			BT_DBG("HS ACTIVATED!");  		} else {  			BT_DBG("HS Enable failed");  		}  		break; -	case BT_CMD_MODULE_CFG_REQ: +	case BT_EVENT_MODULE_CFG_REQ:  		if (priv->btmrvl_dev.sendcmdflag &&  				event->data[1] == MODULE_BRINGUP_REQ) {  			BT_DBG("EVENT:%s", @@ -168,45 +165,50 @@ exit:  }  EXPORT_SYMBOL_GPL(btmrvl_process_event); -int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) +static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode, +				const void *param, u8 len)  {  	struct sk_buff *skb; -	struct btmrvl_cmd *cmd; -	int ret = 0; +	struct hci_command_hdr *hdr; -	skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); +	skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC);  	if (skb == NULL) {  		BT_ERR("No free skb");  		return -ENOMEM;  	} -	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); -	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_MODULE_CFG_REQ)); -	cmd->length = 1; -	cmd->data[0] = subcmd; +	hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE); +	hdr->opcode = cpu_to_le16(opcode); +	hdr->plen = len; + +	if (len) +		memcpy(skb_put(skb, len), param, len);  	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; -	skb->dev = (void *) priv->btmrvl_dev.hcidev;  	skb_queue_head(&priv->adapter->tx_queue, skb);  	priv->btmrvl_dev.sendcmdflag = true;  	priv->adapter->cmd_complete = false; -	BT_DBG("Queue module cfg Command"); -  	wake_up_interruptible(&priv->main_thread.wait_q);  	if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,  				priv->adapter->cmd_complete, -				msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) { -		ret = -ETIMEDOUT; -		BT_ERR("module_cfg_cmd(%x): timeout: %d", -					subcmd, priv->btmrvl_dev.sendcmdflag); -	} +				msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) +		return -ETIMEDOUT; + +	return 0; +} + +int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd) +{ +	int ret; -	BT_DBG("module cfg Command done"); +	ret = btmrvl_send_sync_cmd(priv, BT_CMD_MODULE_CFG_REQ, &subcmd, 1); +	if (ret) +		BT_ERR("module_cfg_cmd(%x) failed\n", subcmd);  	return ret;  } @@ -214,61 +216,36 @@ EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);  int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)  { -	struct sk_buff *skb; -	struct btmrvl_cmd *cmd; - -	skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); -	if (!skb) { -		BT_ERR("No free skb"); -		return -ENOMEM; -	} - -	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); -	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, -						   BT_CMD_HOST_SLEEP_CONFIG)); -	cmd->length = 2; -	cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; -	cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); +	int ret; +	u8 param[2]; -	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; +	param[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; +	param[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); -	skb->dev = (void *) priv->btmrvl_dev.hcidev; -	skb_queue_head(&priv->adapter->tx_queue, skb); +	BT_DBG("Sending HSCFG Command, gpio=0x%x, gap=0x%x", +	       param[0], param[1]); -	BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0], -	       cmd->data[1]); +	ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, 2); +	if (ret) +		BT_ERR("HSCFG command failed\n"); -	return 0; +	return ret;  }  EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd);  int btmrvl_enable_ps(struct btmrvl_private *priv)  { -	struct sk_buff *skb; -	struct btmrvl_cmd *cmd; - -	skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); -	if (skb == NULL) { -		BT_ERR("No free skb"); -		return -ENOMEM; -	} - -	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); -	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, -					BT_CMD_AUTO_SLEEP_MODE)); -	cmd->length = 1; +	int ret; +	u8 param;  	if (priv->btmrvl_dev.psmode) -		cmd->data[0] = BT_PS_ENABLE; +		param = BT_PS_ENABLE;  	else -		cmd->data[0] = BT_PS_DISABLE; - -	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; +		param = BT_PS_DISABLE; -	skb->dev = (void *) priv->btmrvl_dev.hcidev; -	skb_queue_head(&priv->adapter->tx_queue, skb); - -	BT_DBG("Queue PSMODE Command:%d", cmd->data[0]); +	ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, ¶m, 1); +	if (ret) +		BT_ERR("PSMODE command failed\n");  	return 0;  } @@ -276,37 +253,11 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps);  int btmrvl_enable_hs(struct btmrvl_private *priv)  { -	struct sk_buff *skb; -	struct btmrvl_cmd *cmd; -	int ret = 0; - -	skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); -	if (skb == NULL) { -		BT_ERR("No free skb"); -		return -ENOMEM; -	} - -	cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); -	cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_ENABLE)); -	cmd->length = 0; - -	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; - -	skb->dev = (void *) priv->btmrvl_dev.hcidev; -	skb_queue_head(&priv->adapter->tx_queue, skb); - -	BT_DBG("Queue hs enable Command"); +	int ret; -	wake_up_interruptible(&priv->main_thread.wait_q); - -	if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q, -			priv->adapter->hs_state, -			msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED))) { -		ret = -ETIMEDOUT; -		BT_ERR("timeout: %d, %d,%d", priv->adapter->hs_state, -						priv->adapter->ps_state, -						priv->adapter->wakeup_tries); -	} +	ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0); +	if (ret) +		BT_ERR("Host sleep enable command failed\n");  	return ret;  } @@ -387,10 +338,25 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)  static void btmrvl_init_adapter(struct btmrvl_private *priv)  { +	int buf_size; +  	skb_queue_head_init(&priv->adapter->tx_queue);  	priv->adapter->ps_state = PS_AWAKE; +	buf_size = ALIGN_SZ(SDIO_BLOCK_SIZE, BTSDIO_DMA_ALIGN); +	priv->adapter->hw_regs_buf = kzalloc(buf_size, GFP_KERNEL); +	if (!priv->adapter->hw_regs_buf) { +		priv->adapter->hw_regs = NULL; +		BT_ERR("Unable to allocate buffer for hw_regs."); +	} else { +		priv->adapter->hw_regs = +			(u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf, +					 BTSDIO_DMA_ALIGN); +		BT_DBG("hw_regs_buf=%p hw_regs=%p", +		       priv->adapter->hw_regs_buf, priv->adapter->hw_regs); +	} +  	init_waitqueue_head(&priv->adapter->cmd_wait_q);  } @@ -398,31 +364,18 @@ static void btmrvl_free_adapter(struct btmrvl_private *priv)  {  	skb_queue_purge(&priv->adapter->tx_queue); +	kfree(priv->adapter->hw_regs_buf);  	kfree(priv->adapter);  	priv->adapter = NULL;  } -static int btmrvl_ioctl(struct hci_dev *hdev, -				unsigned int cmd, unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -static int btmrvl_send_frame(struct sk_buff *skb) +static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	struct hci_dev *hdev = (struct hci_dev *) skb->dev; -	struct btmrvl_private *priv = NULL; +	struct btmrvl_private *priv = hci_get_drvdata(hdev);  	BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len); -	if (!hdev) { -		BT_ERR("Frame for unknown HCI device"); -		return -ENODEV; -	} - -	priv = hci_get_drvdata(hdev); -  	if (!test_bit(HCI_RUNNING, &hdev->flags)) {  		BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);  		print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET, @@ -479,6 +432,72 @@ static int btmrvl_open(struct hci_dev *hdev)  	return 0;  } +static int btmrvl_download_cal_data(struct btmrvl_private *priv, +				    u8 *data, int len) +{ +	int ret; + +	data[0] = 0x00; +	data[1] = 0x00; +	data[2] = 0x00; +	data[3] = len; + +	print_hex_dump_bytes("Calibration data: ", +			     DUMP_PREFIX_OFFSET, data, BT_CAL_HDR_LEN + len); + +	ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data, +				   BT_CAL_HDR_LEN + len); +	if (ret) +		BT_ERR("Failed to download caibration data\n"); + +	return 0; +} + +static int btmrvl_cal_data_dt(struct btmrvl_private *priv) +{ +	struct device_node *dt_node; +	u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE]; +	const char name[] = "btmrvl_caldata"; +	const char property[] = "btmrvl,caldata"; +	int ret; + +	dt_node = of_find_node_by_name(NULL, name); +	if (!dt_node) +		return -ENODEV; + +	ret = of_property_read_u8_array(dt_node, property, +					cal_data + BT_CAL_HDR_LEN, +					BT_CAL_DATA_SIZE); +	if (ret) +		return ret; + +	BT_DBG("Use cal data from device tree"); +	ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE); +	if (ret) { +		BT_ERR("Fail to download calibrate data"); +		return ret; +	} + +	return 0; +} + +static int btmrvl_setup(struct hci_dev *hdev) +{ +	struct btmrvl_private *priv = hci_get_drvdata(hdev); + +	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); + +	btmrvl_cal_data_dt(priv); + +	priv->btmrvl_dev.psmode = 1; +	btmrvl_enable_ps(priv); + +	priv->btmrvl_dev.gpio_gap = 0xffff; +	btmrvl_send_hscfg_cmd(priv); + +	return 0; +} +  /*   * This function handles the event generated by firmware, rx data   * received from firmware, and tx data sent from kernel. @@ -566,14 +585,12 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)  	priv->btmrvl_dev.hcidev = hdev;  	hci_set_drvdata(hdev, priv); -	hdev->bus = HCI_SDIO; -	hdev->open = btmrvl_open; +	hdev->bus   = HCI_SDIO; +	hdev->open  = btmrvl_open;  	hdev->close = btmrvl_close;  	hdev->flush = btmrvl_flush; -	hdev->send = btmrvl_send_frame; -	hdev->ioctl = btmrvl_ioctl; - -	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); +	hdev->send  = btmrvl_send_frame; +	hdev->setup = btmrvl_setup;  	hdev->dev_type = priv->btmrvl_dev.dev_type; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 00da6df9f71..9dedca516ff 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -64,6 +64,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {  	.io_port_0 = 0x00,  	.io_port_1 = 0x01,  	.io_port_2 = 0x02, +	.int_read_to_clear = false,  };  static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {  	.cfg = 0x00, @@ -80,6 +81,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {  	.io_port_0 = 0x78,  	.io_port_1 = 0x79,  	.io_port_2 = 0x7a, +	.int_read_to_clear = false,  };  static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = { @@ -97,6 +99,9 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {  	.io_port_0 = 0xd8,  	.io_port_1 = 0xd9,  	.io_port_2 = 0xda, +	.int_read_to_clear = true, +	.host_int_rsr = 0x01, +	.card_misc_cfg = 0xcc,  };  static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { @@ -597,15 +602,14 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)  	case HCI_SCODATA_PKT:  	case HCI_EVENT_PKT:  		bt_cb(skb)->pkt_type = type; -		skb->dev = (void *)hdev;  		skb_put(skb, buf_len);  		skb_pull(skb, SDIO_HEADER_LEN);  		if (type == HCI_EVENT_PKT) {  			if (btmrvl_check_evtpkt(priv, skb)) -				hci_recv_frame(skb); +				hci_recv_frame(hdev, skb);  		} else { -			hci_recv_frame(skb); +			hci_recv_frame(hdev, skb);  		}  		hdev->stat.byte_rx += buf_len; @@ -613,12 +617,11 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)  	case MRVL_VENDOR_PKT:  		bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; -		skb->dev = (void *)hdev;  		skb_put(skb, buf_len);  		skb_pull(skb, SDIO_HEADER_LEN);  		if (btmrvl_process_event(priv, skb)) -			hci_recv_frame(skb); +			hci_recv_frame(hdev, skb);  		hdev->stat.byte_rx += buf_len;  		break; @@ -669,46 +672,78 @@ static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)  	return 0;  } -static void btmrvl_sdio_interrupt(struct sdio_func *func) +static int btmrvl_sdio_read_to_clear(struct btmrvl_sdio_card *card, u8 *ireg)  { -	struct btmrvl_private *priv; -	struct btmrvl_sdio_card *card; -	ulong flags; -	u8 ireg = 0; +	struct btmrvl_adapter *adapter = card->priv->adapter;  	int ret; -	card = sdio_get_drvdata(func); -	if (!card || !card->priv) { -		BT_ERR("sbi_interrupt(%p) card or priv is " -				"NULL, card=%p\n", func, card); -		return; +	ret = sdio_readsb(card->func, adapter->hw_regs, 0, SDIO_BLOCK_SIZE); +	if (ret) { +		BT_ERR("sdio_readsb: read int hw_regs failed: %d", ret); +		return ret;  	} -	priv = card->priv; +	*ireg = adapter->hw_regs[card->reg->host_intstatus]; +	BT_DBG("hw_regs[%#x]=%#x", card->reg->host_intstatus, *ireg); -	ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret); +	return 0; +} + +static int btmrvl_sdio_write_to_clear(struct btmrvl_sdio_card *card, u8 *ireg) +{ +	int ret; + +	*ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);  	if (ret) { -		BT_ERR("sdio_readb: read int status register failed"); -		return; +		BT_ERR("sdio_readb: read int status failed: %d", ret); +		return ret;  	} -	if (ireg != 0) { +	if (*ireg) {  		/*  		 * 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); +		BT_DBG("int_status = 0x%x", *ireg); -		sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS | -					UP_LD_HOST_INT_STATUS), -				card->reg->host_intstatus, &ret); +		sdio_writeb(card->func, ~(*ireg) & (DN_LD_HOST_INT_STATUS | +						    UP_LD_HOST_INT_STATUS), +			    card->reg->host_intstatus, &ret);  		if (ret) { -			BT_ERR("sdio_writeb: clear int status register failed"); -			return; +			BT_ERR("sdio_writeb: clear int status failed: %d", ret); +			return ret;  		}  	} +	return 0; +} + +static void btmrvl_sdio_interrupt(struct sdio_func *func) +{ +	struct btmrvl_private *priv; +	struct btmrvl_sdio_card *card; +	ulong flags; +	u8 ireg = 0; +	int ret; + +	card = sdio_get_drvdata(func); +	if (!card || !card->priv) { +		BT_ERR("sbi_interrupt(%p) card or priv is " +				"NULL, card=%p\n", func, card); +		return; +	} + +	priv = card->priv; + +	if (card->reg->int_read_to_clear) +		ret = btmrvl_sdio_read_to_clear(card, &ireg); +	else +		ret = btmrvl_sdio_write_to_clear(card, &ireg); + +	if (ret) +		return; +  	spin_lock_irqsave(&priv->driver_lock, flags);  	sdio_ireg |= ireg;  	spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -779,6 +814,30 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)  	BT_DBG("SDIO FUNC%d IO port: 0x%x", func->num, card->ioport); +	if (card->reg->int_read_to_clear) { +		reg = sdio_readb(func, card->reg->host_int_rsr, &ret); +		if (ret < 0) { +			ret = -EIO; +			goto release_irq; +		} +		sdio_writeb(func, reg | 0x3f, card->reg->host_int_rsr, &ret); +		if (ret < 0) { +			ret = -EIO; +			goto release_irq; +		} + +		reg = sdio_readb(func, card->reg->card_misc_cfg, &ret); +		if (ret < 0) { +			ret = -EIO; +			goto release_irq; +		} +		sdio_writeb(func, reg | 0x10, card->reg->card_misc_cfg, &ret); +		if (ret < 0) { +			ret = -EIO; +			goto release_irq; +		} +	} +  	sdio_set_drvdata(func, card);  	sdio_release_host(func); @@ -1046,12 +1105,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,  		goto disable_host_int;  	} -	priv->btmrvl_dev.psmode = 1; -	btmrvl_enable_ps(priv); - -	priv->btmrvl_dev.gpio_gap = 0xffff; -	btmrvl_send_hscfg_cmd(priv); -  	return 0;  disable_host_int: diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h index 43d35a609ca..d4dd3b0fa53 100644 --- a/drivers/bluetooth/btmrvl_sdio.h +++ b/drivers/bluetooth/btmrvl_sdio.h @@ -78,6 +78,9 @@ struct btmrvl_sdio_card_reg {  	u8 io_port_0;  	u8 io_port_1;  	u8 io_port_2; +	bool int_read_to_clear; +	u8 host_int_rsr; +	u8 card_misc_cfg;  };  struct btmrvl_sdio_card { diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 4a990971387..83f6437dd91 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -73,6 +73,7 @@ struct btsdio_data {  #define REG_CL_INTRD 0x13	/* Interrupt Clear */  #define REG_EN_INTRD 0x14	/* Interrupt Enable */  #define REG_MD_STAT  0x20	/* Bluetooth Mode Status */ +#define REG_MD_SET   0x20	/* Bluetooth Mode Set */  static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)  { @@ -157,10 +158,9 @@ static int btsdio_rx_packet(struct btsdio_data *data)  	data->hdev->stat.byte_rx += len; -	skb->dev = (void *) data->hdev;  	bt_cb(skb)->pkt_type = hdr[3]; -	err = hci_recv_frame(skb); +	err = hci_recv_frame(data->hdev, skb);  	if (err < 0)  		return err; @@ -213,7 +213,7 @@ static int btsdio_open(struct hci_dev *hdev)  	}  	if (data->func->class == SDIO_CLASS_BT_B) -		sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL); +		sdio_writeb(data->func, 0x00, REG_MD_SET, NULL);  	sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL); @@ -255,9 +255,8 @@ static int btsdio_flush(struct hci_dev *hdev)  	return 0;  } -static int btsdio_send_frame(struct sk_buff *skb) +static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	struct hci_dev *hdev = (struct hci_dev *) skb->dev;  	struct btsdio_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s", hdev->name); @@ -335,6 +334,9 @@ static int btsdio_probe(struct sdio_func *func,  	hdev->flush    = btsdio_flush;  	hdev->send     = btsdio_send_frame; +	if (func->vendor == 0x0104 && func->device == 0x00c5) +		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); +  	err = hci_register_dev(hdev);  	if (err < 0) {  		hci_free_dev(hdev); diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index beb262f2dc4..fb948f02eda 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -149,7 +149,8 @@ static void btuart_write_wakeup(btuart_info_t *info)  		if (!pcmcia_dev_present(info->p_dev))  			return; -		if (!(skb = skb_dequeue(&(info->txq)))) +		skb = skb_dequeue(&(info->txq)); +		if (!skb)  			break;  		/* Send frame */ @@ -190,7 +191,8 @@ static void btuart_receive(btuart_info_t *info)  		if (info->rx_skb == NULL) {  			info->rx_state = RECV_WAIT_PACKET_TYPE;  			info->rx_count = 0; -			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { +			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); +			if (!info->rx_skb) {  				BT_ERR("Can't allocate mem for new packet");  				return;  			} @@ -198,7 +200,6 @@ static void btuart_receive(btuart_info_t *info)  		if (info->rx_state == RECV_WAIT_PACKET_TYPE) { -			info->rx_skb->dev = (void *) info->hdev;  			bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX);  			switch (bt_cb(info->rx_skb)->pkt_type) { @@ -265,7 +266,7 @@ static void btuart_receive(btuart_info_t *info)  					break;  				case RECV_WAIT_DATA: -					hci_recv_frame(info->rx_skb); +					hci_recv_frame(info->hdev, info->rx_skb);  					info->rx_skb = NULL;  					break; @@ -424,17 +425,9 @@ static int btuart_hci_close(struct hci_dev *hdev)  } -static int btuart_hci_send_frame(struct sk_buff *skb) +static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	btuart_info_t *info; -	struct hci_dev *hdev = (struct hci_dev *)(skb->dev); - -	if (!hdev) { -		BT_ERR("Frame for unknown HCI device (hdev=NULL)"); -		return -ENODEV; -	} - -	info = hci_get_drvdata(hdev); +	btuart_info_t *info = hci_get_drvdata(hdev);  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT: @@ -458,12 +451,6 @@ static int btuart_hci_send_frame(struct sk_buff *skb)  } -static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -  /* ======================== Card services HCI interaction ======================== */ @@ -495,11 +482,10 @@ static int btuart_open(btuart_info_t *info)  	hci_set_drvdata(hdev, info);  	SET_HCIDEV_DEV(hdev, &info->p_dev->dev); -	hdev->open     = btuart_hci_open; -	hdev->close    = btuart_hci_close; -	hdev->flush    = btuart_hci_flush; -	hdev->send     = btuart_hci_send_frame; -	hdev->ioctl    = btuart_hci_ioctl; +	hdev->open  = btuart_hci_open; +	hdev->close = btuart_hci_close; +	hdev->flush = btuart_hci_flush; +	hdev->send  = btuart_hci_send_frame;  	spin_lock_irqsave(&(info->lock), flags); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f3dfc0a88fd..6250fc2fb93 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -49,8 +49,9 @@ static struct usb_driver btusb_driver;  #define BTUSB_WRONG_SCO_MTU	0x40  #define BTUSB_ATH3012		0x80  #define BTUSB_INTEL		0x100 +#define BTUSB_BCM_PATCHRAM	0x200 -static struct usb_device_id btusb_table[] = { +static const struct usb_device_id btusb_table[] = {  	/* Generic Bluetooth USB device */  	{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, @@ -101,27 +102,31 @@ static struct usb_device_id btusb_table[] = {  	{ USB_DEVICE(0x0c10, 0x0000) },  	/* Broadcom BCM20702A0 */ +	{ USB_DEVICE(0x0489, 0xe042) }, +	{ USB_DEVICE(0x04ca, 0x2003) },  	{ USB_DEVICE(0x0b05, 0x17b5) },  	{ USB_DEVICE(0x0b05, 0x17cb) }, -	{ USB_DEVICE(0x04ca, 0x2003) }, -	{ USB_DEVICE(0x0489, 0xe042) },  	{ USB_DEVICE(0x413c, 0x8197) },  	/* Foxconn - Hon Hai */  	{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) }, -	/*Broadcom devices with vendor specific id */ -	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, +	/* Broadcom devices with vendor specific id */ +	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01), +	  .driver_info = BTUSB_BCM_PATCHRAM },  	/* Belkin F8065bf - Broadcom based */  	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, +	/* IMC Networks - Broadcom based */ +	{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) }, +  	{ }	/* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, btusb_table); -static struct usb_device_id blacklist_table[] = { +static const struct usb_device_id blacklist_table[] = {  	/* CSR BlueCore devices */  	{ USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR }, @@ -129,52 +134,59 @@ static struct usb_device_id blacklist_table[] = {  	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },  	/* Atheros 3011 with sflash firmware */ +	{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, +	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, +	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },  	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },  	{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },  	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, -	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, -	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, -	{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },  	/* Atheros AR9285 Malbec with sflash firmware */  	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },  	/* Atheros 3012 with sflash firmware */ +	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, -	{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },  	/* Atheros AR5BBU12 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },  	/* Atheros AR5BBU12 with sflash firmware */ -	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },  	/* Broadcom BCM2035 */ -	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, -	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },  	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, +	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, +	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },  	/* Broadcom BCM2045 */  	{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU }, @@ -223,6 +235,7 @@ static struct usb_device_id blacklist_table[] = {  	/* Intel Bluetooth device */  	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, +	{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },  	{ }	/* Terminating entry */  }; @@ -716,9 +729,8 @@ static int btusb_flush(struct hci_dev *hdev)  	return 0;  } -static int btusb_send_frame(struct sk_buff *skb) +static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	struct hci_dev *hdev = (struct hci_dev *) skb->dev;  	struct btusb_data *data = hci_get_drvdata(hdev);  	struct usb_ctrlrequest *dr;  	struct urb *urb; @@ -730,6 +742,8 @@ static int btusb_send_frame(struct sk_buff *skb)  	if (!test_bit(HCI_RUNNING, &hdev->flags))  		return -EBUSY; +	skb->dev = (void *) hdev; +  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT:  		urb = usb_alloc_urb(0, GFP_ATOMIC); @@ -774,7 +788,7 @@ 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) +		if (!data->isoc_tx_ep || hci_conn_num(hdev, SCO_LINK) < 1)  			return -ENODEV;  		urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); @@ -833,8 +847,8 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)  	BT_DBG("%s evt %d", hdev->name, evt); -	if (hdev->conn_hash.sco_num != data->sco_num) { -		data->sco_num = hdev->conn_hash.sco_num; +	if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) { +		data->sco_num = hci_conn_num(hdev, SCO_LINK);  		schedule_work(&data->work);  	}  } @@ -889,7 +903,7 @@ static void btusb_work(struct work_struct *work)  	int new_alts;  	int err; -	if (hdev->conn_hash.sco_num > 0) { +	if (data->sco_num > 0) {  		if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {  			err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf);  			if (err < 0) { @@ -903,9 +917,9 @@ static void btusb_work(struct work_struct *work)  		if (hdev->voice_setting & 0x0020) {  			static const int alts[3] = { 2, 4, 5 }; -			new_alts = alts[hdev->conn_hash.sco_num - 1]; +			new_alts = alts[data->sco_num - 1];  		} else { -			new_alts = hdev->conn_hash.sco_num; +			new_alts = data->sco_num;  		}  		if (data->isoc_altsetting != new_alts) { @@ -960,6 +974,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev)  	return 0;  } +static int btusb_setup_csr(struct hci_dev *hdev) +{ +	struct hci_rp_read_local_version *rp; +	struct sk_buff *skb; +	int ret; + +	BT_DBG("%s", hdev->name); + +	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, +			     HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb)); +		return -PTR_ERR(skb); +	} + +	rp = (struct hci_rp_read_local_version *) skb->data; + +	if (!rp->status) { +		if (le16_to_cpu(rp->manufacturer) != 10) { +			/* Clear the reset quirk since this is not an actual +			 * early Bluetooth 1.1 device from CSR. +			 */ +			clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + +			/* These fake CSR controllers have all a broken +			 * stored link key handling and so just disable it. +			 */ +			set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, +				&hdev->quirks); +		} +	} + +	ret = -bt_to_errno(rp->status); + +	kfree_skb(skb); + +	return ret; +} +  struct intel_version {  	u8 status;  	u8 hw_platform; @@ -1329,6 +1382,154 @@ exit_mfg_deactivate:  	return 0;  } +static int btusb_setup_bcm_patchram(struct hci_dev *hdev) +{ +	struct btusb_data *data = hci_get_drvdata(hdev); +	struct usb_device *udev = data->udev; +	char fw_name[64]; +	const struct firmware *fw; +	const u8 *fw_ptr; +	size_t fw_size; +	const struct hci_command_hdr *cmd; +	const u8 *cmd_param; +	u16 opcode; +	struct sk_buff *skb; +	struct hci_rp_read_local_version *ver; +	long ret; + +	snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd", +		 udev->product ? udev->product : "BCM", +		 le16_to_cpu(udev->descriptor.idVendor), +		 le16_to_cpu(udev->descriptor.idProduct)); + +	ret = request_firmware(&fw, fw_name, &hdev->dev); +	if (ret < 0) { +		BT_INFO("%s: BCM: patch %s not found", hdev->name, +			fw_name); +		return 0; +	} + +	/* Reset */ +	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		ret = PTR_ERR(skb); +		BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret); +		goto done; +	} +	kfree_skb(skb); + +	/* Read Local Version Info */ +	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, +			     HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		ret = PTR_ERR(skb); +		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)", +			hdev->name, ret); +		goto done; +	} + +	if (skb->len != sizeof(*ver)) { +		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", +			hdev->name); +		kfree_skb(skb); +		ret = -EIO; +		goto done; +	} + +	ver = (struct hci_rp_read_local_version *) skb->data; +	BT_INFO("%s: BCM: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x " +		"lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev, +		ver->lmp_ver, ver->lmp_subver); +	kfree_skb(skb); + +	/* Start Download */ +	skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		ret = PTR_ERR(skb); +		BT_ERR("%s: BCM: Download Minidrv command failed (%ld)", +			hdev->name, ret); +		goto reset_fw; +	} +	kfree_skb(skb); + +	/* 50 msec delay after Download Minidrv completes */ +	msleep(50); + +	fw_ptr = fw->data; +	fw_size = fw->size; + +	while (fw_size >= sizeof(*cmd)) { +		cmd = (struct hci_command_hdr *) fw_ptr; +		fw_ptr += sizeof(*cmd); +		fw_size -= sizeof(*cmd); + +		if (fw_size < cmd->plen) { +			BT_ERR("%s: BCM: patch %s is corrupted", +				hdev->name, fw_name); +			ret = -EINVAL; +			goto reset_fw; +		} + +		cmd_param = fw_ptr; +		fw_ptr += cmd->plen; +		fw_size -= cmd->plen; + +		opcode = le16_to_cpu(cmd->opcode); + +		skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param, +				     HCI_INIT_TIMEOUT); +		if (IS_ERR(skb)) { +			ret = PTR_ERR(skb); +			BT_ERR("%s: BCM: patch command %04x failed (%ld)", +				hdev->name, opcode, ret); +			goto reset_fw; +		} +		kfree_skb(skb); +	} + +	/* 250 msec delay after Launch Ram completes */ +	msleep(250); + +reset_fw: +	/* Reset */ +	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		ret = PTR_ERR(skb); +		BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret); +		goto done; +	} +	kfree_skb(skb); + +	/* Read Local Version Info */ +	skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, +			     HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		ret = PTR_ERR(skb); +		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)", +			hdev->name, ret); +		goto done; +	} + +	if (skb->len != sizeof(*ver)) { +		BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", +			hdev->name); +		kfree_skb(skb); +		ret = -EIO; +		goto done; +	} + +	ver = (struct hci_rp_read_local_version *) skb->data; +	BT_INFO("%s: BCM: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x " +		"lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev, +		ver->lmp_ver, ver->lmp_subver); +	kfree_skb(skb); + +done: +	release_firmware(fw); + +	return ret; +} +  static int btusb_probe(struct usb_interface *intf,  				const struct usb_device_id *id)  { @@ -1434,6 +1635,9 @@ static int btusb_probe(struct usb_interface *intf,  	if (id->driver_info & BTUSB_BCM92035)  		hdev->setup = btusb_setup_bcm92035; +	if (id->driver_info & BTUSB_BCM_PATCHRAM) +		hdev->setup = btusb_setup_bcm_patchram; +  	if (id->driver_info & BTUSB_INTEL)  		hdev->setup = btusb_setup_intel; @@ -1458,10 +1662,15 @@ static int btusb_probe(struct usb_interface *intf,  	if (id->driver_info & BTUSB_CSR) {  		struct usb_device *udev = data->udev; +		u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);  		/* Old firmware would otherwise execute USB reset */ -		if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117) +		if (bcdDevice < 0x117)  			set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + +		/* Fake CSR devices with broken commands */ +		if (bcdDevice <= 0x100) +			hdev->setup = btusb_setup_csr;  	}  	if (id->driver_info & BTUSB_SNIFFER) { @@ -1628,7 +1837,6 @@ static struct usb_driver btusb_driver = {  #ifdef CONFIG_PM  	.suspend	= btusb_suspend,  	.resume		= btusb_resume, -	.reset_resume	= btusb_resume,  #endif  	.id_table	= btusb_table,  	.supports_autosuspend = 1, diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c index 60abf596f60..f038dba19e3 100644 --- a/drivers/bluetooth/btwilink.c +++ b/drivers/bluetooth/btwilink.c @@ -108,10 +108,8 @@ static long st_receive(void *priv_data, struct sk_buff *skb)  		return -EFAULT;  	} -	skb->dev = (void *) lhst->hdev; -  	/* Forward skb to HCI core layer */ -	err = hci_recv_frame(skb); +	err = hci_recv_frame(lhst->hdev, skb);  	if (err < 0) {  		BT_ERR("Unable to push skb to HCI core(%d)", err);  		return err; @@ -253,14 +251,11 @@ static int ti_st_close(struct hci_dev *hdev)  	return err;  } -static int ti_st_send_frame(struct sk_buff *skb) +static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	struct hci_dev *hdev;  	struct ti_st *hst;  	long len; -	hdev = (struct hci_dev *)skb->dev; -  	if (!test_bit(HCI_RUNNING, &hdev->flags))  		return -EBUSY; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 33f3a6950c0..2bd8fad1720 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -153,7 +153,8 @@ static void dtl1_write_wakeup(dtl1_info_t *info)  		if (!pcmcia_dev_present(info->p_dev))  			return; -		if (!(skb = skb_dequeue(&(info->txq)))) +		skb = skb_dequeue(&(info->txq)); +		if (!skb)  			break;  		/* Send frame */ @@ -215,13 +216,15 @@ static void dtl1_receive(dtl1_info_t *info)  		info->hdev->stat.byte_rx++;  		/* Allocate packet */ -		if (info->rx_skb == NULL) -			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { +		if (info->rx_skb == NULL) { +			info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); +			if (!info->rx_skb) {  				BT_ERR("Can't allocate mem for new packet");  				info->rx_state = RECV_WAIT_NSH;  				info->rx_count = NSHL;  				return;  			} +		}  		*skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);  		nsh = (nsh_t *)info->rx_skb->data; @@ -256,9 +259,8 @@ static void dtl1_receive(dtl1_info_t *info)  				case 0x83:  				case 0x84:  					/* send frame to the HCI layer */ -					info->rx_skb->dev = (void *) info->hdev;  					bt_cb(info->rx_skb)->pkt_type &= 0x0f; -					hci_recv_frame(info->rx_skb); +					hci_recv_frame(info->hdev, info->rx_skb);  					break;  				default:  					/* unknown packet */ @@ -383,20 +385,12 @@ static int dtl1_hci_close(struct hci_dev *hdev)  } -static int dtl1_hci_send_frame(struct sk_buff *skb) +static int dtl1_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	dtl1_info_t *info; -	struct hci_dev *hdev = (struct hci_dev *)(skb->dev); +	dtl1_info_t *info = hci_get_drvdata(hdev);  	struct sk_buff *s;  	nsh_t nsh; -	if (!hdev) { -		BT_ERR("Frame for unknown HCI device (hdev=NULL)"); -		return -ENODEV; -	} - -	info = hci_get_drvdata(hdev); -  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT:  		hdev->stat.cmd_tx++; @@ -438,12 +432,6 @@ static int dtl1_hci_send_frame(struct sk_buff *skb)  } -static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,  unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -  /* ======================== Card services HCI interaction ======================== */ @@ -477,11 +465,10 @@ static int dtl1_open(dtl1_info_t *info)  	hci_set_drvdata(hdev, info);  	SET_HCIDEV_DEV(hdev, &info->p_dev->dev); -	hdev->open     = dtl1_hci_open; -	hdev->close    = dtl1_hci_close; -	hdev->flush    = dtl1_hci_flush; -	hdev->send     = dtl1_hci_send_frame; -	hdev->ioctl    = dtl1_hci_ioctl; +	hdev->open  = dtl1_hci_open; +	hdev->close = dtl1_hci_close; +	hdev->flush = dtl1_hci_flush; +	hdev->send  = dtl1_hci_send_frame;  	spin_lock_irqsave(&(info->lock), flags); diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 57e502e0608..21cc45b34f1 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -291,7 +291,8 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)  	/* First of all, check for unreliable messages in the queue,  	   since they have priority */ -	if ((skb = skb_dequeue(&bcsp->unrel)) != NULL) { +	skb = skb_dequeue(&bcsp->unrel); +	if (skb != NULL) {  		struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);  		if (nskb) {  			kfree_skb(skb); @@ -308,16 +309,20 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)  	spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); -	if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) { -		struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type); -		if (nskb) { -			__skb_queue_tail(&bcsp->unack, skb); -			mod_timer(&bcsp->tbcsp, jiffies + HZ / 4); -			spin_unlock_irqrestore(&bcsp->unack.lock, flags); -			return nskb; -		} else { -			skb_queue_head(&bcsp->rel, skb); -			BT_ERR("Could not dequeue pkt because alloc_skb failed"); +	if (bcsp->unack.qlen < BCSP_TXWINSIZE) { +		skb = skb_dequeue(&bcsp->rel); +		if (skb != NULL) { +			struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, +								bt_cb(skb)->pkt_type); +			if (nskb) { +				__skb_queue_tail(&bcsp->unack, skb); +				mod_timer(&bcsp->tbcsp, jiffies + HZ / 4); +				spin_unlock_irqrestore(&bcsp->unack.lock, flags); +				return nskb; +			} else { +				skb_queue_head(&bcsp->rel, skb); +				BT_ERR("Could not dequeue pkt because alloc_skb failed"); +			}  		}  	} @@ -522,7 +527,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu)  				memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE);  				bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT; -				hci_recv_frame(bcsp->rx_skb); +				hci_recv_frame(hu->hdev, bcsp->rx_skb);  			} else {  				BT_ERR ("Packet for unknown channel (%u %s)",  					bcsp->rx_skb->data[1] & 0x0f, @@ -536,7 +541,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu)  		/* Pull out BCSP hdr */  		skb_pull(bcsp->rx_skb, 4); -		hci_recv_frame(bcsp->rx_skb); +		hci_recv_frame(hu->hdev, bcsp->rx_skb);  	}  	bcsp->rx_state = BCSP_W4_PKT_DELIMITER; @@ -655,7 +660,6 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)  					bcsp->rx_count = 0;  					return 0;  				} -				bcsp->rx_skb->dev = (void *) hu->hdev;  				break;  			}  			break; @@ -716,6 +720,9 @@ static int bcsp_open(struct hci_uart *hu)  static int bcsp_close(struct hci_uart *hu)  {  	struct bcsp_struct *bcsp = hu->priv; + +	del_timer_sync(&bcsp->tbcsp); +  	hu->priv = NULL;  	BT_DBG("hu %p", hu); @@ -723,7 +730,6 @@ static int bcsp_close(struct hci_uart *hu)  	skb_queue_purge(&bcsp->unack);  	skb_queue_purge(&bcsp->rel);  	skb_queue_purge(&bcsp->unrel); -	del_timer(&bcsp->tbcsp);  	kfree(bcsp);  	return 0; diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index 8ae9f1ea2bb..66db9a80337 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -55,13 +55,6 @@ struct h4_struct {  	struct sk_buff_head txq;  }; -/* H4 receiver States */ -#define H4_W4_PACKET_TYPE	0 -#define H4_W4_EVENT_HDR		1 -#define H4_W4_ACL_HDR		2 -#define H4_W4_SCO_HDR		3 -#define H4_W4_DATA		4 -  /* Initialize protocol */  static int h4_open(struct hci_uart *hu)  { @@ -124,30 +117,6 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)  	return 0;  } -static inline int h4_check_data_len(struct h4_struct *h4, int len) -{ -	int room = skb_tailroom(h4->rx_skb); - -	BT_DBG("len %d room %d", len, room); - -	if (!len) { -		hci_recv_frame(h4->rx_skb); -	} else if (len > room) { -		BT_ERR("Data length is too large"); -		kfree_skb(h4->rx_skb); -	} else { -		h4->rx_state = H4_W4_DATA; -		h4->rx_count = len; -		return len; -	} - -	h4->rx_state = H4_W4_PACKET_TYPE; -	h4->rx_skb   = NULL; -	h4->rx_count = 0; - -	return 0; -} -  /* Recv data */  static int h4_recv(struct hci_uart *hu, void *data, int count)  { diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index b6154d5a07a..fede8ca7147 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -206,12 +206,12 @@ static int h5_close(struct hci_uart *hu)  {  	struct h5 *h5 = hu->priv; +	del_timer_sync(&h5->timer); +  	skb_queue_purge(&h5->unack);  	skb_queue_purge(&h5->rel);  	skb_queue_purge(&h5->unrel); -	del_timer(&h5->timer); -  	kfree(h5);  	return 0; @@ -340,7 +340,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu)  		/* Remove Three-wire header */  		skb_pull(h5->rx_skb, 4); -		hci_recv_frame(h5->rx_skb); +		hci_recv_frame(hu->hdev, h5->rx_skb);  		h5->rx_skb = NULL;  		break; @@ -406,6 +406,7 @@ static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c)  	    H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) {  		BT_ERR("Non-link packet received in non-active state");  		h5_reset_rx(h5); +		return 0;  	}  	h5->rx_func = h5_rx_payload; @@ -673,7 +674,8 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)  		return h5_prepare_pkt(hu, HCI_3WIRE_LINK_PKT, wakeup_req, 2);  	} -	if ((skb = skb_dequeue(&h5->unrel)) != NULL) { +	skb = skb_dequeue(&h5->unrel); +	if (skb != NULL) {  		nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,  				      skb->data, skb->len);  		if (nskb) { @@ -690,7 +692,8 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)  	if (h5->unack.qlen >= h5->tx_win)  		goto unlock; -	if ((skb = skb_dequeue(&h5->rel)) != NULL) { +	skb = skb_dequeue(&h5->rel); +	if (skb != NULL) {  		nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,  				      skb->data, skb->len);  		if (nskb) { diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index bc68a440d43..e00f8f5b5c8 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -118,10 +118,6 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)  int hci_uart_tx_wakeup(struct hci_uart *hu)  { -	struct tty_struct *tty = hu->tty; -	struct hci_dev *hdev = hu->hdev; -	struct sk_buff *skb; -  	if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {  		set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);  		return 0; @@ -129,6 +125,22 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)  	BT_DBG(""); +	schedule_work(&hu->write_work); + +	return 0; +} + +static void hci_uart_write_work(struct work_struct *work) +{ +	struct hci_uart *hu = container_of(work, struct hci_uart, write_work); +	struct tty_struct *tty = hu->tty; +	struct hci_dev *hdev = hu->hdev; +	struct sk_buff *skb; + +	/* REVISIT: should we cope with bad skbs or ->write() returning +	 * and error value ? +	 */ +  restart:  	clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); @@ -153,7 +165,6 @@ restart:  		goto restart;  	clear_bit(HCI_UART_SENDING, &hu->tx_state); -	return 0;  }  static void hci_uart_init_work(struct work_struct *work) @@ -234,21 +245,13 @@ static int hci_uart_close(struct hci_dev *hdev)  }  /* Send frames from HCI layer */ -static int hci_uart_send_frame(struct sk_buff *skb) +static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	struct hci_dev* hdev = (struct hci_dev *) skb->dev; -	struct hci_uart *hu; - -	if (!hdev) { -		BT_ERR("Frame for unknown device (hdev=NULL)"); -		return -ENODEV; -	} +	struct hci_uart *hu = hci_get_drvdata(hdev);  	if (!test_bit(HCI_RUNNING, &hdev->flags))  		return -EBUSY; -	hu = hci_get_drvdata(hdev); -  	BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);  	hu->proto->enqueue(hu, skb); @@ -279,7 +282,8 @@ static int hci_uart_tty_open(struct tty_struct *tty)  	if (tty->ops->write == NULL)  		return -EOPNOTSUPP; -	if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) { +	hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL); +	if (!hu) {  		BT_ERR("Can't allocate control structure");  		return -ENFILE;  	} @@ -289,6 +293,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)  	tty->receive_room = 65536;  	INIT_WORK(&hu->init_ready, hci_uart_init_work); +	INIT_WORK(&hu->write_work, hci_uart_write_work);  	spin_lock_init(&hu->rx_lock); @@ -326,6 +331,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)  	if (hdev)  		hci_uart_close(hdev); +	cancel_work_sync(&hu->write_work); +  	if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {  		if (hdev) {  			if (test_bit(HCI_UART_REGISTERED, &hu->flags)) @@ -577,7 +584,8 @@ static int __init hci_uart_init(void)  	hci_uart_ldisc.write_wakeup	= hci_uart_tty_wakeup;  	hci_uart_ldisc.owner		= THIS_MODULE; -	if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) { +	err = tty_register_ldisc(N_HCI, &hci_uart_ldisc); +	if (err) {  		BT_ERR("HCI line discipline registration failed. (%d)", err);  		return err;  	} @@ -622,7 +630,8 @@ static void __exit hci_uart_exit(void)  #endif  	/* Release tty registration of line discipline */ -	if ((err = tty_unregister_ldisc(N_HCI))) +	err = tty_unregister_ldisc(N_HCI); +	if (err)  		BT_ERR("Can't unregister HCI line discipline (%d)", err);  } diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index cfc76793858..69a90b1b5ff 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -110,7 +110,6 @@ static int send_hcill_cmd(u8 cmd, struct hci_uart *hu)  	/* prepare packet */  	hcill_packet = (struct hcill_cmd *) skb_put(skb, 1);  	hcill_packet->cmd = cmd; -	skb->dev = (void *) hu->hdev;  	/* send packet */  	skb_queue_tail(&ll->txq, skb); @@ -346,14 +345,14 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)  	return 0;  } -static inline int ll_check_data_len(struct ll_struct *ll, int len) +static inline int ll_check_data_len(struct hci_dev *hdev, struct ll_struct *ll, int len)  {  	int room = skb_tailroom(ll->rx_skb);  	BT_DBG("len %d room %d", len, room);  	if (!len) { -		hci_recv_frame(ll->rx_skb); +		hci_recv_frame(hdev, ll->rx_skb);  	} else if (len > room) {  		BT_ERR("Data length is too large");  		kfree_skb(ll->rx_skb); @@ -395,7 +394,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count)  			switch (ll->rx_state) {  			case HCILL_W4_DATA:  				BT_DBG("Complete data"); -				hci_recv_frame(ll->rx_skb); +				hci_recv_frame(hu->hdev, ll->rx_skb);  				ll->rx_state = HCILL_W4_PACKET_TYPE;  				ll->rx_skb = NULL; @@ -406,7 +405,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count)  				BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); -				ll_check_data_len(ll, eh->plen); +				ll_check_data_len(hu->hdev, ll, eh->plen);  				continue;  			case HCILL_W4_ACL_HDR: @@ -415,7 +414,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count)  				BT_DBG("ACL header: dlen %d", dlen); -				ll_check_data_len(ll, dlen); +				ll_check_data_len(hu->hdev, ll, dlen);  				continue;  			case HCILL_W4_SCO_HDR: @@ -423,7 +422,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count)  				BT_DBG("SCO header: dlen %d", sh->dlen); -				ll_check_data_len(ll, sh->dlen); +				ll_check_data_len(hu->hdev, ll, sh->dlen);  				continue;  			}  		} @@ -494,7 +493,6 @@ static int ll_recv(struct hci_uart *hu, void *data, int count)  			return -ENOMEM;  		} -		ll->rx_skb->dev = (void *) hu->hdev;  		bt_cb(ll->rx_skb)->pkt_type = type;  	} diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index fffa61ff5cb..12df101ca94 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -68,6 +68,7 @@ struct hci_uart {  	unsigned long		hdev_flags;  	struct work_struct	init_ready; +	struct work_struct	write_work;  	struct hci_uart_proto	*proto;  	void			*priv; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index d8b7aed6e4a..add1c6a7206 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -24,6 +24,7 @@   */  #include <linux/module.h> +#include <asm/unaligned.h>  #include <linux/kernel.h>  #include <linux/init.h> @@ -39,17 +40,17 @@  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h> -#define VERSION "1.3" +#define VERSION "1.4"  static bool amp;  struct vhci_data {  	struct hci_dev *hdev; -	unsigned long flags; -  	wait_queue_head_t read_wait;  	struct sk_buff_head readq; + +	struct delayed_work open_timeout;  };  static int vhci_open_dev(struct hci_dev *hdev) @@ -80,67 +81,153 @@ static int vhci_flush(struct hci_dev *hdev)  	return 0;  } -static int vhci_send_frame(struct sk_buff *skb) +static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)  { -	struct hci_dev* hdev = (struct hci_dev *) skb->dev; -	struct vhci_data *data; +	struct vhci_data *data = hci_get_drvdata(hdev); + +	if (!test_bit(HCI_RUNNING, &hdev->flags)) +		return -EBUSY; + +	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); +	skb_queue_tail(&data->readq, skb); +	wake_up_interruptible(&data->read_wait); +	return 0; +} + +static int vhci_create_device(struct vhci_data *data, __u8 dev_type) +{ +	struct hci_dev *hdev; +	struct sk_buff *skb; + +	skb = bt_skb_alloc(4, GFP_KERNEL); +	if (!skb) +		return -ENOMEM; + +	hdev = hci_alloc_dev();  	if (!hdev) { -		BT_ERR("Frame for unknown HCI device (hdev=NULL)"); -		return -ENODEV; +		kfree_skb(skb); +		return -ENOMEM;  	} -	if (!test_bit(HCI_RUNNING, &hdev->flags)) +	data->hdev = hdev; + +	hdev->bus = HCI_VIRTUAL; +	hdev->dev_type = dev_type; +	hci_set_drvdata(hdev, data); + +	hdev->open  = vhci_open_dev; +	hdev->close = vhci_close_dev; +	hdev->flush = vhci_flush; +	hdev->send  = vhci_send_frame; + +	if (hci_register_dev(hdev) < 0) { +		BT_ERR("Can't register HCI device"); +		hci_free_dev(hdev); +		data->hdev = NULL; +		kfree_skb(skb);  		return -EBUSY; +	} -	data = hci_get_drvdata(hdev); +	bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; -	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); +	*skb_put(skb, 1) = 0xff; +	*skb_put(skb, 1) = dev_type; +	put_unaligned_le16(hdev->id, skb_put(skb, 2));  	skb_queue_tail(&data->readq, skb);  	wake_up_interruptible(&data->read_wait); -  	return 0;  }  static inline ssize_t vhci_get_user(struct vhci_data *data, -					const char __user *buf, size_t count) +				    const struct iovec *iov, +				    unsigned long count)  { +	size_t len = iov_length(iov, count);  	struct sk_buff *skb; +	__u8 pkt_type, dev_type; +	unsigned long i; +	int ret; -	if (count > HCI_MAX_FRAME_SIZE) +	if (len < 2 || len > HCI_MAX_FRAME_SIZE)  		return -EINVAL; -	skb = bt_skb_alloc(count, GFP_KERNEL); +	skb = bt_skb_alloc(len, GFP_KERNEL);  	if (!skb)  		return -ENOMEM; -	if (copy_from_user(skb_put(skb, count), buf, count)) { -		kfree_skb(skb); -		return -EFAULT; +	for (i = 0; i < count; i++) { +		if (copy_from_user(skb_put(skb, iov[i].iov_len), +				   iov[i].iov_base, iov[i].iov_len)) { +			kfree_skb(skb); +			return -EFAULT; +		}  	} -	skb->dev = (void *) data->hdev; -	bt_cb(skb)->pkt_type = *((__u8 *) skb->data); +	pkt_type = *((__u8 *) skb->data);  	skb_pull(skb, 1); -	hci_recv_frame(skb); +	switch (pkt_type) { +	case HCI_EVENT_PKT: +	case HCI_ACLDATA_PKT: +	case HCI_SCODATA_PKT: +		if (!data->hdev) { +			kfree_skb(skb); +			return -ENODEV; +		} + +		bt_cb(skb)->pkt_type = pkt_type; -	return count; +		ret = hci_recv_frame(data->hdev, skb); +		break; + +	case HCI_VENDOR_PKT: +		if (data->hdev) { +			kfree_skb(skb); +			return -EBADFD; +		} + +		cancel_delayed_work_sync(&data->open_timeout); + +		dev_type = *((__u8 *) skb->data); +		skb_pull(skb, 1); + +		if (skb->len > 0) { +			kfree_skb(skb); +			return -EINVAL; +		} + +		kfree_skb(skb); + +		if (dev_type != HCI_BREDR && dev_type != HCI_AMP) +			return -EINVAL; + +		ret = vhci_create_device(data, dev_type); +		break; + +	default: +		kfree_skb(skb); +		return -EINVAL; +	} + +	return (ret < 0) ? ret : len;  }  static inline ssize_t vhci_put_user(struct vhci_data *data, -			struct sk_buff *skb, char __user *buf, int count) +				    struct sk_buff *skb, +				    char __user *buf, int count)  {  	char __user *ptr = buf; -	int len, total = 0; +	int len;  	len = min_t(unsigned int, skb->len, count);  	if (copy_to_user(ptr, skb->data, len))  		return -EFAULT; -	total += len; +	if (!data->hdev) +		return len;  	data->hdev->stat.byte_tx += len; @@ -148,21 +235,19 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,  	case HCI_COMMAND_PKT:  		data->hdev->stat.cmd_tx++;  		break; -  	case HCI_ACLDATA_PKT:  		data->hdev->stat.acl_tx++;  		break; -  	case HCI_SCODATA_PKT:  		data->hdev->stat.sco_tx++;  		break;  	} -	return total; +	return len;  }  static ssize_t vhci_read(struct file *file, -				char __user *buf, size_t count, loff_t *pos) +			 char __user *buf, size_t count, loff_t *pos)  {  	struct vhci_data *data = file->private_data;  	struct sk_buff *skb; @@ -185,7 +270,7 @@ static ssize_t vhci_read(struct file *file,  		}  		ret = wait_event_interruptible(data->read_wait, -					!skb_queue_empty(&data->readq)); +					       !skb_queue_empty(&data->readq));  		if (ret < 0)  			break;  	} @@ -193,12 +278,13 @@ static ssize_t vhci_read(struct file *file,  	return ret;  } -static ssize_t vhci_write(struct file *file, -			const char __user *buf, size_t count, loff_t *pos) +static ssize_t vhci_write(struct kiocb *iocb, const struct iovec *iov, +			  unsigned long count, loff_t pos)  { +	struct file *file = iocb->ki_filp;  	struct vhci_data *data = file->private_data; -	return vhci_get_user(data, buf, count); +	return vhci_get_user(data, iov, count);  }  static unsigned int vhci_poll(struct file *file, poll_table *wait) @@ -213,10 +299,17 @@ static unsigned int vhci_poll(struct file *file, poll_table *wait)  	return POLLOUT | POLLWRNORM;  } +static void vhci_open_timeout(struct work_struct *work) +{ +	struct vhci_data *data = container_of(work, struct vhci_data, +					      open_timeout.work); + +	vhci_create_device(data, amp ? HCI_AMP : HCI_BREDR); +} +  static int vhci_open(struct inode *inode, struct file *file)  {  	struct vhci_data *data; -	struct hci_dev *hdev;  	data = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);  	if (!data) @@ -225,35 +318,13 @@ static int vhci_open(struct inode *inode, struct file *file)  	skb_queue_head_init(&data->readq);  	init_waitqueue_head(&data->read_wait); -	hdev = hci_alloc_dev(); -	if (!hdev) { -		kfree(data); -		return -ENOMEM; -	} - -	data->hdev = hdev; - -	hdev->bus = HCI_VIRTUAL; -	hci_set_drvdata(hdev, data); - -	if (amp) -		hdev->dev_type = HCI_AMP; - -	hdev->open     = vhci_open_dev; -	hdev->close    = vhci_close_dev; -	hdev->flush    = vhci_flush; -	hdev->send     = vhci_send_frame; - -	if (hci_register_dev(hdev) < 0) { -		BT_ERR("Can't register HCI device"); -		kfree(data); -		hci_free_dev(hdev); -		return -EBUSY; -	} +	INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);  	file->private_data = data;  	nonseekable_open(inode, file); +	schedule_delayed_work(&data->open_timeout, msecs_to_jiffies(1000)); +  	return 0;  } @@ -262,8 +333,12 @@ static int vhci_release(struct inode *inode, struct file *file)  	struct vhci_data *data = file->private_data;  	struct hci_dev *hdev = data->hdev; -	hci_unregister_dev(hdev); -	hci_free_dev(hdev); +	cancel_delayed_work_sync(&data->open_timeout); + +	if (hdev) { +		hci_unregister_dev(hdev); +		hci_free_dev(hdev); +	}  	file->private_data = NULL;  	kfree(data); @@ -274,7 +349,7 @@ static int vhci_release(struct inode *inode, struct file *file)  static const struct file_operations vhci_fops = {  	.owner		= THIS_MODULE,  	.read		= vhci_read, -	.write		= vhci_write, +	.aio_write	= vhci_write,  	.poll		= vhci_poll,  	.open		= vhci_open,  	.release	= vhci_release, @@ -284,7 +359,7 @@ static const struct file_operations vhci_fops = {  static struct miscdevice vhci_miscdev= {  	.name	= "vhci",  	.fops	= &vhci_fops, -	.minor	= MISC_DYNAMIC_MINOR, +	.minor	= VHCI_MINOR,  };  static int __init vhci_init(void) @@ -309,3 +384,5 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");  MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);  MODULE_VERSION(VERSION);  MODULE_LICENSE("GPL"); +MODULE_ALIAS("devname:vhci"); +MODULE_ALIAS_MISCDEV(VHCI_MINOR);  | 
