diff options
Diffstat (limited to 'drivers/bluetooth')
26 files changed, 3507 insertions, 1433 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 02deef42492..f5ce64e03fd 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -26,6 +26,7 @@ config BT_HCIBTSDIO  config BT_HCIUART  	tristate "HCI UART driver" +	depends on TTY  	help  	  Bluetooth HCI UART driver.  	  This driver is required if you want to use Bluetooth devices with @@ -81,6 +82,18 @@ config BT_HCIUART_LL  	  Say Y here to compile support for HCILL protocol. +config BT_HCIUART_3WIRE +	bool "Three-wire UART (H5) protocol support" +	depends on BT_HCIUART +	help +	  The HCI Three-wire UART Transport Layer makes it possible to +	  user the Bluetooth HCI over a serial port interface. The HCI +	  Three-wire UART Transport Layer assumes that the UART +	  communication may have bit errors, overrun errors or burst +	  errors and thereby making CTS/RTS lines unnecessary. + +	  Say Y here to compile support for Three-wire UART protocol. +  config BT_HCIBCM203X  	tristate "HCI BCM203x USB driver"  	depends on USB @@ -188,7 +201,7 @@ config BT_MRVL  	  The core driver to support Marvell Bluetooth devices.  	  This driver is required if you want to support -	  Marvell Bluetooth devices, such as 8688. +	  Marvell Bluetooth devices, such as 8688/8787/8797/8897.  	  Say Y here to compile Marvell Bluetooth driver  	  into the kernel or say M to compile it as module. @@ -201,8 +214,8 @@ config BT_MRVL_SDIO  	  The driver for Marvell Bluetooth chipsets with SDIO interface.  	  This driver is required if you want to use Marvell Bluetooth -	  devices with SDIO interface. Currently only SD8688 chipset is -	  supported. +	  devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8897 +	  chipsets are supported.  	  Say Y here to compile support for Marvell BT-over-SDIO driver  	  into the kernel or say M to compile it as module. @@ -219,4 +232,15 @@ config BT_ATH3K  	  Say Y here to compile support for "Atheros firmware download driver"  	  into the kernel or say M to compile it as module (ath3k). +config BT_WILINK +	tristate "Texas Instruments WiLink7 driver" +	depends on TI_ST +	help +	  This enables the Bluetooth driver for Texas Instrument's BT/FM/GPS +	  combo devices. This makes use of shared transport line discipline +	  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 (btwilink). +  endmenu diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 71bdf13287c..9fe8a875a82 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o  obj-$(CONFIG_BT_ATH3K)		+= ath3k.o  obj-$(CONFIG_BT_MRVL)		+= btmrvl.o  obj-$(CONFIG_BT_MRVL_SDIO)	+= btmrvl_sdio.o +obj-$(CONFIG_BT_WILINK)		+= btwilink.o  btmrvl-y			:= btmrvl_main.o  btmrvl-$(CONFIG_DEBUG_FS)	+= btmrvl_debugfs.o @@ -27,4 +28,7 @@ hci_uart-$(CONFIG_BT_HCIUART_H4)	+= hci_h4.o  hci_uart-$(CONFIG_BT_HCIUART_BCSP)	+= hci_bcsp.o  hci_uart-$(CONFIG_BT_HCIUART_LL)	+= hci_ll.o  hci_uart-$(CONFIG_BT_HCIUART_ATH3K)	+= hci_ath.o +hci_uart-$(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 128cae4e862..f50dffc0374 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -30,77 +30,418 @@  #include <net/bluetooth/bluetooth.h>  #define VERSION "1.0" +#define ATH3K_FIRMWARE	"ath3k-1.fw" + +#define ATH3K_DNLOAD				0x01 +#define ATH3K_GETSTATE				0x05 +#define ATH3K_SET_NORMAL_MODE			0x07 +#define ATH3K_GETVERSION			0x09 +#define USB_REG_SWITCH_VID_PID			0x0a + +#define ATH3K_MODE_MASK				0x3F +#define ATH3K_NORMAL_MODE			0x0E + +#define ATH3K_PATCH_UPDATE			0x80 +#define ATH3K_SYSCFG_UPDATE			0x40 + +#define ATH3K_XTAL_FREQ_26M			0x00 +#define ATH3K_XTAL_FREQ_40M			0x01 +#define ATH3K_XTAL_FREQ_19P2			0x02 +#define ATH3K_NAME_LEN				0xFF + +struct ath3k_version { +	unsigned int	rom_version; +	unsigned int	build_version; +	unsigned int	ram_version; +	unsigned char	ref_clock; +	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) }, + +	/* 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(0x0cf3, 0xe003) }, +	{ USB_DEVICE(0x0CF3, 0xE004) }, +	{ USB_DEVICE(0x0CF3, 0xE005) }, +	{ USB_DEVICE(0x13d3, 0x3362) }, +	{ USB_DEVICE(0x13d3, 0x3375) }, +	{ USB_DEVICE(0x13d3, 0x3393) }, +	{ USB_DEVICE(0x13d3, 0x3402) }, + +	/* Atheros AR5BBU12 with sflash firmware */ +	{ USB_DEVICE(0x0489, 0xE02C) }, + +	/* Atheros AR5BBU22 with sflash firmware */ +	{ USB_DEVICE(0x0489, 0xE036) }, +	{ USB_DEVICE(0x0489, 0xE03C) }, +  	{ }	/* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, ath3k_table); -#define USB_REQ_DFU_DNLOAD	1 -#define BULK_SIZE		4096 +#define BTUSB_ATH3012		0x80 +/* This table is to load patch and sysconfig files + * for AR3012 */ +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(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0xe005), .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(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, + +	/* Atheros AR5BBU22 with sflash firmware */ +	{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, -struct ath3k_data { -	struct usb_device *udev; -	u8 *fw_data; -	u32 fw_size; -	u32 fw_sent; +	{ }	/* Terminating entry */  }; -static int ath3k_load_firmware(struct ath3k_data *data, -				unsigned char *firmware, -				int count) +#define USB_REQ_DFU_DNLOAD	1 +#define BULK_SIZE		4096 +#define FW_HDR_SIZE		20 + +static int ath3k_load_firmware(struct usb_device *udev, +				const struct firmware *firmware)  {  	u8 *send_buf;  	int err, pipe, len, size, sent = 0; +	int count = firmware->size; + +	BT_DBG("udev %p", udev); -	BT_DBG("ath3k %p udev %p", data, data->udev); +	pipe = usb_sndctrlpipe(udev, 0); -	pipe = usb_sndctrlpipe(data->udev, 0); +	send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); +	if (!send_buf) { +		BT_ERR("Can't allocate memory chunk for firmware"); +		return -ENOMEM; +	} -	if ((usb_control_msg(data->udev, pipe, -				USB_REQ_DFU_DNLOAD, -				USB_TYPE_VENDOR, 0, 0, -				firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) { +	memcpy(send_buf, firmware->data, 20); +	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"); -		return -EBUSY; +		goto error;  	}  	sent += 20;  	count -= 20; -	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); +	pipe = usb_sndbulkpipe(udev, 0x02); + +	while (count) { +		size = min_t(uint, count, BULK_SIZE); +		memcpy(send_buf, firmware->data + sent, size); + +		err = usb_bulk_msg(udev, pipe, send_buf, size, +					&len, 3000); + +		if (err || (len != size)) { +			BT_ERR("Error in firmware loading err = %d," +				"len = %d, size = %d", err, len, size); +			goto error; +		} + +		sent  += size; +		count -= size; +	} + +error: +	kfree(send_buf); +	return err; +} + +static int ath3k_get_state(struct usb_device *udev, unsigned char *state) +{ +	int ret, pipe = 0; +	char *buf; + +	buf = kmalloc(sizeof(*buf), GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	pipe = usb_rcvctrlpipe(udev, 0); +	ret = usb_control_msg(udev, pipe, ATH3K_GETSTATE, +			      USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, +			      buf, sizeof(*buf), USB_CTRL_SET_TIMEOUT); + +	*state = *buf; +	kfree(buf); + +	return ret; +} + +static int ath3k_get_version(struct usb_device *udev, +			struct ath3k_version *version) +{ +	int ret, pipe = 0; +	struct ath3k_version *buf; +	const int size = sizeof(*buf); + +	buf = kmalloc(size, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	pipe = usb_rcvctrlpipe(udev, 0); +	ret = usb_control_msg(udev, pipe, ATH3K_GETVERSION, +			      USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, +			      buf, size, USB_CTRL_SET_TIMEOUT); + +	memcpy(version, buf, size); +	kfree(buf); + +	return ret; +} + +static int ath3k_load_fwfile(struct usb_device *udev, +		const struct firmware *firmware) +{ +	u8 *send_buf; +	int err, pipe, len, size, count, sent = 0; +	int ret; + +	count = firmware->size; + +	send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);  	if (!send_buf) {  		BT_ERR("Can't allocate memory chunk for firmware");  		return -ENOMEM;  	} +	size = min_t(uint, count, FW_HDR_SIZE); +	memcpy(send_buf, firmware->data, size); + +	pipe = usb_sndctrlpipe(udev, 0); +	ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD, +			USB_TYPE_VENDOR, 0, 0, send_buf, +			size, USB_CTRL_SET_TIMEOUT); +	if (ret < 0) { +		BT_ERR("Can't change to loading configuration err"); +		kfree(send_buf); +		return ret; +	} + +	sent += size; +	count -= size; +  	while (count) {  		size = min_t(uint, count, BULK_SIZE); -		pipe = usb_sndbulkpipe(data->udev, 0x02); -		memcpy(send_buf, firmware + sent, size); +		pipe = usb_sndbulkpipe(udev, 0x02); -		err = usb_bulk_msg(data->udev, pipe, send_buf, size, -					&len, 3000); +		memcpy(send_buf, firmware->data + sent, size); +		err = usb_bulk_msg(udev, pipe, send_buf, size, +					&len, 3000);  		if (err || (len != size)) {  			BT_ERR("Error in firmware loading err = %d,"  				"len = %d, size = %d", err, len, size); -			goto error; +			kfree(send_buf); +			return err;  		} -  		sent  += size;  		count -= size;  	}  	kfree(send_buf);  	return 0; +} -error: -	kfree(send_buf); -	return err; +static int ath3k_switch_pid(struct usb_device *udev) +{ +	int pipe = 0; + +	pipe = usb_sndctrlpipe(udev, 0); +	return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID, +			USB_TYPE_VENDOR, 0, 0, +			NULL, 0, USB_CTRL_SET_TIMEOUT); +} + +static int ath3k_set_normal_mode(struct usb_device *udev) +{ +	unsigned char fw_state; +	int pipe = 0, ret; + +	ret = ath3k_get_state(udev, &fw_state); +	if (ret < 0) { +		BT_ERR("Can't get state to change to normal mode err"); +		return ret; +	} + +	if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) { +		BT_DBG("firmware was already in normal mode"); +		return 0; +	} + +	pipe = usb_sndctrlpipe(udev, 0); +	return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE, +			USB_TYPE_VENDOR, 0, 0, +			NULL, 0, USB_CTRL_SET_TIMEOUT); +} + +static int ath3k_load_patch(struct usb_device *udev) +{ +	unsigned char fw_state; +	char filename[ATH3K_NAME_LEN] = {0}; +	const struct firmware *firmware; +	struct ath3k_version fw_version, pt_version; +	int ret; + +	ret = ath3k_get_state(udev, &fw_state); +	if (ret < 0) { +		BT_ERR("Can't get state to change to load ram patch err"); +		return ret; +	} + +	if (fw_state & ATH3K_PATCH_UPDATE) { +		BT_DBG("Patch was already downloaded"); +		return 0; +	} + +	ret = ath3k_get_version(udev, &fw_version); +	if (ret < 0) { +		BT_ERR("Can't get version to change to load ram patch err"); +		return ret; +	} + +	snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", +		le32_to_cpu(fw_version.rom_version)); + +	ret = request_firmware(&firmware, filename, &udev->dev); +	if (ret < 0) { +		BT_ERR("Patch file not found %s", filename); +		return ret; +	} + +	pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); +	pt_version.build_version = *(int *) +		(firmware->data + firmware->size - 4); + +	if ((pt_version.rom_version != fw_version.rom_version) || +		(pt_version.build_version <= fw_version.build_version)) { +		BT_ERR("Patch file version did not match with firmware"); +		release_firmware(firmware); +		return -EINVAL; +	} + +	ret = ath3k_load_fwfile(udev, firmware); +	release_firmware(firmware); + +	return ret; +} + +static int ath3k_load_syscfg(struct usb_device *udev) +{ +	unsigned char fw_state; +	char filename[ATH3K_NAME_LEN] = {0}; +	const struct firmware *firmware; +	struct ath3k_version fw_version; +	int clk_value, ret; + +	ret = ath3k_get_state(udev, &fw_state); +	if (ret < 0) { +		BT_ERR("Can't get state to change to load configuration err"); +		return -EBUSY; +	} + +	ret = ath3k_get_version(udev, &fw_version); +	if (ret < 0) { +		BT_ERR("Can't get version to change to load ram patch err"); +		return ret; +	} + +	switch (fw_version.ref_clock) { + +	case ATH3K_XTAL_FREQ_26M: +		clk_value = 26; +		break; +	case ATH3K_XTAL_FREQ_40M: +		clk_value = 40; +		break; +	case ATH3K_XTAL_FREQ_19P2: +		clk_value = 19; +		break; +	default: +		clk_value = 0; +		break; +	} + +	snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s", +		le32_to_cpu(fw_version.rom_version), clk_value, ".dfu"); + +	ret = request_firmware(&firmware, filename, &udev->dev); +	if (ret < 0) { +		BT_ERR("Configuration file not found %s", filename); +		return ret; +	} + +	ret = ath3k_load_fwfile(udev, firmware); +	release_firmware(firmware); + +	return ret;  }  static int ath3k_probe(struct usb_interface *intf, @@ -108,57 +449,67 @@ static int ath3k_probe(struct usb_interface *intf,  {  	const struct firmware *firmware;  	struct usb_device *udev = interface_to_usbdev(intf); -	struct ath3k_data *data; -	int size; +	int ret;  	BT_DBG("intf %p id %p", intf, id);  	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)  		return -ENODEV; -	data = kzalloc(sizeof(*data), GFP_KERNEL); -	if (!data) -		return -ENOMEM; +	/* match device ID in ath3k blacklist table */ +	if (!id->driver_info) { +		const struct usb_device_id *match; +		match = usb_match_id(intf, ath3k_blist_tbl); +		if (match) +			id = match; +	} -	data->udev = udev; +	/* load patch and sysconfig files for AR3012 */ +	if (id->driver_info & BTUSB_ATH3012) { -	if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { -		kfree(data); -		return -EIO; +		/* New firmware with patch and sysconfig files already loaded */ +		if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x0001) +			return -ENODEV; + +		ret = ath3k_load_patch(udev); +		if (ret < 0) { +			BT_ERR("Loading patch file failed"); +			return ret; +		} +		ret = ath3k_load_syscfg(udev); +		if (ret < 0) { +			BT_ERR("Loading sysconfig file failed"); +			return ret; +		} +		ret = ath3k_set_normal_mode(udev); +		if (ret < 0) { +			BT_ERR("Set normal mode failed"); +			return ret; +		} +		ath3k_switch_pid(udev); +		return 0;  	} -	size = max_t(uint, firmware->size, 4096); -	data->fw_data = kmalloc(size, GFP_KERNEL); -	if (!data->fw_data) { -		release_firmware(firmware); -		kfree(data); -		return -ENOMEM; +	ret = request_firmware(&firmware, ATH3K_FIRMWARE, &udev->dev); +	if (ret < 0) { +		if (ret == -ENOENT) +			BT_ERR("Firmware file \"%s\" not found", +							ATH3K_FIRMWARE); +		else +			BT_ERR("Firmware file \"%s\" request failed (err=%d)", +							ATH3K_FIRMWARE, ret); +		return ret;  	} -	memcpy(data->fw_data, firmware->data, firmware->size); -	data->fw_size = firmware->size; -	data->fw_sent = 0; +	ret = ath3k_load_firmware(udev, firmware);  	release_firmware(firmware); -	usb_set_intfdata(intf, data); -	if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) { -		usb_set_intfdata(intf, NULL); -		kfree(data->fw_data); -		kfree(data); -		return -EIO; -	} - -	return 0; +	return ret;  }  static void ath3k_disconnect(struct usb_interface *intf)  { -	struct ath3k_data *data = usb_get_intfdata(intf); -  	BT_DBG("ath3k_disconnect intf %p", intf); - -	kfree(data->fw_data); -	kfree(data);  }  static struct usb_driver ath3k_driver = { @@ -166,24 +517,13 @@ static struct usb_driver ath3k_driver = {  	.probe		= ath3k_probe,  	.disconnect	= ath3k_disconnect,  	.id_table	= ath3k_table, +	.disable_hub_initiated_lpm = 1,  }; -static int __init ath3k_init(void) -{ -	BT_INFO("Atheros AR30xx firmware driver ver %s", VERSION); -	return usb_register(&ath3k_driver); -} - -static void __exit ath3k_exit(void) -{ -	usb_deregister(&ath3k_driver); -} - -module_init(ath3k_init); -module_exit(ath3k_exit); +module_usb_driver(ath3k_driver);  MODULE_AUTHOR("Atheros Communications");  MODULE_DESCRIPTION("Atheros AR30xx firmware driver");  MODULE_VERSION(VERSION);  MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("ath3k-1.fw"); +MODULE_FIRMWARE(ATH3K_FIRMWARE); diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 8b1b643a519..364f82b34d0 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -24,6 +24,7 @@  #include <linux/module.h> +#include <linux/atomic.h>  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/slab.h> @@ -65,6 +66,7 @@ struct bcm203x_data {  	unsigned long		state;  	struct work_struct	work; +	atomic_t		shutdown;  	struct urb		*urb;  	unsigned char		*buffer; @@ -97,6 +99,7 @@ static void bcm203x_complete(struct urb *urb)  		data->state = BCM203X_SELECT_MEMORY; +		/* use workqueue to have a small delay */  		schedule_work(&data->work);  		break; @@ -155,7 +158,10 @@ static void bcm203x_work(struct work_struct *work)  	struct bcm203x_data *data =  		container_of(work, struct bcm203x_data, work); -	if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) +	if (atomic_read(&data->shutdown)) +		return; + +	if (usb_submit_urb(data->urb, GFP_KERNEL) < 0)  		BT_ERR("Can't submit URB");  } @@ -171,7 +177,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id  	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)  		return -ENODEV; -	data = kzalloc(sizeof(*data), GFP_KERNEL); +	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);  	if (!data) {  		BT_ERR("Can't allocate memory for data structure");  		return -ENOMEM; @@ -183,14 +189,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id  	data->urb = usb_alloc_urb(0, GFP_KERNEL);  	if (!data->urb) {  		BT_ERR("Can't allocate URB"); -		kfree(data);  		return -ENOMEM;  	}  	if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {  		BT_ERR("Mini driver request failed");  		usb_free_urb(data->urb); -		kfree(data);  		return -EIO;  	} @@ -203,7 +207,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id  		BT_ERR("Can't allocate memory for mini driver");  		release_firmware(firmware);  		usb_free_urb(data->urb); -		kfree(data);  		return -ENOMEM;  	} @@ -218,7 +221,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id  		BT_ERR("Firmware request failed");  		usb_free_urb(data->urb);  		kfree(data->buffer); -		kfree(data);  		return -EIO;  	} @@ -230,7 +232,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id  		release_firmware(firmware);  		usb_free_urb(data->urb);  		kfree(data->buffer); -		kfree(data);  		return -ENOMEM;  	} @@ -243,6 +244,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id  	usb_set_intfdata(intf, data); +	/* use workqueue to have a small delay */  	schedule_work(&data->work);  	return 0; @@ -254,6 +256,9 @@ static void bcm203x_disconnect(struct usb_interface *intf)  	BT_DBG("intf %p", intf); +	atomic_inc(&data->shutdown); +	cancel_work_sync(&data->work); +  	usb_kill_urb(data->urb);  	usb_set_intfdata(intf, NULL); @@ -261,7 +266,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)  	usb_free_urb(data->urb);  	kfree(data->fw_data);  	kfree(data->buffer); -	kfree(data);  }  static struct usb_driver bcm203x_driver = { @@ -269,28 +273,10 @@ static struct usb_driver bcm203x_driver = {  	.probe		= bcm203x_probe,  	.disconnect	= bcm203x_disconnect,  	.id_table	= bcm203x_table, +	.disable_hub_initiated_lpm = 1,  }; -static int __init bcm203x_init(void) -{ -	int err; - -	BT_INFO("Broadcom Blutonium firmware driver ver %s", VERSION); - -	err = usb_register(&bcm203x_driver); -	if (err < 0) -		BT_ERR("Failed to register USB driver"); - -	return err; -} - -static void __exit bcm203x_exit(void) -{ -	usb_deregister(&bcm203x_driver); -} - -module_init(bcm203x_init); -module_exit(bcm203x_exit); +module_usb_driver(bcm203x_driver);  MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");  MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION); diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 005919ab043..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;  	} @@ -411,7 +416,7 @@ unlock:  static int bfusb_open(struct hci_dev *hdev)  { -	struct bfusb_data *data = hdev->driver_data; +	struct bfusb_data *data = hci_get_drvdata(hdev);  	unsigned long flags;  	int i, err; @@ -437,7 +442,7 @@ static int bfusb_open(struct hci_dev *hdev)  static int bfusb_flush(struct hci_dev *hdev)  { -	struct bfusb_data *data = hdev->driver_data; +	struct bfusb_data *data = hci_get_drvdata(hdev);  	BT_DBG("hdev %p bfusb %p", hdev, data); @@ -448,7 +453,7 @@ static int bfusb_flush(struct hci_dev *hdev)  static int bfusb_close(struct hci_dev *hdev)  { -	struct bfusb_data *data = hdev->driver_data; +	struct bfusb_data *data = hci_get_drvdata(hdev);  	unsigned long flags;  	BT_DBG("hdev %p bfusb %p", hdev, data); @@ -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 = hdev->driver_data; -  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT:  		hdev->stat.cmd_tx++; @@ -544,20 +541,6 @@ static int bfusb_send_frame(struct sk_buff *skb)  	return 0;  } -static void bfusb_destruct(struct hci_dev *hdev) -{ -	struct bfusb_data *data = hdev->driver_data; - -	BT_DBG("hdev %p bfusb %p", hdev, data); - -	kfree(data); -} - -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)  { @@ -568,22 +551,23 @@ static int bfusb_load_firmware(struct bfusb_data *data,  	BT_INFO("BlueFRITZ! USB loading firmware"); +	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL); +	if (!buf) { +		BT_ERR("Can't allocate memory chunk for firmware"); +		return -ENOMEM; +	} +  	pipe = usb_sndctrlpipe(data->udev, 0);  	if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,  				0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {  		BT_ERR("Can't change to loading configuration"); +		kfree(buf);  		return -EBUSY;  	}  	data->udev->toggle[0] = data->udev->toggle[1] = 0; -	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC); -	if (!buf) { -		BT_ERR("Can't allocate memory chunk for firmware"); -		return -ENOMEM; -	} -  	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);  	while (count) { @@ -661,7 +645,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i  	}  	/* Initialize control structure and load firmware */ -	data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL); +	data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL);  	if (!data) {  		BT_ERR("Can't allocate memory for control structure");  		goto done; @@ -682,7 +666,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i  	if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {  		BT_ERR("Firmware request failed"); -		goto error; +		goto done;  	}  	BT_DBG("firmware data %p size %zu", firmware->data, firmware->size); @@ -698,28 +682,24 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i  	hdev = hci_alloc_dev();  	if (!hdev) {  		BT_ERR("Can't allocate HCI device"); -		goto error; +		goto done;  	}  	data->hdev = hdev;  	hdev->bus = HCI_USB; -	hdev->driver_data = data; +	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->destruct = bfusb_destruct; -	hdev->ioctl    = bfusb_ioctl; - -	hdev->owner = THIS_MODULE; +	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");  		hci_free_dev(hdev); -		goto error; +		goto done;  	}  	usb_set_intfdata(intf, data); @@ -729,9 +709,6 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i  release:  	release_firmware(firmware); -error: -	kfree(data); -  done:  	return -EIO;  } @@ -750,9 +727,7 @@ static void bfusb_disconnect(struct usb_interface *intf)  	bfusb_close(hdev); -	if (hci_unregister_dev(hdev) < 0) -		BT_ERR("Can't unregister HCI device %s", hdev->name); - +	hci_unregister_dev(hdev);  	hci_free_dev(hdev);  } @@ -761,28 +736,10 @@ static struct usb_driver bfusb_driver = {  	.probe		= bfusb_probe,  	.disconnect	= bfusb_disconnect,  	.id_table	= bfusb_table, +	.disable_hub_initiated_lpm = 1,  }; -static int __init bfusb_init(void) -{ -	int err; - -	BT_INFO("BlueFRITZ! USB driver ver %s", VERSION); - -	err = usb_register(&bfusb_driver); -	if (err < 0) -		BT_ERR("Failed to register BlueFRITZ! USB driver"); - -	return err; -} - -static void __exit bfusb_exit(void) -{ -	usb_deregister(&bfusb_driver); -} - -module_init(bfusb_init); -module_exit(bfusb_exit); +module_usb_driver(bfusb_driver);  MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");  MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION); diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 4104b7feae6..dfa5043e68b 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -231,12 +231,12 @@ static void bluecard_write_wakeup(bluecard_info_t *info)  	}  	do { -		register unsigned int iobase = info->p_dev->resource[0]->start; -		register unsigned int offset; -		register unsigned char command; -		register unsigned long ready_bit; +		unsigned int iobase = info->p_dev->resource[0]->start; +		unsigned int offset; +		unsigned char command; +		unsigned long ready_bit;  		register struct sk_buff *skb; -		register int len; +		int len;  		clear_bit(XMIT_WAKEUP, &(info->tx_state)); @@ -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; @@ -561,13 +562,14 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)  static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)  { -	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); +	bluecard_info_t *info = hci_get_drvdata(hdev);  	struct sk_buff *skb;  	/* 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;  	} @@ -609,7 +611,7 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)  static int bluecard_hci_flush(struct hci_dev *hdev)  { -	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); +	bluecard_info_t *info = hci_get_drvdata(hdev);  	/* Drop TX queue */  	skb_queue_purge(&(info->txq)); @@ -620,8 +622,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)  static int bluecard_hci_open(struct hci_dev *hdev)  { -	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); -	unsigned int iobase = info->p_dev->resource[0]->start; +	bluecard_info_t *info = hci_get_drvdata(hdev);  	if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))  		bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); @@ -630,6 +631,8 @@ static int bluecard_hci_open(struct hci_dev *hdev)  		return 0;  	if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { +		unsigned int iobase = info->p_dev->resource[0]->start; +  		/* Enable LED */  		outb(0x08 | 0x20, iobase + 0x30);  	} @@ -640,8 +643,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)  static int bluecard_hci_close(struct hci_dev *hdev)  { -	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); -	unsigned int iobase = info->p_dev->resource[0]->start; +	bluecard_info_t *info = hci_get_drvdata(hdev);  	if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))  		return 0; @@ -649,6 +651,8 @@ static int bluecard_hci_close(struct hci_dev *hdev)  	bluecard_hci_flush(hdev);  	if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { +		unsigned int iobase = info->p_dev->resource[0]->start; +  		/* Disable LED */  		outb(0x00, iobase + 0x30);  	} @@ -657,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 = (bluecard_info_t *)(hdev->driver_data); +	bluecard_info_t *info = hci_get_drvdata(hdev);  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT: @@ -679,7 +675,7 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)  	case HCI_SCODATA_PKT:  		hdev->stat.sco_tx++;  		break; -	}; +	}  	/* Prepend skb with frame type */  	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); @@ -691,17 +687,6 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)  } -static void bluecard_hci_destruct(struct hci_dev *hdev) -{ -} - - -static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -  /* ======================== Card services HCI interaction ======================== */ @@ -734,17 +719,13 @@ static int bluecard_open(bluecard_info_t *info)  	info->hdev = hdev;  	hdev->bus = HCI_PCCARD; -	hdev->driver_data = 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->destruct = bluecard_hci_destruct; -	hdev->ioctl    = bluecard_hci_ioctl; - -	hdev->owner = THIS_MODULE; +	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); @@ -844,9 +825,7 @@ static int bluecard_close(bluecard_info_t *info)  	/* Turn FPGA off */  	outb(0x80, iobase + 0x30); -	if (hci_unregister_dev(hdev) < 0) -		BT_ERR("Can't unregister HCI device %s", hdev->name); - +	hci_unregister_dev(hdev);  	hci_free_dev(hdev);  	return 0; @@ -857,7 +836,7 @@ static int bluecard_probe(struct pcmcia_device *link)  	bluecard_info_t *info;  	/* Create new info device */ -	info = kzalloc(sizeof(*info), GFP_KERNEL); +	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);  	if (!info)  		return -ENOMEM; @@ -872,10 +851,7 @@ static int bluecard_probe(struct pcmcia_device *link)  static void bluecard_detach(struct pcmcia_device *link)  { -	bluecard_info_t *info = link->priv; -  	bluecard_release(link); -	kfree(info);  } @@ -925,12 +901,12 @@ static void bluecard_release(struct pcmcia_device *link)  	bluecard_close(info); -	del_timer(&(info->timer)); +	del_timer_sync(&(info->timer));  	pcmcia_disable_device(link);  } -static struct pcmcia_device_id bluecard_ids[] = { +static const struct pcmcia_device_id bluecard_ids[] = {  	PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e),  	PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c),  	PCMCIA_DEVICE_PROD_ID12("WSS", "LSE039", 0x0a0736ec, 0x24e6dfab), @@ -945,17 +921,4 @@ static struct pcmcia_driver bluecard_driver = {  	.remove		= bluecard_detach,  	.id_table	= bluecard_ids,  }; - -static int __init init_bluecard_cs(void) -{ -	return pcmcia_register_driver(&bluecard_driver); -} - - -static void __exit exit_bluecard_cs(void) -{ -	pcmcia_unregister_driver(&bluecard_driver); -} - -module_init(init_bluecard_cs); -module_exit(exit_bluecard_cs); +module_pcmcia_driver(bluecard_driver); diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 751b338d904..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) }, @@ -66,7 +66,7 @@ struct hci_vendor_hdr {  static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)  { -	struct bpa10x_data *data = hdev->driver_data; +	struct bpa10x_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s queue %d buffer %p count %d", hdev->name,  							queue, buf, count); @@ -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; @@ -189,7 +187,7 @@ done:  static void bpa10x_rx_complete(struct urb *urb)  {  	struct hci_dev *hdev = urb->context; -	struct bpa10x_data *data = hdev->driver_data; +	struct bpa10x_data *data = hci_get_drvdata(hdev);  	int err;  	BT_DBG("%s urb %p status %d count %d", hdev->name, @@ -219,7 +217,7 @@ static void bpa10x_rx_complete(struct urb *urb)  static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)  { -	struct bpa10x_data *data = hdev->driver_data; +	struct bpa10x_data *data = hci_get_drvdata(hdev);  	struct urb *urb;  	unsigned char *buf;  	unsigned int pipe; @@ -260,7 +258,7 @@ static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)  static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)  { -	struct bpa10x_data *data = hdev->driver_data; +	struct bpa10x_data *data = hci_get_drvdata(hdev);  	struct urb *urb;  	unsigned char *buf;  	unsigned int pipe; @@ -301,7 +299,7 @@ static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)  static int bpa10x_open(struct hci_dev *hdev)  { -	struct bpa10x_data *data = hdev->driver_data; +	struct bpa10x_data *data = hci_get_drvdata(hdev);  	int err;  	BT_DBG("%s", hdev->name); @@ -329,7 +327,7 @@ error:  static int bpa10x_close(struct hci_dev *hdev)  { -	struct bpa10x_data *data = hdev->driver_data; +	struct bpa10x_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s", hdev->name); @@ -343,7 +341,7 @@ static int bpa10x_close(struct hci_dev *hdev)  static int bpa10x_flush(struct hci_dev *hdev)  { -	struct bpa10x_data *data = hdev->driver_data; +	struct bpa10x_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s", hdev->name); @@ -352,10 +350,9 @@ 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 = hdev->driver_data; +	struct bpa10x_data *data = hci_get_drvdata(hdev);  	struct usb_ctrlrequest *dr;  	struct urb *urb;  	unsigned int pipe; @@ -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; @@ -432,17 +431,6 @@ static int bpa10x_send_frame(struct sk_buff *skb)  	return 0;  } -static void bpa10x_destruct(struct hci_dev *hdev) -{ -	struct bpa10x_data *data = hdev->driver_data; - -	BT_DBG("%s", hdev->name); - -	kfree_skb(data->rx_skb[0]); -	kfree_skb(data->rx_skb[1]); -	kfree(data); -} -  static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)  {  	struct bpa10x_data *data; @@ -454,7 +442,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *  	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)  		return -ENODEV; -	data = kzalloc(sizeof(*data), GFP_KERNEL); +	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);  	if (!data)  		return -ENOMEM; @@ -464,13 +452,11 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *  	init_usb_anchor(&data->rx_anchor);  	hdev = hci_alloc_dev(); -	if (!hdev) { -		kfree(data); +	if (!hdev)  		return -ENOMEM; -	}  	hdev->bus = HCI_USB; -	hdev->driver_data = data; +	hci_set_drvdata(hdev, data);  	data->hdev = hdev; @@ -480,16 +466,12 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *  	hdev->close    = bpa10x_close;  	hdev->flush    = bpa10x_flush;  	hdev->send     = bpa10x_send_frame; -	hdev->destruct = bpa10x_destruct; - -	hdev->owner = THIS_MODULE; -	set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); +	set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);  	err = hci_register_dev(hdev);  	if (err < 0) {  		hci_free_dev(hdev); -		kfree(data);  		return err;  	} @@ -512,6 +494,8 @@ static void bpa10x_disconnect(struct usb_interface *intf)  	hci_unregister_dev(data->hdev);  	hci_free_dev(data->hdev); +	kfree_skb(data->rx_skb[0]); +	kfree_skb(data->rx_skb[1]);  }  static struct usb_driver bpa10x_driver = { @@ -519,22 +503,10 @@ static struct usb_driver bpa10x_driver = {  	.probe		= bpa10x_probe,  	.disconnect	= bpa10x_disconnect,  	.id_table	= bpa10x_table, +	.disable_hub_initiated_lpm = 1,  }; -static int __init bpa10x_init(void) -{ -	BT_INFO("Digianswer Bluetooth USB driver ver %s", VERSION); - -	return usb_register(&bpa10x_driver); -} - -static void __exit bpa10x_exit(void) -{ -	usb_deregister(&bpa10x_driver); -} - -module_init(bpa10x_init); -module_exit(bpa10x_exit); +module_usb_driver(bpa10x_driver);  MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");  MODULE_DESCRIPTION("Digianswer Bluetooth USB driver ver " VERSION); diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 0c8a6558749..1d82721cf9c 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -39,7 +39,6 @@  #include <linux/serial.h>  #include <linux/serial_reg.h>  #include <linux/bitops.h> -#include <asm/system.h>  #include <asm/io.h>  #include <linux/device.h> @@ -187,15 +186,15 @@ static void bt3c_write_wakeup(bt3c_info_t *info)  		return;  	do { -		register unsigned int iobase = info->p_dev->resource[0]->start; +		unsigned int iobase = info->p_dev->resource[0]->start;  		register struct sk_buff *skb; -		register int len; +		int len;  		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;  		} @@ -239,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;  			} @@ -248,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); @@ -319,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; @@ -389,7 +388,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)  static int bt3c_hci_flush(struct hci_dev *hdev)  { -	bt3c_info_t *info = (bt3c_info_t *)(hdev->driver_data); +	bt3c_info_t *info = hci_get_drvdata(hdev);  	/* Drop TX queue */  	skb_queue_purge(&(info->txq)); @@ -417,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 = (bt3c_info_t *) (hdev->driver_data); -  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT:  		hdev->stat.cmd_tx++; @@ -456,17 +447,6 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)  } -static void bt3c_hci_destruct(struct hci_dev *hdev) -{ -} - - -static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -  /* ======================== Card services HCI interaction ======================== */ @@ -580,17 +560,13 @@ static int bt3c_open(bt3c_info_t *info)  	info->hdev = hdev;  	hdev->bus = HCI_PCCARD; -	hdev->driver_data = 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->destruct = bt3c_hci_destruct; -	hdev->ioctl    = bt3c_hci_ioctl; - -	hdev->owner = THIS_MODULE; +	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); @@ -636,9 +612,7 @@ static int bt3c_close(bt3c_info_t *info)  	bt3c_hci_close(hdev); -	if (hci_unregister_dev(hdev) < 0) -		BT_ERR("Can't unregister HCI device %s", hdev->name); - +	hci_unregister_dev(hdev);  	hci_free_dev(hdev);  	return 0; @@ -649,7 +623,7 @@ static int bt3c_probe(struct pcmcia_device *link)  	bt3c_info_t *info;  	/* Create new info device */ -	info = kzalloc(sizeof(*info), GFP_KERNEL); +	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);  	if (!info)  		return -ENOMEM; @@ -665,17 +639,14 @@ static int bt3c_probe(struct pcmcia_device *link)  static void bt3c_detach(struct pcmcia_device *link)  { -	bt3c_info_t *info = link->priv; -  	bt3c_release(link); -	kfree(info);  }  static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)  {  	int *try = priv_data; -	if (try == 0) +	if (!try)  		p_dev->io_lines = 16;  	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0)) @@ -761,7 +732,7 @@ static void bt3c_release(struct pcmcia_device *link)  } -static struct pcmcia_device_id bt3c_ids[] = { +static const struct pcmcia_device_id bt3c_ids[] = {  	PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02),  	PCMCIA_DEVICE_NULL  }; @@ -774,17 +745,4 @@ static struct pcmcia_driver bt3c_driver = {  	.remove		= bt3c_detach,  	.id_table	= bt3c_ids,  }; - -static int __init init_bt3c_cs(void) -{ -	return pcmcia_register_driver(&bt3c_driver); -} - - -static void __exit exit_bt3c_cs(void) -{ -	pcmcia_unregister_driver(&bt3c_driver); -} - -module_init(init_bt3c_cs); -module_exit(exit_bt3c_cs); +module_pcmcia_driver(bt3c_driver); diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index fd6305bf953..023d35e3c7a 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -29,28 +29,8 @@  struct btmrvl_debugfs_data {  	struct dentry *config_dir;  	struct dentry *status_dir; - -	/* config */ -	struct dentry *psmode; -	struct dentry *pscmd; -	struct dentry *hsmode; -	struct dentry *hscmd; -	struct dentry *gpiogap; -	struct dentry *hscfgcmd; - -	/* status */ -	struct dentry *curpsmode; -	struct dentry *hsstate; -	struct dentry *psstate; -	struct dentry *txdnldready;  }; -static int btmrvl_open_generic(struct inode *inode, struct file *file) -{ -	file->private_data = inode->i_private; -	return 0; -} -  static ssize_t btmrvl_hscfgcmd_write(struct file *file,  			const char __user *ubuf, size_t count, loff_t *ppos)  { @@ -63,7 +43,9 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file,  	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))  		return -EFAULT; -	ret = strict_strtol(buf, 10, &result); +	ret = kstrtol(buf, 10, &result); +	if (ret) +		return ret;  	priv->btmrvl_dev.hscfgcmd = result; @@ -91,46 +73,7 @@ static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf,  static const struct file_operations btmrvl_hscfgcmd_fops = {  	.read	= btmrvl_hscfgcmd_read,  	.write	= btmrvl_hscfgcmd_write, -	.open	= btmrvl_open_generic, -	.llseek = default_llseek, -}; - -static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	long result, ret; - -	memset(buf, 0, sizeof(buf)); - -	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) -		return -EFAULT; - -	ret = strict_strtol(buf, 10, &result); - -	priv->btmrvl_dev.psmode = result; - -	return count; -} - -static ssize_t btmrvl_psmode_read(struct file *file, char __user *userbuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	int ret; - -	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", -						priv->btmrvl_dev.psmode); - -	return simple_read_from_buffer(userbuf, count, ppos, buf, ret); -} - -static const struct file_operations btmrvl_psmode_fops = { -	.read	= btmrvl_psmode_read, -	.write	= btmrvl_psmode_write, -	.open	= btmrvl_open_generic, +	.open	= simple_open,  	.llseek = default_llseek,  }; @@ -146,7 +89,9 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,  	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))  		return -EFAULT; -	ret = strict_strtol(buf, 10, &result); +	ret = kstrtol(buf, 10, &result); +	if (ret) +		return ret;  	priv->btmrvl_dev.pscmd = result; @@ -174,46 +119,7 @@ static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf,  static const struct file_operations btmrvl_pscmd_fops = {  	.read = btmrvl_pscmd_read,  	.write = btmrvl_pscmd_write, -	.open = btmrvl_open_generic, -	.llseek = default_llseek, -}; - -static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	long result, ret; - -	memset(buf, 0, sizeof(buf)); - -	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) -		return -EFAULT; - -	ret = strict_strtol(buf, 16, &result); - -	priv->btmrvl_dev.gpio_gap = result; - -	return count; -} - -static ssize_t btmrvl_gpiogap_read(struct file *file, char __user *userbuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	int ret; - -	ret = snprintf(buf, sizeof(buf) - 1, "0x%x\n", -						priv->btmrvl_dev.gpio_gap); - -	return simple_read_from_buffer(userbuf, count, ppos, buf, ret); -} - -static const struct file_operations btmrvl_gpiogap_fops = { -	.read	= btmrvl_gpiogap_read, -	.write	= btmrvl_gpiogap_write, -	.open	= btmrvl_open_generic, +	.open = simple_open,  	.llseek = default_llseek,  }; @@ -229,7 +135,9 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,  	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))  		return -EFAULT; -	ret = strict_strtol(buf, 10, &result); +	ret = kstrtol(buf, 10, &result); +	if (ret) +		return ret;  	priv->btmrvl_dev.hscmd = result;  	if (priv->btmrvl_dev.hscmd) { @@ -255,124 +163,13 @@ static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf,  static const struct file_operations btmrvl_hscmd_fops = {  	.read	= btmrvl_hscmd_read,  	.write	= btmrvl_hscmd_write, -	.open	= btmrvl_open_generic, -	.llseek = default_llseek, -}; - -static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	long result, ret; - -	memset(buf, 0, sizeof(buf)); - -	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) -		return -EFAULT; - -	ret = strict_strtol(buf, 10, &result); - -	priv->btmrvl_dev.hsmode = result; - -	return count; -} - -static ssize_t btmrvl_hsmode_read(struct file *file, char __user * userbuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	int ret; - -	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hsmode); - -	return simple_read_from_buffer(userbuf, count, ppos, buf, ret); -} - -static const struct file_operations btmrvl_hsmode_fops = { -	.read	= btmrvl_hsmode_read, -	.write	= btmrvl_hsmode_write, -	.open	= btmrvl_open_generic, -	.llseek = default_llseek, -}; - -static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	int ret; - -	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->psmode); - -	return simple_read_from_buffer(userbuf, count, ppos, buf, ret); -} - -static const struct file_operations btmrvl_curpsmode_fops = { -	.read	= btmrvl_curpsmode_read, -	.open	= btmrvl_open_generic, -	.llseek = default_llseek, -}; - -static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	int ret; - -	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->ps_state); - -	return simple_read_from_buffer(userbuf, count, ppos, buf, ret); -} - -static const struct file_operations btmrvl_psstate_fops = { -	.read	= btmrvl_psstate_read, -	.open	= btmrvl_open_generic, -	.llseek = default_llseek, -}; - -static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	int ret; - -	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->hs_state); - -	return simple_read_from_buffer(userbuf, count, ppos, buf, ret); -} - -static const struct file_operations btmrvl_hsstate_fops = { -	.read	= btmrvl_hsstate_read, -	.open	= btmrvl_open_generic, -	.llseek = default_llseek, -}; - -static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf, -						size_t count, loff_t *ppos) -{ -	struct btmrvl_private *priv = file->private_data; -	char buf[16]; -	int ret; - -	ret = snprintf(buf, sizeof(buf) - 1, "%d\n", -					priv->btmrvl_dev.tx_dnld_rdy); - -	return simple_read_from_buffer(userbuf, count, ppos, buf, ret); -} - -static const struct file_operations btmrvl_txdnldready_fops = { -	.read	= btmrvl_txdnldready_read, -	.open	= btmrvl_open_generic, +	.open	= simple_open,  	.llseek = default_llseek,  };  void btmrvl_debugfs_init(struct hci_dev *hdev)  { -	struct btmrvl_private *priv = hdev->driver_data; +	struct btmrvl_private *priv = hci_get_drvdata(hdev);  	struct btmrvl_debugfs_data *dbg;  	if (!hdev->debugfs) @@ -388,55 +185,40 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)  	dbg->config_dir = debugfs_create_dir("config", hdev->debugfs); -	dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir, -				hdev->driver_data, &btmrvl_psmode_fops); -	dbg->pscmd = debugfs_create_file("pscmd", 0644, dbg->config_dir, -				hdev->driver_data, &btmrvl_pscmd_fops); -	dbg->gpiogap = debugfs_create_file("gpiogap", 0644, dbg->config_dir, -				hdev->driver_data, &btmrvl_gpiogap_fops); -	dbg->hsmode =  debugfs_create_file("hsmode", 0644, dbg->config_dir, -				hdev->driver_data, &btmrvl_hsmode_fops); -	dbg->hscmd = debugfs_create_file("hscmd", 0644, dbg->config_dir, -				hdev->driver_data, &btmrvl_hscmd_fops); -	dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir, -				hdev->driver_data, &btmrvl_hscfgcmd_fops); +	debugfs_create_u8("psmode", 0644, dbg->config_dir, +			  &priv->btmrvl_dev.psmode); +	debugfs_create_file("pscmd", 0644, dbg->config_dir, +			    priv, &btmrvl_pscmd_fops); +	debugfs_create_x16("gpiogap", 0644, dbg->config_dir, +			   &priv->btmrvl_dev.gpio_gap); +	debugfs_create_u8("hsmode", 0644, dbg->config_dir, +			  &priv->btmrvl_dev.hsmode); +	debugfs_create_file("hscmd", 0644, dbg->config_dir, +			    priv, &btmrvl_hscmd_fops); +	debugfs_create_file("hscfgcmd", 0644, dbg->config_dir, +			    priv, &btmrvl_hscfgcmd_fops);  	dbg->status_dir = debugfs_create_dir("status", hdev->debugfs); -	dbg->curpsmode = debugfs_create_file("curpsmode", 0444, -						dbg->status_dir, -						hdev->driver_data, -						&btmrvl_curpsmode_fops); -	dbg->psstate = debugfs_create_file("psstate", 0444, dbg->status_dir, -				hdev->driver_data, &btmrvl_psstate_fops); -	dbg->hsstate = debugfs_create_file("hsstate", 0444, dbg->status_dir, -				hdev->driver_data, &btmrvl_hsstate_fops); -	dbg->txdnldready = debugfs_create_file("txdnldready", 0444, -						dbg->status_dir, -						hdev->driver_data, -						&btmrvl_txdnldready_fops); +	debugfs_create_u8("curpsmode", 0444, dbg->status_dir, +			  &priv->adapter->psmode); +	debugfs_create_u8("psstate", 0444, dbg->status_dir, +			  &priv->adapter->ps_state); +	debugfs_create_u8("hsstate", 0444, dbg->status_dir, +			  &priv->adapter->hs_state); +	debugfs_create_u8("txdnldready", 0444, dbg->status_dir, +			  &priv->btmrvl_dev.tx_dnld_rdy);  }  void btmrvl_debugfs_remove(struct hci_dev *hdev)  { -	struct btmrvl_private *priv = hdev->driver_data; +	struct btmrvl_private *priv = hci_get_drvdata(hdev);  	struct btmrvl_debugfs_data *dbg = priv->debugfs_data;  	if (!dbg)  		return; -	debugfs_remove(dbg->psmode); -	debugfs_remove(dbg->pscmd); -	debugfs_remove(dbg->gpiogap); -	debugfs_remove(dbg->hsmode); -	debugfs_remove(dbg->hscmd); -	debugfs_remove(dbg->hscfgcmd); -	debugfs_remove(dbg->config_dir); - -	debugfs_remove(dbg->curpsmode); -	debugfs_remove(dbg->psstate); -	debugfs_remove(dbg->hsstate); -	debugfs_remove(dbg->txdnldready); -	debugfs_remove(dbg->status_dir); +	debugfs_remove_recursive(dbg->config_dir); +	debugfs_remove_recursive(dbg->status_dir);  	kfree(dbg);  } diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 90bda50dc44..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; @@ -67,6 +69,7 @@ struct btmrvl_adapter {  	u8 wakeup_tries;  	wait_queue_head_t cmd_wait_q;  	u8 cmd_complete; +	bool is_suspended;  };  struct btmrvl_private { @@ -85,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 @@ -98,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 */ @@ -105,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 @@ -115,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 */ @@ -135,12 +139,14 @@ int btmrvl_remove_card(struct btmrvl_private *priv);  void btmrvl_interrupt(struct btmrvl_private *priv); -void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb); +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); +int btmrvl_enable_hs(struct btmrvl_private *priv);  #ifdef CONFIG_DEBUG_FS  void btmrvl_debugfs_init(struct hci_dev *hdev); diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 548d1d9e4dd..e9dbddb0b8f 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -18,10 +18,13 @@   * this warranty disclaimer.   **/ +#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" @@ -42,23 +45,32 @@ void btmrvl_interrupt(struct btmrvl_private *priv)  }  EXPORT_SYMBOL_GPL(btmrvl_interrupt); -void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) +bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)  {  	struct hci_event_hdr *hdr = (void *) skb->data; -	struct hci_ev_cmd_complete *ec; -	u16 opcode, ocf;  	if (hdr->evt == HCI_EV_CMD_COMPLETE) { +		struct hci_ev_cmd_complete *ec; +		u16 opcode; +  		ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);  		opcode = __le16_to_cpu(ec->opcode); -		ocf = hci_opcode_ocf(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 (hci_opcode_ogf(opcode) == 0x3F) { +				BT_DBG("vendor event skipped: opcode=%#4.4x", +				       opcode); +				kfree_skb(skb); +				return false; +			}  		}  	} + +	return true;  }  EXPORT_SYMBOL_GPL(btmrvl_check_evtpkt); @@ -76,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; @@ -89,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]); @@ -97,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", @@ -154,147 +165,111 @@ 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;  }  EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); -int btmrvl_enable_ps(struct btmrvl_private *priv) +int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)  { -	struct sk_buff *skb; -	struct btmrvl_cmd *cmd; +	int ret; +	u8 param[2]; -	skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); -	if (skb == NULL) { -		BT_ERR("No free skb"); -		return -ENOMEM; -	} +	param[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; +	param[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); -	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; +	BT_DBG("Sending HSCFG Command, gpio=0x%x, gap=0x%x", +	       param[0], param[1]); -	if (priv->btmrvl_dev.psmode) -		cmd->data[0] = BT_PS_ENABLE; -	else -		cmd->data[0] = BT_PS_DISABLE; +	ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, 2); +	if (ret) +		BT_ERR("HSCFG command failed\n"); -	bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; +	return ret; +} +EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd); -	skb->dev = (void *) priv->btmrvl_dev.hcidev; -	skb_queue_head(&priv->adapter->tx_queue, skb); +int btmrvl_enable_ps(struct btmrvl_private *priv) +{ +	int ret; +	u8 param; -	BT_DBG("Queue PSMODE Command:%d", cmd->data[0]); +	if (priv->btmrvl_dev.psmode) +		param = BT_PS_ENABLE; +	else +		param = BT_PS_DISABLE; + +	ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, ¶m, 1); +	if (ret) +		BT_ERR("PSMODE command failed\n");  	return 0;  }  EXPORT_SYMBOL_GPL(btmrvl_enable_ps); -static int btmrvl_enable_hs(struct btmrvl_private *priv) +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;  } +EXPORT_SYMBOL_GPL(btmrvl_enable_hs);  int btmrvl_prepare_command(struct btmrvl_private *priv)  { -	struct sk_buff *skb = NULL; -	struct btmrvl_cmd *cmd;  	int ret = 0;  	if (priv->btmrvl_dev.hscfgcmd) {  		priv->btmrvl_dev.hscfgcmd = 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_CONFIG)); -		cmd->length = 2; -		cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; -		cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); - -		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 HSCFG Command, gpio=0x%x, gap=0x%x", -						cmd->data[0], cmd->data[1]); +		btmrvl_send_hscfg_cmd(priv);  	}  	if (priv->btmrvl_dev.pscmd) { @@ -363,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);  } @@ -374,34 +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 void btmrvl_destruct(struct hci_dev *hdev) -{ -} - -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 || !hdev->driver_data) { -		BT_ERR("Frame for unknown HCI device"); -		return -ENODEV; -	} - -	priv = (struct btmrvl_private *) hdev->driver_data;  	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, @@ -432,7 +406,7 @@ static int btmrvl_send_frame(struct sk_buff *skb)  static int btmrvl_flush(struct hci_dev *hdev)  { -	struct btmrvl_private *priv = hdev->driver_data; +	struct btmrvl_private *priv = hci_get_drvdata(hdev);  	skb_queue_purge(&priv->adapter->tx_queue); @@ -441,7 +415,7 @@ static int btmrvl_flush(struct hci_dev *hdev)  static int btmrvl_close(struct hci_dev *hdev)  { -	struct btmrvl_private *priv = hdev->driver_data; +	struct btmrvl_private *priv = hci_get_drvdata(hdev);  	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))  		return 0; @@ -458,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. @@ -473,12 +513,14 @@ static int btmrvl_service_main_thread(void *data)  	init_waitqueue_entry(&wait, current); -	current->flags |= PF_NOFREEZE; -  	for (;;) {  		add_wait_queue(&thread->wait_q, &wait);  		set_current_state(TASK_INTERRUPTIBLE); +		if (kthread_should_stop()) { +			BT_DBG("main_thread: break from main thread"); +			break; +		}  		if (adapter->wakeup_tries ||  				((!adapter->int_count) && @@ -494,11 +536,6 @@ static int btmrvl_service_main_thread(void *data)  		BT_DBG("main_thread woke up"); -		if (kthread_should_stop()) { -			BT_DBG("main_thread: break from main thread"); -			break; -		} -  		spin_lock_irqsave(&priv->driver_lock, flags);  		if (adapter->int_count) {  			adapter->int_count = 0; @@ -546,18 +583,14 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)  	}  	priv->btmrvl_dev.hcidev = hdev; -	hdev->driver_data = priv; +	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->destruct = btmrvl_destruct; -	hdev->ioctl = btmrvl_ioctl; -	hdev->owner = THIS_MODULE; - -	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 dcc2a6ec23f..9dedca516ff 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -23,6 +23,7 @@  #include <linux/mmc/sdio_ids.h>  #include <linux/mmc/sdio_func.h> +#include <linux/module.h>  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h> @@ -49,15 +50,104 @@  static u8 user_rmmod;  static u8 sdio_ireg; -static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = { -	.helper		= "sd8688_helper.bin", -	.firmware	= "sd8688.bin", +static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { +	.cfg = 0x03, +	.host_int_mask = 0x04, +	.host_intstatus = 0x05, +	.card_status = 0x20, +	.sq_read_base_addr_a0 = 0x10, +	.sq_read_base_addr_a1 = 0x11, +	.card_fw_status0 = 0x40, +	.card_fw_status1 = 0x41, +	.card_rx_len = 0x42, +	.card_rx_unit = 0x43, +	.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, +	.host_int_mask = 0x02, +	.host_intstatus = 0x03, +	.card_status = 0x30, +	.sq_read_base_addr_a0 = 0x40, +	.sq_read_base_addr_a1 = 0x41, +	.card_revision = 0x5c, +	.card_fw_status0 = 0x60, +	.card_fw_status1 = 0x61, +	.card_rx_len = 0x62, +	.card_rx_unit = 0x63, +	.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 = { +	.cfg = 0x00, +	.host_int_mask = 0x02, +	.host_intstatus = 0x03, +	.card_status = 0x50, +	.sq_read_base_addr_a0 = 0x60, +	.sq_read_base_addr_a1 = 0x61, +	.card_revision = 0xbc, +	.card_fw_status0 = 0xc0, +	.card_fw_status1 = 0xc1, +	.card_rx_len = 0xc2, +	.card_rx_unit = 0xc3, +	.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 = { +	.helper		= "mrvl/sd8688_helper.bin", +	.firmware	= "mrvl/sd8688.bin", +	.reg		= &btmrvl_reg_8688, +	.sd_blksz_fw_dl	= 64, +}; + +static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { +	.helper		= NULL, +	.firmware	= "mrvl/sd8787_uapsta.bin", +	.reg		= &btmrvl_reg_87xx, +	.sd_blksz_fw_dl	= 256, +}; + +static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { +	.helper		= NULL, +	.firmware	= "mrvl/sd8797_uapsta.bin", +	.reg		= &btmrvl_reg_87xx, +	.sd_blksz_fw_dl	= 256, +}; + +static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { +	.helper		= NULL, +	.firmware	= "mrvl/sd8897_uapsta.bin", +	.reg		= &btmrvl_reg_88xx, +	.sd_blksz_fw_dl	= 256,  };  static const struct sdio_device_id btmrvl_sdio_ids[] = {  	/* Marvell SD8688 Bluetooth device */  	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105), -			.driver_data = (unsigned long) &btmrvl_sdio_sd6888 }, +			.driver_data = (unsigned long) &btmrvl_sdio_sd8688 }, +	/* Marvell SD8787 Bluetooth device */ +	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), +			.driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, +	/* Marvell SD8787 Bluetooth AMP device */ +	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B), +			.driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, +	/* Marvell SD8797 Bluetooth device */ +	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), +			.driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, +	/* Marvell SD8897 Bluetooth device */ +	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E), +			.driver_data = (unsigned long) &btmrvl_sdio_sd8897 },  	{ }	/* Terminating entry */  }; @@ -69,7 +159,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)  	u8 reg;  	int ret; -	reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret); +	reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);  	if (!ret)  		card->rx_unit = reg; @@ -83,11 +173,11 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)  	*dat = 0; -	fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret); +	fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);  	if (ret)  		return -EIO; -	fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret); +	fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);  	if (ret)  		return -EIO; @@ -101,7 +191,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)  	u8 reg;  	int ret; -	reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret); +	reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);  	if (!ret)  		*dat = (u16) reg << card->rx_unit; @@ -113,7 +203,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,  {  	int ret; -	sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret); +	sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);  	if (ret) {  		BT_ERR("Unable to enable the host interrupt!");  		ret = -EIO; @@ -128,13 +218,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,  	u8 host_int_mask;  	int ret; -	host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret); +	host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);  	if (ret)  		return -EIO;  	host_int_mask &= ~mask; -	sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret); +	sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);  	if (ret < 0) {  		BT_ERR("Unable to disable the host interrupt!");  		return -EIO; @@ -150,7 +240,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)  	int ret;  	for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) { -		status = sdio_readb(card->func, CARD_STATUS_REG, &ret); +		status = sdio_readb(card->func, card->reg->card_status,	&ret);  		if (ret)  			goto failed;  		if ((status & bits) == bits) @@ -170,24 +260,24 @@ failed:  static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,  								int pollnum)  { -	int ret = -ETIMEDOUT;  	u16 firmwarestat; -	unsigned int tries; +	int tries, ret;  	 /* Wait for firmware to become ready */  	for (tries = 0; tries < pollnum; tries++) { -		if (btmrvl_sdio_read_fw_status(card, &firmwarestat) < 0) +		sdio_claim_host(card->func); +		ret = btmrvl_sdio_read_fw_status(card, &firmwarestat); +		sdio_release_host(card->func); +		if (ret < 0)  			continue; -		if (firmwarestat == FIRMWARE_READY) { -			ret = 0; -			break; -		} else { -			msleep(10); -		} +		if (firmwarestat == FIRMWARE_READY) +			return 0; + +		msleep(10);  	} -	return ret; +	return -ETIMEDOUT;  }  static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) @@ -284,9 +374,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)  done:  	kfree(tmphlprbuf); -	if (fw_helper) -		release_firmware(fw_helper); - +	release_firmware(fw_helper);  	return ret;  } @@ -299,7 +387,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  	u8 base0, base1;  	void *tmpfwbuf = NULL;  	u8 *fwbuf; -	u16 len; +	u16 len, blksz_dl = card->sd_blksz_fw_dl;  	int txlen = 0, tx_blocks = 0, count = 0;  	ret = request_firmware(&fw_firmware, card->firmware, @@ -345,7 +433,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {  			base0 = sdio_readb(card->func, -					SQ_READ_BASE_ADDRESS_A0_REG, &ret); +					card->reg->sq_read_base_addr_a0, &ret);  			if (ret) {  				BT_ERR("BASE0 register read failed:"  					" base0 = 0x%04X(%d)." @@ -355,7 +443,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  				goto done;  			}  			base1 = sdio_readb(card->func, -					SQ_READ_BASE_ADDRESS_A1_REG, &ret); +					card->reg->sq_read_base_addr_a1, &ret);  			if (ret) {  				BT_ERR("BASE1 register read failed:"  					" base1 = 0x%04X(%d)." @@ -403,20 +491,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  			if (firmwarelen - offset < txlen)  				txlen = firmwarelen - offset; -			tx_blocks = -			    (txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE; +			tx_blocks = DIV_ROUND_UP(txlen, blksz_dl);  			memcpy(fwbuf, &firmware[offset], txlen);  		}  		ret = sdio_writesb(card->func, card->ioport, fwbuf, -					tx_blocks * SDIO_BLOCK_SIZE); +						tx_blocks * blksz_dl);  		if (ret < 0) {  			BT_ERR("FW download, writesb(%d) failed @%d",  							count, offset); -			sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG, -									&ret); +			sdio_writeb(card->func, HOST_CMD53_FIN, +						card->reg->cfg, &ret);  			if (ret)  				BT_ERR("writeb failed (CFG)");  		} @@ -430,17 +517,14 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)  done:  	kfree(tmpfwbuf); - -	if (fw_firmware) -		release_firmware(fw_firmware); - +	release_firmware(fw_firmware);  	return ret;  }  static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)  {  	u16 buf_len = 0; -	int ret, buf_block_len, blksz; +	int ret, num_blocks, blksz;  	struct sk_buff *skb = NULL;  	u32 type;  	u8 *payload = NULL; @@ -462,20 +546,20 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)  	}  	blksz = SDIO_BLOCK_SIZE; -	buf_block_len = (buf_len + blksz - 1) / blksz; +	num_blocks = DIV_ROUND_UP(buf_len, blksz);  	if (buf_len <= SDIO_HEADER_LEN -			|| (buf_block_len * blksz) > ALLOC_BUF_SIZE) { +	    || (num_blocks * blksz) > ALLOC_BUF_SIZE) {  		BT_ERR("invalid packet length: %d", buf_len);  		ret = -EINVAL;  		goto exit;  	}  	/* Allocate buffer */ -	skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN, -								GFP_ATOMIC); +	skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);  	if (skb == NULL) {  		BT_ERR("No free skb"); +		ret = -ENOMEM;  		goto exit;  	} @@ -489,7 +573,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)  	payload = skb->data;  	ret = sdio_readsb(card->func, payload, card->ioport, -			  buf_block_len * blksz); +			  num_blocks * blksz);  	if (ret < 0) {  		BT_ERR("readsb failed: %d", ret);  		ret = -EIO; @@ -501,7 +585,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)  	 */  	buf_len = payload[0]; -	buf_len |= (u16) payload[1] << 8; +	buf_len |= payload[1] << 8; +	buf_len |= payload[2] << 16; + +	if (buf_len > blksz * num_blocks) { +		BT_ERR("Skip incorrect packet: hdrlen %d buffer %d", +		       buf_len, blksz * num_blocks); +		ret = -EIO; +		goto exit; +	} +  	type = payload[3];  	switch (type) { @@ -509,33 +602,33 @@ 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) -			btmrvl_check_evtpkt(priv, skb); +		if (type == HCI_EVENT_PKT) { +			if (btmrvl_check_evtpkt(priv, skb)) +				hci_recv_frame(hdev, skb); +		} else { +			hci_recv_frame(hdev, skb); +		} -		hci_recv_frame(skb);  		hdev->stat.byte_rx += buf_len;  		break;  	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;  	default:  		BT_ERR("Unknown packet type:%d", type); -		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload, -						blksz * buf_block_len); +		BT_ERR("hex: %*ph", blksz * num_blocks, payload);  		kfree_skb(skb);  		skb = NULL; @@ -545,8 +638,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)  exit:  	if (ret) {  		hdev->stat.err_rx++; -		if (skb) -			kfree_skb(skb); +		kfree_skb(skb);  	}  	return ret; @@ -580,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); + +	return 0; +} -	ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); +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), -				HOST_INTSTATUS_REG, &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); @@ -664,7 +788,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)  		goto release_irq;  	} -	reg = sdio_readb(func, IO_PORT_0_REG, &ret); +	reg = sdio_readb(func, card->reg->io_port_0, &ret);  	if (ret < 0) {  		ret = -EIO;  		goto release_irq; @@ -672,7 +796,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)  	card->ioport = reg; -	reg = sdio_readb(func, IO_PORT_1_REG, &ret); +	reg = sdio_readb(func, card->reg->io_port_1, &ret);  	if (ret < 0) {  		ret = -EIO;  		goto release_irq; @@ -680,7 +804,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)  	card->ioport |= (reg << 8); -	reg = sdio_readb(func, IO_PORT_2_REG, &ret); +	reg = sdio_readb(func, card->reg->io_port_2, &ret);  	if (ret < 0) {  		ret = -EIO;  		goto release_irq; @@ -690,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); @@ -784,7 +932,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,  	}  	blksz = SDIO_BLOCK_SIZE; -	buf_block_len = (nb + blksz - 1) / blksz; +	buf_block_len = DIV_ROUND_UP(nb, blksz);  	sdio_claim_host(card->func); @@ -795,8 +943,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,  		if (ret < 0) {  			i++;  			BT_ERR("i=%d writesb failed: %d", i, ret); -			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, -						payload, nb); +			BT_ERR("hex: %*ph", nb, payload);  			ret = -EIO;  			if (i > MAX_WRITE_IOMEM_RETRY)  				goto exit; @@ -814,41 +961,66 @@ exit:  static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)  { -	int ret = 0; +	int ret; +	u8 fws0; +	int pollnum = MAX_POLL_TRIES;  	if (!card || !card->func) {  		BT_ERR("card or function is NULL!");  		return -EINVAL;  	} -	sdio_claim_host(card->func);  	if (!btmrvl_sdio_verify_fw_download(card, 1)) {  		BT_DBG("Firmware already downloaded!"); -		goto done; +		return 0;  	} -	ret = btmrvl_sdio_download_helper(card); +	sdio_claim_host(card->func); + +	/* Check if other function driver is downloading the firmware */ +	fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);  	if (ret) { -		BT_ERR("Failed to download helper!"); +		BT_ERR("Failed to read FW downloading status!");  		ret = -EIO;  		goto done;  	} +	if (fws0) { +		BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0); + +		/* Give other function more time to download the firmware */ +		pollnum *= 10; +	} else { +		if (card->helper) { +			ret = btmrvl_sdio_download_helper(card); +			if (ret) { +				BT_ERR("Failed to download helper!"); +				ret = -EIO; +				goto done; +			} +		} -	if (btmrvl_sdio_download_fw_w_helper(card)) { -		BT_ERR("Failed to download firmware!"); -		ret = -EIO; -		goto done; +		if (btmrvl_sdio_download_fw_w_helper(card)) { +			BT_ERR("Failed to download firmware!"); +			ret = -EIO; +			goto done; +		}  	} -	if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) { +	sdio_release_host(card->func); + +	/* +	 * winner or not, with this test the FW synchronizes when the +	 * module can continue its initialization +	 */ +	if (btmrvl_sdio_verify_fw_download(card, pollnum)) {  		BT_ERR("FW failed to be active in time!"); -		ret = -ETIMEDOUT; -		goto done; +		return -ETIMEDOUT;  	} +	return 0; +  done:  	sdio_release_host(card->func); -  	return ret;  } @@ -864,7 +1036,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)  	sdio_claim_host(card->func); -	sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret); +	sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);  	sdio_release_host(card->func); @@ -883,24 +1055,23 @@ static int btmrvl_sdio_probe(struct sdio_func *func,  	BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",  			id->vendor, id->device, id->class, func->num); -	card = kzalloc(sizeof(*card), GFP_KERNEL); -	if (!card) { -		ret = -ENOMEM; -		goto done; -	} +	card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL); +	if (!card) +		return -ENOMEM;  	card->func = func;  	if (id->driver_data) {  		struct btmrvl_sdio_device *data = (void *) id->driver_data; -		card->helper   = data->helper; +		card->helper = data->helper;  		card->firmware = data->firmware; +		card->reg = data->reg; +		card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;  	}  	if (btmrvl_sdio_register_dev(card) < 0) {  		BT_ERR("Failed to register BT device!"); -		ret = -ENODEV; -		goto free_card; +		return -ENODEV;  	}  	/* Disable the interrupts on the card */ @@ -912,8 +1083,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,  		goto unreg_dev;  	} -	msleep(100); -  	btmrvl_sdio_enable_host_int(card);  	priv = btmrvl_add_card(card); @@ -936,18 +1105,12 @@ static int btmrvl_sdio_probe(struct sdio_func *func,  		goto disable_host_int;  	} -	priv->btmrvl_dev.psmode = 1; -	btmrvl_enable_ps(priv); -  	return 0;  disable_host_int:  	btmrvl_sdio_disable_host_int(card);  unreg_dev:  	btmrvl_sdio_unregister_dev(card); -free_card: -	kfree(card); -done:  	return ret;  } @@ -969,16 +1132,115 @@ static void btmrvl_sdio_remove(struct sdio_func *func)  			BT_DBG("unregester dev");  			btmrvl_sdio_unregister_dev(card);  			btmrvl_remove_card(card->priv); -			kfree(card);  		}  	}  } +static int btmrvl_sdio_suspend(struct device *dev) +{ +	struct sdio_func *func = dev_to_sdio_func(dev); +	struct btmrvl_sdio_card *card; +	struct btmrvl_private *priv; +	mmc_pm_flag_t pm_flags; +	struct hci_dev *hcidev; + +	if (func) { +		pm_flags = sdio_get_host_pm_caps(func); +		BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func), +		       pm_flags); +		if (!(pm_flags & MMC_PM_KEEP_POWER)) { +			BT_ERR("%s: cannot remain alive while suspended", +			       sdio_func_id(func)); +			return -ENOSYS; +		} +		card = sdio_get_drvdata(func); +		if (!card || !card->priv) { +			BT_ERR("card or priv structure is not valid"); +			return 0; +		} +	} else { +		BT_ERR("sdio_func is not specified"); +		return 0; +	} + +	priv = card->priv; + +	if (priv->adapter->hs_state != HS_ACTIVATED) { +		if (btmrvl_enable_hs(priv)) { +			BT_ERR("HS not actived, suspend failed!"); +			return -EBUSY; +		} +	} +	hcidev = priv->btmrvl_dev.hcidev; +	BT_DBG("%s: SDIO suspend", hcidev->name); +	hci_suspend_dev(hcidev); +	skb_queue_purge(&priv->adapter->tx_queue); + +	priv->adapter->is_suspended = true; + +	/* We will keep the power when hs enabled successfully */ +	if (priv->adapter->hs_state == HS_ACTIVATED) { +		BT_DBG("suspend with MMC_PM_KEEP_POWER"); +		return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); +	} else { +		BT_DBG("suspend without MMC_PM_KEEP_POWER"); +		return 0; +	} +} + +static int btmrvl_sdio_resume(struct device *dev) +{ +	struct sdio_func *func = dev_to_sdio_func(dev); +	struct btmrvl_sdio_card *card; +	struct btmrvl_private *priv; +	mmc_pm_flag_t pm_flags; +	struct hci_dev *hcidev; + +	if (func) { +		pm_flags = sdio_get_host_pm_caps(func); +		BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func), +		       pm_flags); +		card = sdio_get_drvdata(func); +		if (!card || !card->priv) { +			BT_ERR("card or priv structure is not valid"); +			return 0; +		} +	} else { +		BT_ERR("sdio_func is not specified"); +		return 0; +	} +	priv = card->priv; + +	if (!priv->adapter->is_suspended) { +		BT_DBG("device already resumed"); +		return 0; +	} + +	priv->adapter->is_suspended = false; +	hcidev = priv->btmrvl_dev.hcidev; +	BT_DBG("%s: SDIO resume", hcidev->name); +	hci_resume_dev(hcidev); +	priv->hw_wakeup_firmware(priv); +	priv->adapter->hs_state = HS_DEACTIVATED; +	BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); + +	return 0; +} + +static const struct dev_pm_ops btmrvl_sdio_pm_ops = { +	.suspend	= btmrvl_sdio_suspend, +	.resume		= btmrvl_sdio_resume, +}; +  static struct sdio_driver bt_mrvl_sdio = {  	.name		= "btmrvl_sdio",  	.id_table	= btmrvl_sdio_ids,  	.probe		= btmrvl_sdio_probe,  	.remove		= btmrvl_sdio_remove, +	.drv = { +		.owner = THIS_MODULE, +		.pm = &btmrvl_sdio_pm_ops, +	}  };  static int __init btmrvl_sdio_init_module(void) @@ -1009,5 +1271,8 @@ MODULE_AUTHOR("Marvell International Ltd.");  MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);  MODULE_VERSION(VERSION);  MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE("sd8688_helper.bin"); -MODULE_FIRMWARE("sd8688.bin"); +MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); +MODULE_FIRMWARE("mrvl/sd8688.bin"); +MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); +MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); +MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h index 27329f107e5..d4dd3b0fa53 100644 --- a/drivers/bluetooth/btmrvl_sdio.h +++ b/drivers/bluetooth/btmrvl_sdio.h @@ -47,44 +47,49 @@  /* Max retry number of CMD53 write */  #define MAX_WRITE_IOMEM_RETRY		2 -/* Host Control Registers */ -#define IO_PORT_0_REG			0x00 -#define IO_PORT_1_REG			0x01 -#define IO_PORT_2_REG			0x02 - -#define CONFIG_REG			0x03 -#define HOST_POWER_UP			BIT(1) -#define HOST_CMD53_FIN			BIT(2) - -#define HOST_INT_MASK_REG		0x04 -#define HIM_DISABLE			0xff -#define HIM_ENABLE			(BIT(0) | BIT(1)) - -#define HOST_INTSTATUS_REG		0x05 -#define UP_LD_HOST_INT_STATUS		BIT(0) -#define DN_LD_HOST_INT_STATUS		BIT(1) - -/* Card Control Registers */ -#define SQ_READ_BASE_ADDRESS_A0_REG  	0x10 -#define SQ_READ_BASE_ADDRESS_A1_REG  	0x11 - -#define CARD_STATUS_REG              	0x20 -#define DN_LD_CARD_RDY               	BIT(0) -#define CARD_IO_READY              	BIT(3) - -#define CARD_FW_STATUS0_REG		0x40 -#define CARD_FW_STATUS1_REG		0x41 -#define FIRMWARE_READY			0xfedc - -#define CARD_RX_LEN_REG			0x42 -#define CARD_RX_UNIT_REG		0x43 - +/* register bitmasks */ +#define HOST_POWER_UP				BIT(1) +#define HOST_CMD53_FIN				BIT(2) + +#define HIM_DISABLE				0xff +#define HIM_ENABLE				(BIT(0) | BIT(1)) + +#define UP_LD_HOST_INT_STATUS			BIT(0) +#define DN_LD_HOST_INT_STATUS			BIT(1) + +#define DN_LD_CARD_RDY				BIT(0) +#define CARD_IO_READY				BIT(3) + +#define FIRMWARE_READY				0xfedc + + +struct btmrvl_sdio_card_reg { +	u8 cfg; +	u8 host_int_mask; +	u8 host_intstatus; +	u8 card_status; +	u8 sq_read_base_addr_a0; +	u8 sq_read_base_addr_a1; +	u8 card_revision; +	u8 card_fw_status0; +	u8 card_fw_status1; +	u8 card_rx_len; +	u8 card_rx_unit; +	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 {  	struct sdio_func *func;  	u32 ioport;  	const char *helper;  	const char *firmware; +	const struct btmrvl_sdio_card_reg *reg; +	u16 sd_blksz_fw_dl;  	u8 rx_unit;  	struct btmrvl_private *priv;  }; @@ -92,6 +97,8 @@ struct btmrvl_sdio_card {  struct btmrvl_sdio_device {  	const char *helper;  	const char *firmware; +	const struct btmrvl_sdio_card_reg *reg; +	u16 sd_blksz_fw_dl;  }; diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 792e32d29a1..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; @@ -189,7 +189,7 @@ static void btsdio_interrupt(struct sdio_func *func)  static int btsdio_open(struct hci_dev *hdev)  { -	struct btsdio_data *data = hdev->driver_data; +	struct btsdio_data *data = hci_get_drvdata(hdev);  	int err;  	BT_DBG("%s", hdev->name); @@ -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); @@ -225,7 +225,7 @@ release:  static int btsdio_close(struct hci_dev *hdev)  { -	struct btsdio_data *data = hdev->driver_data; +	struct btsdio_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s", hdev->name); @@ -246,7 +246,7 @@ static int btsdio_close(struct hci_dev *hdev)  static int btsdio_flush(struct hci_dev *hdev)  { -	struct btsdio_data *data = hdev->driver_data; +	struct btsdio_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s", hdev->name); @@ -255,10 +255,9 @@ 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 = hdev->driver_data; +	struct btsdio_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s", hdev->name); @@ -289,15 +288,6 @@ static int btsdio_send_frame(struct sk_buff *skb)  	return 0;  } -static void btsdio_destruct(struct hci_dev *hdev) -{ -	struct btsdio_data *data = hdev->driver_data; - -	BT_DBG("%s", hdev->name); - -	kfree(data); -} -  static int btsdio_probe(struct sdio_func *func,  				const struct sdio_device_id *id)  { @@ -313,7 +303,7 @@ static int btsdio_probe(struct sdio_func *func,  		tuple = tuple->next;  	} -	data = kzalloc(sizeof(*data), GFP_KERNEL); +	data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);  	if (!data)  		return -ENOMEM; @@ -324,13 +314,11 @@ static int btsdio_probe(struct sdio_func *func,  	skb_queue_head_init(&data->txq);  	hdev = hci_alloc_dev(); -	if (!hdev) { -		kfree(data); +	if (!hdev)  		return -ENOMEM; -	}  	hdev->bus = HCI_SDIO; -	hdev->driver_data = data; +	hci_set_drvdata(hdev, data);  	if (id->class == SDIO_CLASS_BT_AMP)  		hdev->dev_type = HCI_AMP; @@ -345,14 +333,13 @@ static int btsdio_probe(struct sdio_func *func,  	hdev->close    = btsdio_close;  	hdev->flush    = btsdio_flush;  	hdev->send     = btsdio_send_frame; -	hdev->destruct = btsdio_destruct; -	hdev->owner = THIS_MODULE; +	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); -		kfree(data);  		return err;  	} diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index f8a0708e231..fb948f02eda 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -38,7 +38,6 @@  #include <linux/serial.h>  #include <linux/serial_reg.h>  #include <linux/bitops.h> -#include <asm/system.h>  #include <asm/io.h>  #include <pcmcia/cistpl.h> @@ -141,16 +140,17 @@ static void btuart_write_wakeup(btuart_info_t *info)  	}  	do { -		register unsigned int iobase = info->p_dev->resource[0]->start; +		unsigned int iobase = info->p_dev->resource[0]->start;  		register struct sk_buff *skb; -		register int len; +		int len;  		clear_bit(XMIT_WAKEUP, &(info->tx_state));  		if (!pcmcia_dev_present(info->p_dev))  			return; -		if (!(skb = skb_dequeue(&(info->txq)))) +		skb = skb_dequeue(&(info->txq)); +		if (!skb)  			break;  		/* Send frame */ @@ -191,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;  			} @@ -199,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) { @@ -266,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; @@ -397,7 +397,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)  static int btuart_hci_flush(struct hci_dev *hdev)  { -	btuart_info_t *info = (btuart_info_t *)(hdev->driver_data); +	btuart_info_t *info = hci_get_drvdata(hdev);  	/* Drop TX queue */  	skb_queue_purge(&(info->txq)); @@ -425,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 = (btuart_info_t *)(hdev->driver_data); +	btuart_info_t *info = hci_get_drvdata(hdev);  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT: @@ -447,7 +439,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb)  	case HCI_SCODATA_PKT:  		hdev->stat.sco_tx++;  		break; -	}; +	}  	/* Prepend skb with frame type */  	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); @@ -459,17 +451,6 @@ static int btuart_hci_send_frame(struct sk_buff *skb)  } -static void btuart_hci_destruct(struct hci_dev *hdev) -{ -} - - -static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -  /* ======================== Card services HCI interaction ======================== */ @@ -498,17 +479,13 @@ static int btuart_open(btuart_info_t *info)  	info->hdev = hdev;  	hdev->bus = HCI_PCCARD; -	hdev->driver_data = 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->destruct = btuart_hci_destruct; -	hdev->ioctl    = btuart_hci_ioctl; - -	hdev->owner = THIS_MODULE; +	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); @@ -565,9 +542,7 @@ static int btuart_close(btuart_info_t *info)  	spin_unlock_irqrestore(&(info->lock), flags); -	if (hci_unregister_dev(hdev) < 0) -		BT_ERR("Can't unregister HCI device %s", hdev->name); - +	hci_unregister_dev(hdev);  	hci_free_dev(hdev);  	return 0; @@ -578,7 +553,7 @@ static int btuart_probe(struct pcmcia_device *link)  	btuart_info_t *info;  	/* Create new info device */ -	info = kzalloc(sizeof(*info), GFP_KERNEL); +	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);  	if (!info)  		return -ENOMEM; @@ -594,17 +569,14 @@ static int btuart_probe(struct pcmcia_device *link)  static void btuart_detach(struct pcmcia_device *link)  { -	btuart_info_t *info = link->priv; -  	btuart_release(link); -	kfree(info);  }  static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)  {  	int *try = priv_data; -	if (try == 0) +	if (!try)  		p_dev->io_lines = 16;  	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0)) @@ -689,7 +661,7 @@ static void btuart_release(struct pcmcia_device *link)  	pcmcia_disable_device(link);  } -static struct pcmcia_device_id btuart_ids[] = { +static const struct pcmcia_device_id btuart_ids[] = {  	/* don't use this driver. Use serial_cs + hci_uart instead */  	PCMCIA_DEVICE_NULL  }; @@ -702,17 +674,4 @@ static struct pcmcia_driver btuart_driver = {  	.remove		= btuart_detach,  	.id_table	= btuart_ids,  }; - -static int __init init_btuart_cs(void) -{ -	return pcmcia_register_driver(&btuart_driver); -} - - -static void __exit exit_btuart_cs(void) -{ -	pcmcia_unregister_driver(&btuart_driver); -} - -module_init(init_btuart_cs); -module_exit(exit_btuart_cs); +module_pcmcia_driver(btuart_driver); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index ab3894f742c..6250fc2fb93 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -21,29 +21,22 @@   *   */ -#include <linux/kernel.h>  #include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/skbuff.h> -  #include <linux/usb.h> +#include <linux/firmware.h>  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h>  #define VERSION "0.6" -static int ignore_dga; -static int ignore_csr; -static int ignore_sniffer; -static int disable_scofix; -static int force_scofix; +static bool ignore_dga; +static bool ignore_csr; +static bool ignore_sniffer; +static bool disable_scofix; +static bool force_scofix; -static int reset = 1; +static bool reset = 1;  static struct usb_driver btusb_driver; @@ -54,11 +47,23 @@ static struct usb_driver btusb_driver;  #define BTUSB_BCM92035		0x10  #define BTUSB_BROKEN_ISOC	0x20  #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) }, +	/* Apple-specific (Broadcom) devices */ +	{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, + +	/* MediaTek MT76x0E */ +	{ USB_DEVICE(0x0e8d, 0x763f) }, + +	/* Broadcom SoftSailing reporting vendor specific */ +	{ USB_DEVICE(0x0a5c, 0x21e1) }, +  	/* Apple MacBookPro 7,1 */  	{ USB_DEVICE(0x05ac, 0x8213) }, @@ -71,6 +76,15 @@ static struct usb_device_id btusb_table[] = {  	/* Apple MacBookAir3,1, MacBookAir3,2 */  	{ USB_DEVICE(0x05ac, 0x821b) }, +	/* Apple MacBookAir4,1 */ +	{ USB_DEVICE(0x05ac, 0x821f) }, + +	/* Apple MacBookPro8,2 */ +	{ USB_DEVICE(0x05ac, 0x821a) }, + +	/* Apple MacMini5,1 */ +	{ USB_DEVICE(0x05ac, 0x8281) }, +  	/* AVM BlueFRITZ! USB v2.0 */  	{ USB_DEVICE(0x057c, 0x3800) }, @@ -87,22 +101,92 @@ static struct usb_device_id btusb_table[] = {  	/* Canyon CN-BTU1 with HID interfaces */  	{ USB_DEVICE(0x0c10, 0x0000) }, +	/* Broadcom BCM20702A0 */ +	{ USB_DEVICE(0x0489, 0xe042) }, +	{ USB_DEVICE(0x04ca, 0x2003) }, +	{ USB_DEVICE(0x0b05, 0x17b5) }, +	{ USB_DEVICE(0x0b05, 0x17cb) }, +	{ 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), +	  .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 },  	/* Broadcom BCM2033 without firmware */  	{ 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 }, + +	/* 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(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0cf3, 0xe005), .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(0x13d3, 0x3402), .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, 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 }, @@ -149,6 +233,10 @@ static struct usb_device_id blacklist_table[] = {  	/* Frontline ComProbe Bluetooth Sniffer */  	{ USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER }, +	/* Intel Bluetooth device */ +	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, +	{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, +  	{ }	/* Terminating entry */  }; @@ -211,7 +299,7 @@ static int inc_tx(struct btusb_data *data)  static void btusb_intr_complete(struct urb *urb)  {  	struct hci_dev *hdev = urb->context; -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	int err;  	BT_DBG("%s urb %p status %d count %d", hdev->name, @@ -239,7 +327,10 @@ static void btusb_intr_complete(struct urb *urb)  	err = usb_submit_urb(urb, GFP_ATOMIC);  	if (err < 0) { -		BT_ERR("%s urb %p failed to resubmit (%d)", +		/* -EPERM: urb is being killed; +		 * -ENODEV: device got disconnected */ +		if (err != -EPERM && err != -ENODEV) +			BT_ERR("%s urb %p failed to resubmit (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb);  	} @@ -247,7 +338,7 @@ static void btusb_intr_complete(struct urb *urb)  static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)  { -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	struct urb *urb;  	unsigned char *buf;  	unsigned int pipe; @@ -282,7 +373,8 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)  	err = usb_submit_urb(urb, mem_flags);  	if (err < 0) { -		BT_ERR("%s urb %p submission failed (%d)", +		if (err != -EPERM && err != -ENODEV) +			BT_ERR("%s urb %p submission failed (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb);  	} @@ -295,7 +387,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)  static void btusb_bulk_complete(struct urb *urb)  {  	struct hci_dev *hdev = urb->context; -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	int err;  	BT_DBG("%s urb %p status %d count %d", hdev->name, @@ -323,7 +415,10 @@ static void btusb_bulk_complete(struct urb *urb)  	err = usb_submit_urb(urb, GFP_ATOMIC);  	if (err < 0) { -		BT_ERR("%s urb %p failed to resubmit (%d)", +		/* -EPERM: urb is being killed; +		 * -ENODEV: device got disconnected */ +		if (err != -EPERM && err != -ENODEV) +			BT_ERR("%s urb %p failed to resubmit (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb);  	} @@ -331,7 +426,7 @@ static void btusb_bulk_complete(struct urb *urb)  static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)  { -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	struct urb *urb;  	unsigned char *buf;  	unsigned int pipe; @@ -364,7 +459,8 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)  	err = usb_submit_urb(urb, mem_flags);  	if (err < 0) { -		BT_ERR("%s urb %p submission failed (%d)", +		if (err != -EPERM && err != -ENODEV) +			BT_ERR("%s urb %p submission failed (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb);  	} @@ -377,7 +473,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)  static void btusb_isoc_complete(struct urb *urb)  {  	struct hci_dev *hdev = urb->context; -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	int i, err;  	BT_DBG("%s urb %p status %d count %d", hdev->name, @@ -412,13 +508,16 @@ static void btusb_isoc_complete(struct urb *urb)  	err = usb_submit_urb(urb, GFP_ATOMIC);  	if (err < 0) { -		BT_ERR("%s urb %p failed to resubmit (%d)", +		/* -EPERM: urb is being killed; +		 * -ENODEV: device got disconnected */ +		if (err != -EPERM && err != -ENODEV) +			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) +static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)  {  	int i, offset = 0; @@ -441,7 +540,7 @@ static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)  static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)  { -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	struct urb *urb;  	unsigned char *buf;  	unsigned int pipe; @@ -467,15 +566,10 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)  	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; +	usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete, +				hdev, 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)); @@ -484,7 +578,8 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)  	err = usb_submit_urb(urb, mem_flags);  	if (err < 0) { -		BT_ERR("%s urb %p submission failed (%d)", +		if (err != -EPERM && err != -ENODEV) +			BT_ERR("%s urb %p submission failed (%d)",  						hdev->name, urb, -err);  		usb_unanchor_urb(urb);  	} @@ -498,7 +593,7 @@ static void btusb_tx_complete(struct urb *urb)  {  	struct sk_buff *skb = urb->context;  	struct hci_dev *hdev = (struct hci_dev *) skb->dev; -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s urb %p status %d count %d", hdev->name,  					urb, urb->status, urb->actual_length); @@ -545,7 +640,7 @@ done:  static int btusb_open(struct hci_dev *hdev)  { -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	int err;  	BT_DBG("%s", hdev->name); @@ -595,7 +690,7 @@ static void btusb_stop_traffic(struct btusb_data *data)  static int btusb_close(struct hci_dev *hdev)  { -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	int err;  	BT_DBG("%s", hdev->name); @@ -625,7 +720,7 @@ failed:  static int btusb_flush(struct hci_dev *hdev)  { -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	BT_DBG("%s", hdev->name); @@ -634,10 +729,9 @@ 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 = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	struct usb_ctrlrequest *dr;  	struct urb *urb;  	unsigned int pipe; @@ -648,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); @@ -675,7 +771,7 @@ 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) +		if (!data->bulk_tx_ep)  			return -ENODEV;  		urb = usb_alloc_urb(0, GFP_ATOMIC); @@ -692,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); @@ -702,15 +798,11 @@ static int btusb_send_frame(struct sk_buff *skb)  		pipe = usb_sndisocpipe(data->udev,  					data->isoc_tx_ep->bEndpointAddress); -		urb->dev      = data->udev; -		urb->pipe     = pipe; -		urb->context  = skb; -		urb->complete = btusb_isoc_tx_complete; -		urb->interval = data->isoc_tx_ep->bInterval; +		usb_fill_int_urb(urb, data->udev, pipe, +				skb->data, skb->len, btusb_isoc_tx_complete, +				skb, 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)); @@ -735,43 +827,35 @@ skip_waking:  	err = usb_submit_urb(urb, GFP_ATOMIC);  	if (err < 0) { -		BT_ERR("%s urb %p submission failed", hdev->name, urb); +		if (err != -EPERM && err != -ENODEV) +			BT_ERR("%s urb %p submission failed (%d)", +						hdev->name, urb, -err);  		kfree(urb->setup_packet);  		usb_unanchor_urb(urb);  	} else {  		usb_mark_last_busy(data->udev);  	} -	usb_free_urb(urb); -  done: +	usb_free_urb(urb);  	return err;  } -static void btusb_destruct(struct hci_dev *hdev) -{ -	struct btusb_data *data = hdev->driver_data; - -	BT_DBG("%s", hdev->name); - -	kfree(data); -} -  static void btusb_notify(struct hci_dev *hdev, unsigned int evt)  { -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	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);  	}  } -static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting) +static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)  { -	struct btusb_data *data = hdev->driver_data; +	struct btusb_data *data = hci_get_drvdata(hdev);  	struct usb_interface *intf = data->isoc;  	struct usb_endpoint_descriptor *ep_desc;  	int i, err; @@ -816,11 +900,12 @@ 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; +	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); +			err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf);  			if (err < 0) {  				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);  				usb_kill_anchored_urbs(&data->isoc_anchor); @@ -829,11 +914,19 @@ static void btusb_work(struct work_struct *work)  			set_bit(BTUSB_DID_ISO_RESUME, &data->flags);  		} -		if (data->isoc_altsetting != 2) { + +		if (hdev->voice_setting & 0x0020) { +			static const int alts[3] = { 2, 4, 5 }; +			new_alts = alts[data->sco_num - 1]; +		} else { +			new_alts = data->sco_num; +		} + +		if (data->isoc_altsetting != new_alts) {  			clear_bit(BTUSB_ISOC_RUNNING, &data->flags);  			usb_kill_anchored_urbs(&data->isoc_anchor); -			if (__set_isoc_interface(hdev, 2) < 0) +			if (__set_isoc_interface(hdev, new_alts) < 0)  				return;  		} @@ -849,7 +942,7 @@ static void btusb_work(struct work_struct *work)  		__set_isoc_interface(hdev, 0);  		if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags)) -			usb_autopm_put_interface(data->isoc); +			usb_autopm_put_interface(data->isoc ? data->isoc : data->intf);  	}  } @@ -865,6 +958,578 @@ static void btusb_waker(struct work_struct *work)  	usb_autopm_put_interface(data->intf);  } +static int btusb_setup_bcm92035(struct hci_dev *hdev) +{ +	struct sk_buff *skb; +	u8 val = 0x00; + +	BT_DBG("%s", hdev->name); + +	skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) +		BT_ERR("BCM92035 command failed (%ld)", -PTR_ERR(skb)); +	else +		kfree_skb(skb); + +	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; +	u8 hw_variant; +	u8 hw_revision; +	u8 fw_variant; +	u8 fw_revision; +	u8 fw_build_num; +	u8 fw_build_ww; +	u8 fw_build_yy; +	u8 fw_patch_num; +} __packed; + +static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev, +						struct intel_version *ver) +{ +	const struct firmware *fw; +	char fwname[64]; +	int ret; + +	snprintf(fwname, sizeof(fwname), +		 "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq", +		 ver->hw_platform, ver->hw_variant, ver->hw_revision, +		 ver->fw_variant,  ver->fw_revision, ver->fw_build_num, +		 ver->fw_build_ww, ver->fw_build_yy); + +	ret = request_firmware(&fw, fwname, &hdev->dev); +	if (ret < 0) { +		if (ret == -EINVAL) { +			BT_ERR("%s Intel firmware file request failed (%d)", +			       hdev->name, ret); +			return NULL; +		} + +		BT_ERR("%s failed to open Intel firmware file: %s(%d)", +		       hdev->name, fwname, ret); + +		/* If the correct firmware patch file is not found, use the +		 * default firmware patch file instead +		 */ +		snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq", +			 ver->hw_platform, ver->hw_variant); +		if (request_firmware(&fw, fwname, &hdev->dev) < 0) { +			BT_ERR("%s failed to open default Intel fw file: %s", +			       hdev->name, fwname); +			return NULL; +		} +	} + +	BT_INFO("%s: Intel Bluetooth firmware file: %s", hdev->name, fwname); + +	return fw; +} + +static int btusb_setup_intel_patching(struct hci_dev *hdev, +				      const struct firmware *fw, +				      const u8 **fw_ptr, int *disable_patch) +{ +	struct sk_buff *skb; +	struct hci_command_hdr *cmd; +	const u8 *cmd_param; +	struct hci_event_hdr *evt = NULL; +	const u8 *evt_param = NULL; +	int remain = fw->size - (*fw_ptr - fw->data); + +	/* The first byte indicates the types of the patch command or event. +	 * 0x01 means HCI command and 0x02 is HCI event. If the first bytes +	 * in the current firmware buffer doesn't start with 0x01 or +	 * the size of remain buffer is smaller than HCI command header, +	 * the firmware file is corrupted and it should stop the patching +	 * process. +	 */ +	if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) { +		BT_ERR("%s Intel fw corrupted: invalid cmd read", hdev->name); +		return -EINVAL; +	} +	(*fw_ptr)++; +	remain--; + +	cmd = (struct hci_command_hdr *)(*fw_ptr); +	*fw_ptr += sizeof(*cmd); +	remain -= sizeof(*cmd); + +	/* Ensure that the remain firmware data is long enough than the length +	 * of command parameter. If not, the firmware file is corrupted. +	 */ +	if (remain < cmd->plen) { +		BT_ERR("%s Intel fw corrupted: invalid cmd len", hdev->name); +		return -EFAULT; +	} + +	/* If there is a command that loads a patch in the firmware +	 * file, then enable the patch upon success, otherwise just +	 * disable the manufacturer mode, for example patch activation +	 * is not required when the default firmware patch file is used +	 * because there are no patch data to load. +	 */ +	if (*disable_patch && le16_to_cpu(cmd->opcode) == 0xfc8e) +		*disable_patch = 0; + +	cmd_param = *fw_ptr; +	*fw_ptr += cmd->plen; +	remain -= cmd->plen; + +	/* This reads the expected events when the above command is sent to the +	 * device. Some vendor commands expects more than one events, for +	 * example command status event followed by vendor specific event. +	 * For this case, it only keeps the last expected event. so the command +	 * can be sent with __hci_cmd_sync_ev() which returns the sk_buff of +	 * last expected event. +	 */ +	while (remain > HCI_EVENT_HDR_SIZE && *fw_ptr[0] == 0x02) { +		(*fw_ptr)++; +		remain--; + +		evt = (struct hci_event_hdr *)(*fw_ptr); +		*fw_ptr += sizeof(*evt); +		remain -= sizeof(*evt); + +		if (remain < evt->plen) { +			BT_ERR("%s Intel fw corrupted: invalid evt len", +			       hdev->name); +			return -EFAULT; +		} + +		evt_param = *fw_ptr; +		*fw_ptr += evt->plen; +		remain -= evt->plen; +	} + +	/* Every HCI commands in the firmware file has its correspond event. +	 * If event is not found or remain is smaller than zero, the firmware +	 * file is corrupted. +	 */ +	if (!evt || !evt_param || remain < 0) { +		BT_ERR("%s Intel fw corrupted: invalid evt read", hdev->name); +		return -EFAULT; +	} + +	skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cmd->opcode), cmd->plen, +				cmd_param, evt->evt, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("%s sending Intel patch command (0x%4.4x) failed (%ld)", +		       hdev->name, cmd->opcode, PTR_ERR(skb)); +		return PTR_ERR(skb); +	} + +	/* It ensures that the returned event matches the event data read from +	 * the firmware file. At fist, it checks the length and then +	 * the contents of the event. +	 */ +	if (skb->len != evt->plen) { +		BT_ERR("%s mismatch event length (opcode 0x%4.4x)", hdev->name, +		       le16_to_cpu(cmd->opcode)); +		kfree_skb(skb); +		return -EFAULT; +	} + +	if (memcmp(skb->data, evt_param, evt->plen)) { +		BT_ERR("%s mismatch event parameter (opcode 0x%4.4x)", +		       hdev->name, le16_to_cpu(cmd->opcode)); +		kfree_skb(skb); +		return -EFAULT; +	} +	kfree_skb(skb); + +	return 0; +} + +static int btusb_setup_intel(struct hci_dev *hdev) +{ +	struct sk_buff *skb; +	const struct firmware *fw; +	const u8 *fw_ptr; +	int disable_patch; +	struct intel_version *ver; + +	const u8 mfg_enable[] = { 0x01, 0x00 }; +	const u8 mfg_disable[] = { 0x00, 0x00 }; +	const u8 mfg_reset_deactivate[] = { 0x00, 0x01 }; +	const u8 mfg_reset_activate[] = { 0x00, 0x02 }; + +	BT_DBG("%s", hdev->name); + +	/* The controller has a bug with the first HCI command sent to it +	 * returning number of completed commands as zero. This would stall the +	 * command processing in the Bluetooth core. +	 * +	 * As a workaround, send HCI Reset command first which will reset the +	 * number of completed commands and allow normal command processing +	 * from now on. +	 */ +	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("%s sending initial HCI reset command failed (%ld)", +		       hdev->name, PTR_ERR(skb)); +		return PTR_ERR(skb); +	} +	kfree_skb(skb); + +	/* Read Intel specific controller version first to allow selection of +	 * which firmware file to load. +	 * +	 * The returned information are hardware variant and revision plus +	 * firmware variant, revision and build number. +	 */ +	skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("%s reading Intel fw version command failed (%ld)", +		       hdev->name, PTR_ERR(skb)); +		return PTR_ERR(skb); +	} + +	if (skb->len != sizeof(*ver)) { +		BT_ERR("%s Intel version event length mismatch", hdev->name); +		kfree_skb(skb); +		return -EIO; +	} + +	ver = (struct intel_version *)skb->data; +	if (ver->status) { +		BT_ERR("%s Intel fw version event failed (%02x)", hdev->name, +		       ver->status); +		kfree_skb(skb); +		return -bt_to_errno(ver->status); +	} + +	BT_INFO("%s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x", +		hdev->name, ver->hw_platform, ver->hw_variant, +		ver->hw_revision, ver->fw_variant,  ver->fw_revision, +		ver->fw_build_num, ver->fw_build_ww, ver->fw_build_yy, +		ver->fw_patch_num); + +	/* fw_patch_num indicates the version of patch the device currently +	 * have. If there is no patch data in the device, it is always 0x00. +	 * So, if it is other than 0x00, no need to patch the deivce again. +	 */ +	if (ver->fw_patch_num) { +		BT_INFO("%s: Intel device is already patched. patch num: %02x", +			hdev->name, ver->fw_patch_num); +		kfree_skb(skb); +		return 0; +	} + +	/* Opens the firmware patch file based on the firmware version read +	 * from the controller. If it fails to open the matching firmware +	 * patch file, it tries to open the default firmware patch file. +	 * If no patch file is found, allow the device to operate without +	 * a patch. +	 */ +	fw = btusb_setup_intel_get_fw(hdev, ver); +	if (!fw) { +		kfree_skb(skb); +		return 0; +	} +	fw_ptr = fw->data; + +	/* This Intel specific command enables the manufacturer mode of the +	 * controller. +	 * +	 * Only while this mode is enabled, the driver can download the +	 * firmware patch data and configuration parameters. +	 */ +	skb = __hci_cmd_sync(hdev, 0xfc11, 2, mfg_enable, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("%s entering Intel manufacturer mode failed (%ld)", +		       hdev->name, PTR_ERR(skb)); +		release_firmware(fw); +		return PTR_ERR(skb); +	} + +	if (skb->data[0]) { +		u8 evt_status = skb->data[0]; +		BT_ERR("%s enable Intel manufacturer mode event failed (%02x)", +		       hdev->name, evt_status); +		kfree_skb(skb); +		release_firmware(fw); +		return -bt_to_errno(evt_status); +	} +	kfree_skb(skb); + +	disable_patch = 1; + +	/* The firmware data file consists of list of Intel specific HCI +	 * commands and its expected events. The first byte indicates the +	 * type of the message, either HCI command or HCI event. +	 * +	 * It reads the command and its expected event from the firmware file, +	 * and send to the controller. Once __hci_cmd_sync_ev() returns, +	 * the returned event is compared with the event read from the firmware +	 * file and it will continue until all the messages are downloaded to +	 * the controller. +	 * +	 * Once the firmware patching is completed successfully, +	 * the manufacturer mode is disabled with reset and activating the +	 * downloaded patch. +	 * +	 * If the firmware patching fails, the manufacturer mode is +	 * disabled with reset and deactivating the patch. +	 * +	 * If the default patch file is used, no reset is done when disabling +	 * the manufacturer. +	 */ +	while (fw->size > fw_ptr - fw->data) { +		int ret; + +		ret = btusb_setup_intel_patching(hdev, fw, &fw_ptr, +						 &disable_patch); +		if (ret < 0) +			goto exit_mfg_deactivate; +	} + +	release_firmware(fw); + +	if (disable_patch) +		goto exit_mfg_disable; + +	/* Patching completed successfully and disable the manufacturer mode +	 * with reset and activate the downloaded firmware patches. +	 */ +	skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_activate), +			     mfg_reset_activate, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("%s exiting Intel manufacturer mode failed (%ld)", +		       hdev->name, PTR_ERR(skb)); +		return PTR_ERR(skb); +	} +	kfree_skb(skb); + +	BT_INFO("%s: Intel Bluetooth firmware patch completed and activated", +		hdev->name); + +	return 0; + +exit_mfg_disable: +	/* Disable the manufacturer mode without reset */ +	skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_disable), mfg_disable, +			     HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("%s exiting Intel manufacturer mode failed (%ld)", +		       hdev->name, PTR_ERR(skb)); +		return PTR_ERR(skb); +	} +	kfree_skb(skb); + +	BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name); +	return 0; + +exit_mfg_deactivate: +	release_firmware(fw); + +	/* Patching failed. Disable the manufacturer mode with reset and +	 * deactivate the downloaded firmware patches. +	 */ +	skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_deactivate), +			     mfg_reset_deactivate, HCI_INIT_TIMEOUT); +	if (IS_ERR(skb)) { +		BT_ERR("%s exiting Intel manufacturer mode failed (%ld)", +		       hdev->name, PTR_ERR(skb)); +		return PTR_ERR(skb); +	} +	kfree_skb(skb); + +	BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated", +		hdev->name); + +	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)  { @@ -898,7 +1563,16 @@ static int btusb_probe(struct usb_interface *intf,  	if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)  		return -ENODEV; -	data = kzalloc(sizeof(*data), GFP_KERNEL); +	if (id->driver_info & BTUSB_ATH3012) { +		struct usb_device *udev = interface_to_usbdev(intf); + +		/* Old firmware would otherwise let ath3k driver load +		 * patch and sysconfig files */ +		if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) +			return -ENODEV; +	} + +	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);  	if (!data)  		return -ENOMEM; @@ -921,10 +1595,8 @@ static int btusb_probe(struct usb_interface *intf,  		}  	} -	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) { -		kfree(data); +	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)  		return -ENODEV; -	}  	data->cmdreq_type = USB_TYPE_CLASS; @@ -944,32 +1616,36 @@ static int btusb_probe(struct usb_interface *intf,  	init_usb_anchor(&data->deferred);  	hdev = hci_alloc_dev(); -	if (!hdev) { -		kfree(data); +	if (!hdev)  		return -ENOMEM; -	}  	hdev->bus = HCI_USB; -	hdev->driver_data = data; +	hci_set_drvdata(hdev, data);  	data->hdev = hdev;  	SET_HCIDEV_DEV(hdev, &intf->dev); -	hdev->open     = btusb_open; -	hdev->close    = btusb_close; -	hdev->flush    = btusb_flush; -	hdev->send     = btusb_send_frame; -	hdev->destruct = btusb_destruct; -	hdev->notify   = btusb_notify; +	hdev->open   = btusb_open; +	hdev->close  = btusb_close; +	hdev->flush  = btusb_flush; +	hdev->send   = btusb_send_frame; +	hdev->notify = btusb_notify; -	hdev->owner = THIS_MODULE; +	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;  	/* Interface numbers are hardcoded in the specification */  	data->isoc = usb_ifnum_to_if(data->udev, 1);  	if (!reset) -		set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); +		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);  	if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {  		if (!disable_scofix) @@ -981,15 +1657,20 @@ static int btusb_probe(struct usb_interface *intf,  	if (id->driver_info & BTUSB_DIGIANSWER) {  		data->cmdreq_type = USB_TYPE_VENDOR; -		set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); +		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);  	}  	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) -			set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); +		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) { @@ -1002,23 +1683,11 @@ static int btusb_probe(struct usb_interface *intf,  		data->isoc = NULL;  	} -	if (id->driver_info & BTUSB_BCM92035) { -		unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 }; -		struct sk_buff *skb; - -		skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL); -		if (skb) { -			memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd)); -			skb_queue_tail(&hdev->driver_init, skb); -		} -	} -  	if (data->isoc) {  		err = usb_driver_claim_interface(&btusb_driver,  							data->isoc, data);  		if (err < 0) {  			hci_free_dev(hdev); -			kfree(data);  			return err;  		}  	} @@ -1026,14 +1695,11 @@ static int btusb_probe(struct usb_interface *intf,  	err = hci_register_dev(hdev);  	if (err < 0) {  		hci_free_dev(hdev); -		kfree(data);  		return err;  	}  	usb_set_intfdata(intf, data); -	usb_enable_autosuspend(interface_to_usbdev(intf)); -  	return 0;  } @@ -1048,9 +1714,6 @@ static void btusb_disconnect(struct usb_interface *intf)  		return;  	hdev = data->hdev; - -	__hci_dev_hold(hdev); -  	usb_set_intfdata(data->intf, NULL);  	if (data->isoc) @@ -1063,8 +1726,6 @@ static void btusb_disconnect(struct usb_interface *intf)  	else if (data->isoc)  		usb_driver_release_interface(&btusb_driver, data->isoc); -	__hci_dev_put(hdev); -  	hci_free_dev(hdev);  } @@ -1079,7 +1740,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)  		return 0;  	spin_lock_irq(&data->txlock); -	if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) { +	if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {  		set_bit(BTUSB_SUSPENDING, &data->flags);  		spin_unlock_irq(&data->txlock);  	} else { @@ -1179,22 +1840,10 @@ static struct usb_driver btusb_driver = {  #endif  	.id_table	= btusb_table,  	.supports_autosuspend = 1, +	.disable_hub_initiated_lpm = 1,  }; -static int __init btusb_init(void) -{ -	BT_INFO("Generic Bluetooth USB driver ver %s", VERSION); - -	return usb_register(&btusb_driver); -} - -static void __exit btusb_exit(void) -{ -	usb_deregister(&btusb_driver); -} - -module_init(btusb_init); -module_exit(btusb_exit); +module_usb_driver(btusb_driver);  module_param(ignore_dga, bool, 0644);  MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001"); diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c new file mode 100644 index 00000000000..f038dba19e3 --- /dev/null +++ b/drivers/bluetooth/btwilink.c @@ -0,0 +1,363 @@ +/* + *  Texas Instrument's Bluetooth Driver For Shared Transport. + * + *  Bluetooth Driver acts as interface between HCI core and + *  TI Shared Transport Layer. + * + *  Copyright (C) 2009-2010 Texas Instruments + *  Author: Raja Mani <raja_mani@ti.com> + *	Pavan Savoy <pavan_savoy@ti.com> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License version 2 as + *  published by the Free Software Foundation. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ +#define DEBUG +#include <linux/platform_device.h> +#include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/hci_core.h> +#include <net/bluetooth/hci.h> + +#include <linux/ti_wilink_st.h> +#include <linux/module.h> + +/* Bluetooth Driver Version */ +#define VERSION               "1.0" +#define MAX_BT_CHNL_IDS		3 + +/* Number of seconds to wait for registration completion + * when ST returns PENDING status. + */ +#define BT_REGISTER_TIMEOUT   6000	/* 6 sec */ + +/** + * struct ti_st - driver operation structure + * @hdev: hci device pointer which binds to bt driver + * @reg_status: ST registration callback status + * @st_write: write function provided by the ST driver + *	to be used by the driver during send_frame. + * @wait_reg_completion - completion sync between ti_st_open + *	and st_reg_completion_cb. + */ +struct ti_st { +	struct hci_dev *hdev; +	char reg_status; +	long (*st_write) (struct sk_buff *); +	struct completion wait_reg_completion; +}; + +/* Increments HCI counters based on pocket ID (cmd,acl,sco) */ +static inline void ti_st_tx_complete(struct ti_st *hst, int pkt_type) +{ +	struct hci_dev *hdev = hst->hdev; + +	/* Update HCI stat counters */ +	switch (pkt_type) { +	case HCI_COMMAND_PKT: +		hdev->stat.cmd_tx++; +		break; + +	case HCI_ACLDATA_PKT: +		hdev->stat.acl_tx++; +		break; + +	case HCI_SCODATA_PKT: +		hdev->stat.sco_tx++; +		break; +	} +} + +/* ------- Interfaces to Shared Transport ------ */ + +/* Called by ST layer to indicate protocol registration completion + * status.ti_st_open() function will wait for signal from this + * API when st_register() function returns ST_PENDING. + */ +static void st_reg_completion_cb(void *priv_data, char data) +{ +	struct ti_st *lhst = priv_data; + +	/* Save registration status for use in ti_st_open() */ +	lhst->reg_status = data; +	/* complete the wait in ti_st_open() */ +	complete(&lhst->wait_reg_completion); +} + +/* Called by Shared Transport layer when receive data is + * available */ +static long st_receive(void *priv_data, struct sk_buff *skb) +{ +	struct ti_st *lhst = priv_data; +	int err; + +	if (!skb) +		return -EFAULT; + +	if (!lhst) { +		kfree_skb(skb); +		return -EFAULT; +	} + +	/* Forward skb to HCI core layer */ +	err = hci_recv_frame(lhst->hdev, skb); +	if (err < 0) { +		BT_ERR("Unable to push skb to HCI core(%d)", err); +		return err; +	} + +	lhst->hdev->stat.byte_rx += skb->len; + +	return 0; +} + +/* ------- Interfaces to HCI layer ------ */ +/* protocol structure registered with shared transport */ +static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = { +	{ +		.chnl_id = HCI_EVENT_PKT, /* HCI Events */ +		.hdr_len = sizeof(struct hci_event_hdr), +		.offset_len_in_hdr = offsetof(struct hci_event_hdr, plen), +		.len_size = 1, /* sizeof(plen) in struct hci_event_hdr */ +		.reserve = 8, +	}, +	{ +		.chnl_id = HCI_ACLDATA_PKT, /* ACL */ +		.hdr_len = sizeof(struct hci_acl_hdr), +		.offset_len_in_hdr = offsetof(struct hci_acl_hdr, dlen), +		.len_size = 2,	/* sizeof(dlen) in struct hci_acl_hdr */ +		.reserve = 8, +	}, +	{ +		.chnl_id = HCI_SCODATA_PKT, /* SCO */ +		.hdr_len = sizeof(struct hci_sco_hdr), +		.offset_len_in_hdr = offsetof(struct hci_sco_hdr, dlen), +		.len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */ +		.reserve = 8, +	}, +}; + +/* Called from HCI core to initialize the device */ +static int ti_st_open(struct hci_dev *hdev) +{ +	unsigned long timeleft; +	struct ti_st *hst; +	int err, i; + +	BT_DBG("%s %p", hdev->name, hdev); + +	if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) +		return -EBUSY; + +	/* provide contexts for callbacks from ST */ +	hst = hci_get_drvdata(hdev); + +	for (i = 0; i < MAX_BT_CHNL_IDS; i++) { +		ti_st_proto[i].priv_data = hst; +		ti_st_proto[i].max_frame_size = HCI_MAX_FRAME_SIZE; +		ti_st_proto[i].recv = st_receive; +		ti_st_proto[i].reg_complete_cb = st_reg_completion_cb; + +		/* Prepare wait-for-completion handler */ +		init_completion(&hst->wait_reg_completion); +		/* Reset ST registration callback status flag, +		 * this value will be updated in +		 * st_reg_completion_cb() +		 * function whenever it called from ST driver. +		 */ +		hst->reg_status = -EINPROGRESS; + +		err = st_register(&ti_st_proto[i]); +		if (!err) +			goto done; + +		if (err != -EINPROGRESS) { +			clear_bit(HCI_RUNNING, &hdev->flags); +			BT_ERR("st_register failed %d", err); +			return err; +		} + +		/* ST is busy with either protocol +		 * registration or firmware download. +		 */ +		BT_DBG("waiting for registration " +				"completion signal from ST"); +		timeleft = wait_for_completion_timeout +			(&hst->wait_reg_completion, +			 msecs_to_jiffies(BT_REGISTER_TIMEOUT)); +		if (!timeleft) { +			clear_bit(HCI_RUNNING, &hdev->flags); +			BT_ERR("Timeout(%d sec),didn't get reg " +					"completion signal from ST", +					BT_REGISTER_TIMEOUT / 1000); +			return -ETIMEDOUT; +		} + +		/* Is ST registration callback +		 * called with ERROR status? */ +		if (hst->reg_status != 0) { +			clear_bit(HCI_RUNNING, &hdev->flags); +			BT_ERR("ST registration completed with invalid " +					"status %d", hst->reg_status); +			return -EAGAIN; +		} + +done: +		hst->st_write = ti_st_proto[i].write; +		if (!hst->st_write) { +			BT_ERR("undefined ST write function"); +			clear_bit(HCI_RUNNING, &hdev->flags); +			for (i = 0; i < MAX_BT_CHNL_IDS; i++) { +				/* Undo registration with ST */ +				err = st_unregister(&ti_st_proto[i]); +				if (err) +					BT_ERR("st_unregister() failed with " +							"error %d", err); +				hst->st_write = NULL; +			} +			return -EIO; +		} +	} +	return 0; +} + +/* Close device */ +static int ti_st_close(struct hci_dev *hdev) +{ +	int err, i; +	struct ti_st *hst = hci_get_drvdata(hdev); + +	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) +		return 0; + +	for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) { +		err = st_unregister(&ti_st_proto[i]); +		if (err) +			BT_ERR("st_unregister(%d) failed with error %d", +					ti_st_proto[i].chnl_id, err); +	} + +	hst->st_write = NULL; + +	return err; +} + +static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb) +{ +	struct ti_st *hst; +	long len; + +	if (!test_bit(HCI_RUNNING, &hdev->flags)) +		return -EBUSY; + +	hst = hci_get_drvdata(hdev); + +	/* Prepend skb with frame type */ +	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); + +	BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, +			skb->len); + +	/* Insert skb to shared transport layer's transmit queue. +	 * Freeing skb memory is taken care in shared transport layer, +	 * so don't free skb memory here. +	 */ +	len = hst->st_write(skb); +	if (len < 0) { +		kfree_skb(skb); +		BT_ERR("ST write failed (%ld)", len); +		/* Try Again, would only fail if UART has gone bad */ +		return -EAGAIN; +	} + +	/* ST accepted our skb. So, Go ahead and do rest */ +	hdev->stat.byte_tx += len; +	ti_st_tx_complete(hst, bt_cb(skb)->pkt_type); + +	return 0; +} + +static int bt_ti_probe(struct platform_device *pdev) +{ +	static struct ti_st *hst; +	struct hci_dev *hdev; +	int err; + +	hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL); +	if (!hst) +		return -ENOMEM; + +	/* Expose "hciX" device to user space */ +	hdev = hci_alloc_dev(); +	if (!hdev) +		return -ENOMEM; + +	BT_DBG("hdev %p", hdev); + +	hst->hdev = hdev; +	hdev->bus = HCI_UART; +	hci_set_drvdata(hdev, hst); +	hdev->open = ti_st_open; +	hdev->close = ti_st_close; +	hdev->flush = NULL; +	hdev->send = ti_st_send_frame; + +	err = hci_register_dev(hdev); +	if (err < 0) { +		BT_ERR("Can't register HCI device error %d", err); +		hci_free_dev(hdev); +		return err; +	} + +	BT_DBG("HCI device registered (hdev %p)", hdev); + +	dev_set_drvdata(&pdev->dev, hst); +	return err; +} + +static int bt_ti_remove(struct platform_device *pdev) +{ +	struct hci_dev *hdev; +	struct ti_st *hst = dev_get_drvdata(&pdev->dev); + +	if (!hst) +		return -EFAULT; + +	BT_DBG("%s", hst->hdev->name); + +	hdev = hst->hdev; +	ti_st_close(hdev); +	hci_unregister_dev(hdev); + +	hci_free_dev(hdev); + +	dev_set_drvdata(&pdev->dev, NULL); +	return 0; +} + +static struct platform_driver btwilink_driver = { +	.probe = bt_ti_probe, +	.remove = bt_ti_remove, +	.driver = { +		.name = "btwilink", +		.owner = THIS_MODULE, +	}, +}; + +module_platform_driver(btwilink_driver); + +/* ------ Module Info ------ */ + +MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>"); +MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION); +MODULE_VERSION(VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 26ee0cf88d2..2bd8fad1720 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -38,7 +38,6 @@  #include <linux/serial.h>  #include <linux/serial_reg.h>  #include <linux/bitops.h> -#include <asm/system.h>  #include <asm/io.h>  #include <pcmcia/cistpl.h> @@ -83,9 +82,6 @@ typedef struct dtl1_info_t {  static int dtl1_config(struct pcmcia_device *link); -static void dtl1_release(struct pcmcia_device *link); - -static void dtl1_detach(struct pcmcia_device *p_dev);  /* Transmit states  */ @@ -148,16 +144,17 @@ static void dtl1_write_wakeup(dtl1_info_t *info)  	}  	do { -		register unsigned int iobase = info->p_dev->resource[0]->start; +		unsigned int iobase = info->p_dev->resource[0]->start;  		register struct sk_buff *skb; -		register int len; +		int len;  		clear_bit(XMIT_WAKEUP, &(info->tx_state));  		if (!pcmcia_dev_present(info->p_dev))  			return; -		if (!(skb = skb_dequeue(&(info->txq)))) +		skb = skb_dequeue(&(info->txq)); +		if (!skb)  			break;  		/* Send frame */ @@ -219,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; @@ -260,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 */ @@ -367,7 +365,7 @@ static int dtl1_hci_open(struct hci_dev *hdev)  static int dtl1_hci_flush(struct hci_dev *hdev)  { -	dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data); +	dtl1_info_t *info = hci_get_drvdata(hdev);  	/* Drop TX queue */  	skb_queue_purge(&(info->txq)); @@ -387,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 = (dtl1_info_t *)(hdev->driver_data); -  	switch (bt_cb(skb)->pkt_type) {  	case HCI_COMMAND_PKT:  		hdev->stat.cmd_tx++; @@ -442,17 +432,6 @@ static int dtl1_hci_send_frame(struct sk_buff *skb)  } -static void dtl1_hci_destruct(struct hci_dev *hdev) -{ -} - - -static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,  unsigned long arg) -{ -	return -ENOIOCTLCMD; -} - -  /* ======================== Card services HCI interaction ======================== */ @@ -483,17 +462,13 @@ static int dtl1_open(dtl1_info_t *info)  	info->hdev = hdev;  	hdev->bus = HCI_PCCARD; -	hdev->driver_data = 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->destruct = dtl1_hci_destruct; -	hdev->ioctl    = dtl1_hci_ioctl; - -	hdev->owner = THIS_MODULE; +	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); @@ -551,9 +526,7 @@ static int dtl1_close(dtl1_info_t *info)  	spin_unlock_irqrestore(&(info->lock), flags); -	if (hci_unregister_dev(hdev) < 0) -		BT_ERR("Can't unregister HCI device %s", hdev->name); - +	hci_unregister_dev(hdev);  	hci_free_dev(hdev);  	return 0; @@ -564,7 +537,7 @@ static int dtl1_probe(struct pcmcia_device *link)  	dtl1_info_t *info;  	/* Create new info device */ -	info = kzalloc(sizeof(*info), GFP_KERNEL); +	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);  	if (!info)  		return -ENOMEM; @@ -581,9 +554,8 @@ static void dtl1_detach(struct pcmcia_device *link)  {  	dtl1_info_t *info = link->priv; -	dtl1_release(link); - -	kfree(info); +	dtl1_close(info); +	pcmcia_disable_device(link);  }  static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data) @@ -600,43 +572,34 @@ static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)  static int dtl1_config(struct pcmcia_device *link)  {  	dtl1_info_t *info = link->priv; -	int i; +	int ret;  	/* Look for a generic full-sized window */  	link->resource[0]->end = 8; -	if (pcmcia_loop_config(link, dtl1_confcheck, NULL) < 0) +	ret = pcmcia_loop_config(link, dtl1_confcheck, NULL); +	if (ret)  		goto failed; -	i = pcmcia_request_irq(link, dtl1_interrupt); -	if (i != 0) +	ret = pcmcia_request_irq(link, dtl1_interrupt); +	if (ret)  		goto failed; -	i = pcmcia_enable_device(link); -	if (i != 0) +	ret = pcmcia_enable_device(link); +	if (ret)  		goto failed; -	if (dtl1_open(info) != 0) +	ret = dtl1_open(info); +	if (ret)  		goto failed;  	return 0;  failed: -	dtl1_release(link); -	return -ENODEV; -} - - -static void dtl1_release(struct pcmcia_device *link) -{ -	dtl1_info_t *info = link->priv; - -	dtl1_close(info); - -	pcmcia_disable_device(link); +	dtl1_detach(link); +	return ret;  } - -static struct pcmcia_device_id dtl1_ids[] = { +static const struct pcmcia_device_id dtl1_ids[] = {  	PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),  	PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82),  	PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863), @@ -652,17 +615,4 @@ static struct pcmcia_driver dtl1_driver = {  	.remove		= dtl1_detach,  	.id_table	= dtl1_ids,  }; - -static int __init init_dtl1_cs(void) -{ -	return pcmcia_register_driver(&dtl1_driver); -} - - -static void __exit exit_dtl1_cs(void) -{ -	pcmcia_unregister_driver(&dtl1_driver); -} - -module_init(init_dtl1_cs); -module_exit(exit_dtl1_cs); +module_pcmcia_driver(dtl1_driver); diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c index 6a160c17ea9..0bc8a6a6a14 100644 --- a/drivers/bluetooth/hci_ath.c +++ b/drivers/bluetooth/hci_ath.c @@ -51,32 +51,32 @@ struct ath_struct {  static int ath_wakeup_ar3k(struct tty_struct *tty)  { -	struct termios settings; -	int status = tty->driver->ops->tiocmget(tty, NULL); +	struct ktermios ktermios; +	int status = tty->driver->ops->tiocmget(tty);  	if (status & TIOCM_CTS)  		return status;  	/* Disable Automatic RTSCTS */ -	n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings); -	settings.c_cflag &= ~CRTSCTS; -	n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings); +	ktermios = tty->termios; +	ktermios.c_cflag &= ~CRTSCTS; +	tty_set_termios(tty, &ktermios);  	/* Clear RTS first */ -	status = tty->driver->ops->tiocmget(tty, NULL); -	tty->driver->ops->tiocmset(tty, NULL, 0x00, TIOCM_RTS); +	status = tty->driver->ops->tiocmget(tty); +	tty->driver->ops->tiocmset(tty, 0x00, TIOCM_RTS);  	mdelay(20);  	/* Set RTS, wake up board */ -	status = tty->driver->ops->tiocmget(tty, NULL); -	tty->driver->ops->tiocmset(tty, NULL, TIOCM_RTS, 0x00); +	status = tty->driver->ops->tiocmget(tty); +	tty->driver->ops->tiocmset(tty, TIOCM_RTS, 0x00);  	mdelay(20); -	status = tty->driver->ops->tiocmget(tty, NULL); +	status = tty->driver->ops->tiocmget(tty); -	n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings); -	settings.c_cflag |= CRTSCTS; -	n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings); +	/* Disable Automatic RTSCTS */ +	ktermios.c_cflag |= CRTSCTS; +	status = tty_set_termios(tty, &ktermios);  	return status;  } @@ -112,7 +112,7 @@ static int ath_open(struct hci_uart *hu)  	BT_DBG("hu %p", hu); -	ath = kzalloc(sizeof(*ath), GFP_ATOMIC); +	ath = kzalloc(sizeof(*ath), GFP_KERNEL);  	if (!ath)  		return -ENOMEM; @@ -201,8 +201,13 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu)  /* Recv data */  static int ath_recv(struct hci_uart *hu, void *data, int count)  { -	if (hci_recv_stream_fragment(hu->hdev, data, count) < 0) +	int ret; + +	ret = hci_recv_stream_fragment(hu->hdev, data, count); +	if (ret < 0) {  		BT_ERR("Frame Reassembly Failed"); +		return ret; +	}  	return count;  } diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 9c5b2dc38e2..21cc45b34f1 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -49,8 +49,8 @@  #define VERSION "0.3" -static int txcrc = 1; -static int hciextn = 1; +static bool txcrc = 1; +static bool hciextn = 1;  #define BCSP_TXWINSIZE	4 @@ -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; @@ -552,7 +557,7 @@ static u16 bscp_get_crc(struct bcsp_struct *bcsp)  static int bcsp_recv(struct hci_uart *hu, void *data, int count)  {  	struct bcsp_struct *bcsp = hu->priv; -	register unsigned char *ptr; +	unsigned char *ptr;  	BT_DBG("hu %p count %d rx_state %d rx_count %ld",   		hu, count, bcsp->rx_state, bcsp->rx_count); @@ -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; @@ -692,7 +696,7 @@ static int bcsp_open(struct hci_uart *hu)  	BT_DBG("hu %p", hu); -	bcsp = kzalloc(sizeof(*bcsp), GFP_ATOMIC); +	bcsp = kzalloc(sizeof(*bcsp), GFP_KERNEL);  	if (!bcsp)  		return -ENOMEM; @@ -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 7b8ad93e2c3..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)  { @@ -69,7 +62,7 @@ static int h4_open(struct hci_uart *hu)  	BT_DBG("hu %p", hu); -	h4 = kzalloc(sizeof(*h4), GFP_ATOMIC); +	h4 = kzalloc(sizeof(*h4), GFP_KERNEL);  	if (!h4)  		return -ENOMEM; @@ -124,35 +117,19 @@ 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) -{ -	register 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)  { -	if (hci_recv_stream_fragment(hu->hdev, data, count) < 0) +	int ret; + +	if (!test_bit(HCI_UART_REGISTERED, &hu->flags)) +		return -EUNATCH; + +	ret = hci_recv_stream_fragment(hu->hdev, data, count); +	if (ret < 0) {  		BT_ERR("Frame Reassembly Failed"); +		return ret; +	}  	return count;  } diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c new file mode 100644 index 00000000000..fede8ca7147 --- /dev/null +++ b/drivers/bluetooth/hci_h5.c @@ -0,0 +1,750 @@ +/* + * + *  Bluetooth HCI Three-wire UART driver + * + *  Copyright (C) 2012  Intel Corporation + * + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/skbuff.h> + +#include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/hci_core.h> + +#include "hci_uart.h" + +#define HCI_3WIRE_ACK_PKT	0 +#define HCI_3WIRE_LINK_PKT	15 + +/* Sliding window size */ +#define H5_TX_WIN_MAX		4 + +#define H5_ACK_TIMEOUT	msecs_to_jiffies(250) +#define H5_SYNC_TIMEOUT	msecs_to_jiffies(100) + +/* + * Maximum Three-wire packet: + *     4 byte header + max value for 12-bit length + 2 bytes for CRC + */ +#define H5_MAX_LEN (4 + 0xfff + 2) + +/* Convenience macros for reading Three-wire header values */ +#define H5_HDR_SEQ(hdr)		((hdr)[0] & 0x07) +#define H5_HDR_ACK(hdr)		(((hdr)[0] >> 3) & 0x07) +#define H5_HDR_CRC(hdr)		(((hdr)[0] >> 6) & 0x01) +#define H5_HDR_RELIABLE(hdr)	(((hdr)[0] >> 7) & 0x01) +#define H5_HDR_PKT_TYPE(hdr)	((hdr)[1] & 0x0f) +#define H5_HDR_LEN(hdr)		((((hdr)[1] >> 4) & 0xff) + ((hdr)[2] << 4)) + +#define SLIP_DELIMITER	0xc0 +#define SLIP_ESC	0xdb +#define SLIP_ESC_DELIM	0xdc +#define SLIP_ESC_ESC	0xdd + +/* H5 state flags */ +enum { +	H5_RX_ESC,	/* SLIP escape mode */ +	H5_TX_ACK_REQ,	/* Pending ack to send */ +}; + +struct h5 { +	struct sk_buff_head	unack;		/* Unack'ed packets queue */ +	struct sk_buff_head	rel;		/* Reliable packets queue */ +	struct sk_buff_head	unrel;		/* Unreliable packets queue */ + +	unsigned long		flags; + +	struct sk_buff		*rx_skb;	/* Receive buffer */ +	size_t			rx_pending;	/* Expecting more bytes */ +	u8			rx_ack;		/* Last ack number received */ + +	int			(*rx_func) (struct hci_uart *hu, u8 c); + +	struct timer_list	timer;		/* Retransmission timer */ + +	u8			tx_seq;		/* Next seq number to send */ +	u8			tx_ack;		/* Next ack number to send */ +	u8			tx_win;		/* Sliding window size */ + +	enum { +		H5_UNINITIALIZED, +		H5_INITIALIZED, +		H5_ACTIVE, +	} state; + +	enum { +		H5_AWAKE, +		H5_SLEEPING, +		H5_WAKING_UP, +	} sleep; +}; + +static void h5_reset_rx(struct h5 *h5); + +static void h5_link_control(struct hci_uart *hu, const void *data, size_t len) +{ +	struct h5 *h5 = hu->priv; +	struct sk_buff *nskb; + +	nskb = alloc_skb(3, GFP_ATOMIC); +	if (!nskb) +		return; + +	bt_cb(nskb)->pkt_type = HCI_3WIRE_LINK_PKT; + +	memcpy(skb_put(nskb, len), data, len); + +	skb_queue_tail(&h5->unrel, nskb); +} + +static u8 h5_cfg_field(struct h5 *h5) +{ +	u8 field = 0; + +	/* Sliding window size (first 3 bits) */ +	field |= (h5->tx_win & 7); + +	return field; +} + +static void h5_timed_event(unsigned long arg) +{ +	const unsigned char sync_req[] = { 0x01, 0x7e }; +	unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; +	struct hci_uart *hu = (struct hci_uart *) arg; +	struct h5 *h5 = hu->priv; +	struct sk_buff *skb; +	unsigned long flags; + +	BT_DBG("%s", hu->hdev->name); + +	if (h5->state == H5_UNINITIALIZED) +		h5_link_control(hu, sync_req, sizeof(sync_req)); + +	if (h5->state == H5_INITIALIZED) { +		conf_req[2] = h5_cfg_field(h5); +		h5_link_control(hu, conf_req, sizeof(conf_req)); +	} + +	if (h5->state != H5_ACTIVE) { +		mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT); +		goto wakeup; +	} + +	if (h5->sleep != H5_AWAKE) { +		h5->sleep = H5_SLEEPING; +		goto wakeup; +	} + +	BT_DBG("hu %p retransmitting %u pkts", hu, h5->unack.qlen); + +	spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING); + +	while ((skb = __skb_dequeue_tail(&h5->unack)) != NULL) { +		h5->tx_seq = (h5->tx_seq - 1) & 0x07; +		skb_queue_head(&h5->rel, skb); +	} + +	spin_unlock_irqrestore(&h5->unack.lock, flags); + +wakeup: +	hci_uart_tx_wakeup(hu); +} + +static int h5_open(struct hci_uart *hu) +{ +	struct h5 *h5; +	const unsigned char sync[] = { 0x01, 0x7e }; + +	BT_DBG("hu %p", hu); + +	h5 = kzalloc(sizeof(*h5), GFP_KERNEL); +	if (!h5) +		return -ENOMEM; + +	hu->priv = h5; + +	skb_queue_head_init(&h5->unack); +	skb_queue_head_init(&h5->rel); +	skb_queue_head_init(&h5->unrel); + +	h5_reset_rx(h5); + +	init_timer(&h5->timer); +	h5->timer.function = h5_timed_event; +	h5->timer.data = (unsigned long) hu; + +	h5->tx_win = H5_TX_WIN_MAX; + +	set_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags); + +	/* Send initial sync request */ +	h5_link_control(hu, sync, sizeof(sync)); +	mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT); + +	return 0; +} + +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); + +	kfree(h5); + +	return 0; +} + +static void h5_pkt_cull(struct h5 *h5) +{ +	struct sk_buff *skb, *tmp; +	unsigned long flags; +	int i, to_remove; +	u8 seq; + +	spin_lock_irqsave(&h5->unack.lock, flags); + +	to_remove = skb_queue_len(&h5->unack); +	if (to_remove == 0) +		goto unlock; + +	seq = h5->tx_seq; + +	while (to_remove > 0) { +		if (h5->rx_ack == seq) +			break; + +		to_remove--; +		seq = (seq - 1) % 8; +	} + +	if (seq != h5->rx_ack) +		BT_ERR("Controller acked invalid packet"); + +	i = 0; +	skb_queue_walk_safe(&h5->unack, skb, tmp) { +		if (i++ >= to_remove) +			break; + +		__skb_unlink(skb, &h5->unack); +		kfree_skb(skb); +	} + +	if (skb_queue_empty(&h5->unack)) +		del_timer(&h5->timer); + +unlock: +	spin_unlock_irqrestore(&h5->unack.lock, flags); +} + +static void h5_handle_internal_rx(struct hci_uart *hu) +{ +	struct h5 *h5 = hu->priv; +	const unsigned char sync_req[] = { 0x01, 0x7e }; +	const unsigned char sync_rsp[] = { 0x02, 0x7d }; +	unsigned char conf_req[] = { 0x03, 0xfc, 0x01 }; +	const unsigned char conf_rsp[] = { 0x04, 0x7b }; +	const unsigned char wakeup_req[] = { 0x05, 0xfa }; +	const unsigned char woken_req[] = { 0x06, 0xf9 }; +	const unsigned char sleep_req[] = { 0x07, 0x78 }; +	const unsigned char *hdr = h5->rx_skb->data; +	const unsigned char *data = &h5->rx_skb->data[4]; + +	BT_DBG("%s", hu->hdev->name); + +	if (H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) +		return; + +	if (H5_HDR_LEN(hdr) < 2) +		return; + +	conf_req[2] = h5_cfg_field(h5); + +	if (memcmp(data, sync_req, 2) == 0) { +		h5_link_control(hu, sync_rsp, 2); +	} else if (memcmp(data, sync_rsp, 2) == 0) { +		h5->state = H5_INITIALIZED; +		h5_link_control(hu, conf_req, 3); +	} else if (memcmp(data, conf_req, 2) == 0) { +		h5_link_control(hu, conf_rsp, 2); +		h5_link_control(hu, conf_req, 3); +	} else if (memcmp(data, conf_rsp, 2) == 0) { +		if (H5_HDR_LEN(hdr) > 2) +			h5->tx_win = (data[2] & 7); +		BT_DBG("Three-wire init complete. tx_win %u", h5->tx_win); +		h5->state = H5_ACTIVE; +		hci_uart_init_ready(hu); +		return; +	} else if (memcmp(data, sleep_req, 2) == 0) { +		BT_DBG("Peer went to sleep"); +		h5->sleep = H5_SLEEPING; +		return; +	} else if (memcmp(data, woken_req, 2) == 0) { +		BT_DBG("Peer woke up"); +		h5->sleep = H5_AWAKE; +	} else if (memcmp(data, wakeup_req, 2) == 0) { +		BT_DBG("Peer requested wakeup"); +		h5_link_control(hu, woken_req, 2); +		h5->sleep = H5_AWAKE; +	} else { +		BT_DBG("Link Control: 0x%02hhx 0x%02hhx", data[0], data[1]); +		return; +	} + +	hci_uart_tx_wakeup(hu); +} + +static void h5_complete_rx_pkt(struct hci_uart *hu) +{ +	struct h5 *h5 = hu->priv; +	const unsigned char *hdr = h5->rx_skb->data; + +	if (H5_HDR_RELIABLE(hdr)) { +		h5->tx_ack = (h5->tx_ack + 1) % 8; +		set_bit(H5_TX_ACK_REQ, &h5->flags); +		hci_uart_tx_wakeup(hu); +	} + +	h5->rx_ack = H5_HDR_ACK(hdr); + +	h5_pkt_cull(h5); + +	switch (H5_HDR_PKT_TYPE(hdr)) { +	case HCI_EVENT_PKT: +	case HCI_ACLDATA_PKT: +	case HCI_SCODATA_PKT: +		bt_cb(h5->rx_skb)->pkt_type = H5_HDR_PKT_TYPE(hdr); + +		/* Remove Three-wire header */ +		skb_pull(h5->rx_skb, 4); + +		hci_recv_frame(hu->hdev, h5->rx_skb); +		h5->rx_skb = NULL; + +		break; + +	default: +		h5_handle_internal_rx(hu); +		break; +	} + +	h5_reset_rx(h5); +} + +static int h5_rx_crc(struct hci_uart *hu, unsigned char c) +{ +	struct h5 *h5 = hu->priv; + +	h5_complete_rx_pkt(hu); +	h5_reset_rx(h5); + +	return 0; +} + +static int h5_rx_payload(struct hci_uart *hu, unsigned char c) +{ +	struct h5 *h5 = hu->priv; +	const unsigned char *hdr = h5->rx_skb->data; + +	if (H5_HDR_CRC(hdr)) { +		h5->rx_func = h5_rx_crc; +		h5->rx_pending = 2; +	} else { +		h5_complete_rx_pkt(hu); +		h5_reset_rx(h5); +	} + +	return 0; +} + +static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c) +{ +	struct h5 *h5 = hu->priv; +	const unsigned char *hdr = h5->rx_skb->data; + +	BT_DBG("%s rx: seq %u ack %u crc %u rel %u type %u len %u", +	       hu->hdev->name, H5_HDR_SEQ(hdr), H5_HDR_ACK(hdr), +	       H5_HDR_CRC(hdr), H5_HDR_RELIABLE(hdr), H5_HDR_PKT_TYPE(hdr), +	       H5_HDR_LEN(hdr)); + +	if (((hdr[0] + hdr[1] + hdr[2] + hdr[3]) & 0xff) != 0xff) { +		BT_ERR("Invalid header checksum"); +		h5_reset_rx(h5); +		return 0; +	} + +	if (H5_HDR_RELIABLE(hdr) && H5_HDR_SEQ(hdr) != h5->tx_ack) { +		BT_ERR("Out-of-order packet arrived (%u != %u)", +		       H5_HDR_SEQ(hdr), h5->tx_ack); +		h5_reset_rx(h5); +		return 0; +	} + +	if (h5->state != H5_ACTIVE && +	    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; +	h5->rx_pending = H5_HDR_LEN(hdr); + +	return 0; +} + +static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c) +{ +	struct h5 *h5 = hu->priv; + +	if (c == SLIP_DELIMITER) +		return 1; + +	h5->rx_func = h5_rx_3wire_hdr; +	h5->rx_pending = 4; + +	h5->rx_skb = bt_skb_alloc(H5_MAX_LEN, GFP_ATOMIC); +	if (!h5->rx_skb) { +		BT_ERR("Can't allocate mem for new packet"); +		h5_reset_rx(h5); +		return -ENOMEM; +	} + +	h5->rx_skb->dev = (void *) hu->hdev; + +	return 0; +} + +static int h5_rx_delimiter(struct hci_uart *hu, unsigned char c) +{ +	struct h5 *h5 = hu->priv; + +	if (c == SLIP_DELIMITER) +		h5->rx_func = h5_rx_pkt_start; + +	return 1; +} + +static void h5_unslip_one_byte(struct h5 *h5, unsigned char c) +{ +	const u8 delim = SLIP_DELIMITER, esc = SLIP_ESC; +	const u8 *byte = &c; + +	if (!test_bit(H5_RX_ESC, &h5->flags) && c == SLIP_ESC) { +		set_bit(H5_RX_ESC, &h5->flags); +		return; +	} + +	if (test_and_clear_bit(H5_RX_ESC, &h5->flags)) { +		switch (c) { +		case SLIP_ESC_DELIM: +			byte = &delim; +			break; +		case SLIP_ESC_ESC: +			byte = &esc; +			break; +		default: +			BT_ERR("Invalid esc byte 0x%02hhx", c); +			h5_reset_rx(h5); +			return; +		} +	} + +	memcpy(skb_put(h5->rx_skb, 1), byte, 1); +	h5->rx_pending--; + +	BT_DBG("unsliped 0x%02hhx, rx_pending %zu", *byte, h5->rx_pending); +} + +static void h5_reset_rx(struct h5 *h5) +{ +	if (h5->rx_skb) { +		kfree_skb(h5->rx_skb); +		h5->rx_skb = NULL; +	} + +	h5->rx_func = h5_rx_delimiter; +	h5->rx_pending = 0; +	clear_bit(H5_RX_ESC, &h5->flags); +} + +static int h5_recv(struct hci_uart *hu, void *data, int count) +{ +	struct h5 *h5 = hu->priv; +	unsigned char *ptr = data; + +	BT_DBG("%s pending %zu count %d", hu->hdev->name, h5->rx_pending, +	       count); + +	while (count > 0) { +		int processed; + +		if (h5->rx_pending > 0) { +			if (*ptr == SLIP_DELIMITER) { +				BT_ERR("Too short H5 packet"); +				h5_reset_rx(h5); +				continue; +			} + +			h5_unslip_one_byte(h5, *ptr); + +			ptr++; count--; +			continue; +		} + +		processed = h5->rx_func(hu, *ptr); +		if (processed < 0) +			return processed; + +		ptr += processed; +		count -= processed; +	} + +	return 0; +} + +static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb) +{ +	struct h5 *h5 = hu->priv; + +	if (skb->len > 0xfff) { +		BT_ERR("Packet too long (%u bytes)", skb->len); +		kfree_skb(skb); +		return 0; +	} + +	if (h5->state != H5_ACTIVE) { +		BT_ERR("Ignoring HCI data in non-active state"); +		kfree_skb(skb); +		return 0; +	} + +	switch (bt_cb(skb)->pkt_type) { +	case HCI_ACLDATA_PKT: +	case HCI_COMMAND_PKT: +		skb_queue_tail(&h5->rel, skb); +		break; + +	case HCI_SCODATA_PKT: +		skb_queue_tail(&h5->unrel, skb); +		break; + +	default: +		BT_ERR("Unknown packet type %u", bt_cb(skb)->pkt_type); +		kfree_skb(skb); +		break; +	} + +	return 0; +} + +static void h5_slip_delim(struct sk_buff *skb) +{ +	const char delim = SLIP_DELIMITER; + +	memcpy(skb_put(skb, 1), &delim, 1); +} + +static void h5_slip_one_byte(struct sk_buff *skb, u8 c) +{ +	const char esc_delim[2] = { SLIP_ESC, SLIP_ESC_DELIM }; +	const char esc_esc[2] = { SLIP_ESC, SLIP_ESC_ESC }; + +	switch (c) { +	case SLIP_DELIMITER: +		memcpy(skb_put(skb, 2), &esc_delim, 2); +		break; +	case SLIP_ESC: +		memcpy(skb_put(skb, 2), &esc_esc, 2); +		break; +	default: +		memcpy(skb_put(skb, 1), &c, 1); +	} +} + +static bool valid_packet_type(u8 type) +{ +	switch (type) { +	case HCI_ACLDATA_PKT: +	case HCI_COMMAND_PKT: +	case HCI_SCODATA_PKT: +	case HCI_3WIRE_LINK_PKT: +	case HCI_3WIRE_ACK_PKT: +		return true; +	default: +		return false; +	} +} + +static struct sk_buff *h5_prepare_pkt(struct hci_uart *hu, u8 pkt_type, +				      const u8 *data, size_t len) +{ +	struct h5 *h5 = hu->priv; +	struct sk_buff *nskb; +	u8 hdr[4]; +	int i; + +	if (!valid_packet_type(pkt_type)) { +		BT_ERR("Unknown packet type %u", pkt_type); +		return NULL; +	} + +	/* +	 * Max len of packet: (original len + 4 (H5 hdr) + 2 (crc)) * 2 +	 * (because bytes 0xc0 and 0xdb are escaped, worst case is when +	 * the packet is all made of 0xc0 and 0xdb) + 2 (0xc0 +	 * delimiters at start and end). +	 */ +	nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC); +	if (!nskb) +		return NULL; + +	bt_cb(nskb)->pkt_type = pkt_type; + +	h5_slip_delim(nskb); + +	hdr[0] = h5->tx_ack << 3; +	clear_bit(H5_TX_ACK_REQ, &h5->flags); + +	/* Reliable packet? */ +	if (pkt_type == HCI_ACLDATA_PKT || pkt_type == HCI_COMMAND_PKT) { +		hdr[0] |= 1 << 7; +		hdr[0] |= h5->tx_seq; +		h5->tx_seq = (h5->tx_seq + 1) % 8; +	} + +	hdr[1] = pkt_type | ((len & 0x0f) << 4); +	hdr[2] = len >> 4; +	hdr[3] = ~((hdr[0] + hdr[1] + hdr[2]) & 0xff); + +	BT_DBG("%s tx: seq %u ack %u crc %u rel %u type %u len %u", +	       hu->hdev->name, H5_HDR_SEQ(hdr), H5_HDR_ACK(hdr), +	       H5_HDR_CRC(hdr), H5_HDR_RELIABLE(hdr), H5_HDR_PKT_TYPE(hdr), +	       H5_HDR_LEN(hdr)); + +	for (i = 0; i < 4; i++) +		h5_slip_one_byte(nskb, hdr[i]); + +	for (i = 0; i < len; i++) +		h5_slip_one_byte(nskb, data[i]); + +	h5_slip_delim(nskb); + +	return nskb; +} + +static struct sk_buff *h5_dequeue(struct hci_uart *hu) +{ +	struct h5 *h5 = hu->priv; +	unsigned long flags; +	struct sk_buff *skb, *nskb; + +	if (h5->sleep != H5_AWAKE) { +		const unsigned char wakeup_req[] = { 0x05, 0xfa }; + +		if (h5->sleep == H5_WAKING_UP) +			return NULL; + +		h5->sleep = H5_WAKING_UP; +		BT_DBG("Sending wakeup request"); + +		mod_timer(&h5->timer, jiffies + HZ / 100); +		return h5_prepare_pkt(hu, HCI_3WIRE_LINK_PKT, wakeup_req, 2); +	} + +	skb = skb_dequeue(&h5->unrel); +	if (skb != NULL) { +		nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, +				      skb->data, skb->len); +		if (nskb) { +			kfree_skb(skb); +			return nskb; +		} + +		skb_queue_head(&h5->unrel, skb); +		BT_ERR("Could not dequeue pkt because alloc_skb failed"); +	} + +	spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING); + +	if (h5->unack.qlen >= h5->tx_win) +		goto unlock; + +	skb = skb_dequeue(&h5->rel); +	if (skb != NULL) { +		nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type, +				      skb->data, skb->len); +		if (nskb) { +			__skb_queue_tail(&h5->unack, skb); +			mod_timer(&h5->timer, jiffies + H5_ACK_TIMEOUT); +			spin_unlock_irqrestore(&h5->unack.lock, flags); +			return nskb; +		} + +		skb_queue_head(&h5->rel, skb); +		BT_ERR("Could not dequeue pkt because alloc_skb failed"); +	} + +unlock: +	spin_unlock_irqrestore(&h5->unack.lock, flags); + +	if (test_bit(H5_TX_ACK_REQ, &h5->flags)) +		return h5_prepare_pkt(hu, HCI_3WIRE_ACK_PKT, NULL, 0); + +	return NULL; +} + +static int h5_flush(struct hci_uart *hu) +{ +	BT_DBG("hu %p", hu); +	return 0; +} + +static struct hci_uart_proto h5p = { +	.id		= HCI_UART_3WIRE, +	.open		= h5_open, +	.close		= h5_close, +	.recv		= h5_recv, +	.enqueue	= h5_enqueue, +	.dequeue	= h5_dequeue, +	.flush		= h5_flush, +}; + +int __init h5_init(void) +{ +	int err = hci_uart_register_proto(&h5p); + +	if (!err) +		BT_INFO("HCI Three-wire UART (H5) protocol initialized"); +	else +		BT_ERR("HCI Three-wire UART (H5) protocol init failed"); + +	return err; +} + +int __exit h5_deinit(void) +{ +	return hci_uart_unregister_proto(&h5p); +} diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 720148294e6..e00f8f5b5c8 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -48,8 +48,6 @@  #define VERSION "2.2" -static int reset = 0; -  static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];  int hci_uart_register_proto(struct hci_uart_proto *p) @@ -120,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; @@ -131,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); @@ -155,6 +165,34 @@ restart:  		goto restart;  	clear_bit(HCI_UART_SENDING, &hu->tx_state); +} + +static void hci_uart_init_work(struct work_struct *work) +{ +	struct hci_uart *hu = container_of(work, struct hci_uart, init_ready); +	int err; + +	if (!test_and_clear_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) +		return; + +	err = hci_register_dev(hu->hdev); +	if (err < 0) { +		BT_ERR("Can't register HCI device"); +		hci_free_dev(hu->hdev); +		hu->hdev = NULL; +		hu->proto->close(hu); +	} + +	set_bit(HCI_UART_REGISTERED, &hu->flags); +} + +int hci_uart_init_ready(struct hci_uart *hu) +{ +	if (!test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) +		return -EALREADY; + +	schedule_work(&hu->init_ready); +  	return 0;  } @@ -174,7 +212,7 @@ static int hci_uart_open(struct hci_dev *hdev)  /* Reset device */  static int hci_uart_flush(struct hci_dev *hdev)  { -	struct hci_uart *hu  = (struct hci_uart *) hdev->driver_data; +	struct hci_uart *hu  = hci_get_drvdata(hdev);  	struct tty_struct *tty = hu->tty;  	BT_DBG("hdev %p tty %p", hdev, tty); @@ -207,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 = (struct hci_uart *) hdev->driver_data; -  	BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);  	hu->proto->enqueue(hu, skb); @@ -231,42 +261,29 @@ static int hci_uart_send_frame(struct sk_buff *skb)  	return 0;  } -static void hci_uart_destruct(struct hci_dev *hdev) -{ -	if (!hdev) -		return; - -	BT_DBG("%s", hdev->name); -	kfree(hdev->driver_data); -} -  /* ------ LDISC part ------ */  /* hci_uart_tty_open - *  + *   *     Called when line discipline changed to HCI_UART.   *   * Arguments:   *     tty    pointer to tty info structure - * Return Value:     + * Return Value:   *     0 if success, otherwise error code   */  static int hci_uart_tty_open(struct tty_struct *tty)  { -	struct hci_uart *hu = (void *) tty->disc_data; +	struct hci_uart *hu;  	BT_DBG("tty %p", tty); -	/* FIXME: This btw is bogus, nothing requires the old ldisc to clear -	   the pointer */ -	if (hu) -		return -EEXIST; -  	/* Error if the tty has no write op instead of leaving an exploitable  	   hole */  	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;  	} @@ -275,6 +292,9 @@ static int hci_uart_tty_open(struct tty_struct *tty)  	hu->tty = 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);  	/* Flush any pending characters in the driver and line discipline. */ @@ -297,24 +317,32 @@ static int hci_uart_tty_open(struct tty_struct *tty)  static void hci_uart_tty_close(struct tty_struct *tty)  {  	struct hci_uart *hu = (void *)tty->disc_data; +	struct hci_dev *hdev;  	BT_DBG("tty %p", tty);  	/* Detach from the tty */  	tty->disc_data = NULL; -	if (hu) { -		struct hci_dev *hdev = hu->hdev; +	if (!hu) +		return; -		if (hdev) -			hci_uart_close(hdev); +	hdev = hu->hdev; +	if (hdev) +		hci_uart_close(hdev); -		if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { -			hu->proto->close(hu); -			hci_unregister_dev(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)) +				hci_unregister_dev(hdev);  			hci_free_dev(hdev);  		} +		hu->proto->close(hu);  	} + +	kfree(hu);  }  /* hci_uart_tty_wakeup() @@ -344,15 +372,15 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)  }  /* hci_uart_tty_receive() - *  + *   *     Called by tty low level driver when receive data is   *     available. - *      + *   * Arguments:  tty          pointer to tty isntance data   *             data         pointer to received data   *             flags        pointer to flags for data   *             count        count of received data in bytes - *      + *   * Return Value:    None   */  static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count) @@ -367,7 +395,10 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f  	spin_lock(&hu->rx_lock);  	hu->proto->recv(hu, (void *) data, count); -	hu->hdev->stat.byte_rx += count; + +	if (hu->hdev) +		hu->hdev->stat.byte_rx += count; +  	spin_unlock(&hu->rx_lock);  	tty_unthrottle(tty); @@ -389,28 +420,36 @@ static int hci_uart_register_dev(struct hci_uart *hu)  	hu->hdev = hdev;  	hdev->bus = HCI_UART; -	hdev->driver_data = hu; +	hci_set_drvdata(hdev, hu);  	hdev->open  = hci_uart_open;  	hdev->close = hci_uart_close;  	hdev->flush = hci_uart_flush;  	hdev->send  = hci_uart_send_frame; -	hdev->destruct = hci_uart_destruct; - -	hdev->owner = THIS_MODULE; - -	if (!reset) -		set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); +	SET_HCIDEV_DEV(hdev, hu->tty->dev);  	if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))  		set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); +	if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) +		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + +	if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) +		hdev->dev_type = HCI_AMP; +	else +		hdev->dev_type = HCI_BREDR; + +	if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) +		return 0; +  	if (hci_register_dev(hdev) < 0) {  		BT_ERR("Can't register HCI device");  		hci_free_dev(hdev);  		return -ENODEV;  	} +	set_bit(HCI_UART_REGISTERED, &hu->flags); +  	return 0;  } @@ -497,7 +536,7 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,  	default:  		err = n_tty_ioctl_helper(tty, file, cmd, arg);  		break; -	}; +	}  	return err;  } @@ -545,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;  	} @@ -562,6 +602,9 @@ static int __init hci_uart_init(void)  #ifdef CONFIG_BT_HCIUART_ATH3K  	ath_init();  #endif +#ifdef CONFIG_BT_HCIUART_3WIRE +	h5_init(); +#endif  	return 0;  } @@ -582,18 +625,19 @@ static void __exit hci_uart_exit(void)  #ifdef CONFIG_BT_HCIUART_ATH3K  	ath_deinit();  #endif +#ifdef CONFIG_BT_HCIUART_3WIRE +	h5_deinit(); +#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);  }  module_init(hci_uart_init);  module_exit(hci_uart_exit); -module_param(reset, bool, 0644); -MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); -  MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");  MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);  MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 38595e782d0..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); @@ -125,7 +124,7 @@ static int ll_open(struct hci_uart *hu)  	BT_DBG("hu %p", hu); -	ll = kzalloc(sizeof(*ll), GFP_ATOMIC); +	ll = kzalloc(sizeof(*ll), GFP_KERNEL);  	if (!ll)  		return -ENOMEM; @@ -207,7 +206,7 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu)  		/*  		 * This state means that both the host and the BRF chip  		 * have simultaneously sent a wake-up-indication packet. -		 * Traditionaly, in this case, receiving a wake-up-indication +		 * Traditionally, in this case, receiving a wake-up-indication  		 * was enough and an additional wake-up-ack wasn't needed.  		 * This has changed with the BRF6350, which does require an  		 * explicit wake-up-ack. Other BRF versions, which do not @@ -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)  { -	register int room = skb_tailroom(ll->rx_skb); +	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); @@ -374,11 +373,11 @@ static inline int ll_check_data_len(struct ll_struct *ll, int len)  static int ll_recv(struct hci_uart *hu, void *data, int count)  {  	struct ll_struct *ll = hu->priv; -	register char *ptr; +	char *ptr;  	struct hci_event_hdr *eh;  	struct hci_acl_hdr   *ah;  	struct hci_sco_hdr   *sh; -	register int len, type, dlen; +	int len, type, dlen;  	BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count); @@ -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;  			}  		} @@ -481,7 +480,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count)  			hu->hdev->stat.err_rx++;  			ptr++; count--;  			continue; -		}; +		}  		ptr++; count--; @@ -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 99fb35239d1..12df101ca94 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -45,6 +45,9 @@  #define HCI_UART_ATH3K	5  #define HCI_UART_RAW_DEVICE	0 +#define HCI_UART_RESET_ON_INIT	1 +#define HCI_UART_CREATE_AMP	2 +#define HCI_UART_INIT_PENDING	3  struct hci_uart; @@ -64,6 +67,9 @@ struct hci_uart {  	unsigned long		flags;  	unsigned long		hdev_flags; +	struct work_struct	init_ready; +	struct work_struct	write_work; +  	struct hci_uart_proto	*proto;  	void			*priv; @@ -74,6 +80,7 @@ struct hci_uart {  /* HCI_UART proto flag bits */  #define HCI_UART_PROTO_SET	0 +#define HCI_UART_REGISTERED	1  /* TX states  */  #define HCI_UART_SENDING	1 @@ -82,6 +89,7 @@ struct hci_uart {  int hci_uart_register_proto(struct hci_uart_proto *p);  int hci_uart_unregister_proto(struct hci_uart_proto *p);  int hci_uart_tx_wakeup(struct hci_uart *hu); +int hci_uart_init_ready(struct hci_uart *hu);  #ifdef CONFIG_BT_HCIUART_H4  int h4_init(void); @@ -102,3 +110,8 @@ int ll_deinit(void);  int ath_init(void);  int ath_deinit(void);  #endif + +#ifdef CONFIG_BT_HCIUART_3WIRE +int h5_init(void); +int h5_deinit(void); +#endif diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 67c180c2c1e..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,15 +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) @@ -59,7 +62,7 @@ static int vhci_open_dev(struct hci_dev *hdev)  static int vhci_close_dev(struct hci_dev *hdev)  { -	struct vhci_data *data = hdev->driver_data; +	struct vhci_data *data = hci_get_drvdata(hdev);  	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))  		return 0; @@ -71,79 +74,160 @@ static int vhci_close_dev(struct hci_dev *hdev)  static int vhci_flush(struct hci_dev *hdev)  { -	struct vhci_data *data = hdev->driver_data; +	struct vhci_data *data = hci_get_drvdata(hdev);  	skb_queue_purge(&data->readq);  	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; - -	if (!hdev) { -		BT_ERR("Frame for unknown HCI device (hdev=NULL)"); -		return -ENODEV; -	} +	struct vhci_data *data = hci_get_drvdata(hdev);  	if (!test_bit(HCI_RUNNING, &hdev->flags))  		return -EBUSY; -	data = hdev->driver_data; -  	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 void vhci_destruct(struct hci_dev *hdev) +static int vhci_create_device(struct vhci_data *data, __u8 dev_type)  { -	kfree(hdev->driver_data); +	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) { +		kfree_skb(skb); +		return -ENOMEM; +	} + +	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; +	} + +	bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; + +	*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; + +		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; -	return count; +	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; @@ -151,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; @@ -188,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;  	} @@ -196,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) @@ -216,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) @@ -228,35 +318,14 @@ 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; -	hdev->driver_data = data; - -	hdev->open     = vhci_open_dev; -	hdev->close    = vhci_close_dev; -	hdev->flush    = vhci_flush; -	hdev->send     = vhci_send_frame; -	hdev->destruct = vhci_destruct; - -	hdev->owner = THIS_MODULE; - -	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 nonseekable_open(inode, file); +	return 0;  }  static int vhci_release(struct inode *inode, struct file *file) @@ -264,13 +333,15 @@ static int vhci_release(struct inode *inode, struct file *file)  	struct vhci_data *data = file->private_data;  	struct hci_dev *hdev = data->hdev; -	if (hci_unregister_dev(hdev) < 0) { -		BT_ERR("Can't unregister HCI device %s", hdev->name); -	} +	cancel_delayed_work_sync(&data->open_timeout); -	hci_free_dev(hdev); +	if (hdev) { +		hci_unregister_dev(hdev); +		hci_free_dev(hdev); +	}  	file->private_data = NULL; +	kfree(data);  	return 0;  } @@ -278,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, @@ -288,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) @@ -306,7 +377,12 @@ static void __exit vhci_exit(void)  module_init(vhci_init);  module_exit(vhci_exit); +module_param(amp, bool, 0644); +MODULE_PARM_DESC(amp, "Create AMP controller device"); +  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);  | 
