Commit fcd8c627 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2019-09-06

Here's the main bluetooth-next pull request for the 5.4 kernel.

 - Cleanups & fixes to btrtl driver
 - Fixes for Realtek devices in btusb, e.g. for suspend handling
 - Firmware loading support for BCM4345C5
 - hidp_send_message() return value handling fixes
 - Added support for utilizing Fast Advertising Interval
 - Various other minor cleanups & fixes

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e9ac25b7 8bb35370
...@@ -13,6 +13,7 @@ Required properties: ...@@ -13,6 +13,7 @@ Required properties:
* "brcm,bcm20702a1" * "brcm,bcm20702a1"
* "brcm,bcm4330-bt" * "brcm,bcm4330-bt"
* "brcm,bcm43438-bt" * "brcm,bcm43438-bt"
* "brcm,bcm4345c5"
Optional properties: Optional properties:
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}}) #define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}})
#define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}}) #define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}})
#define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}}) #define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}})
#define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}})
#define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}}) #define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}})
int btbcm_check_bdaddr(struct hci_dev *hdev) int btbcm_check_bdaddr(struct hci_dev *hdev)
...@@ -73,6 +74,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) ...@@ -73,6 +74,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
!bacmp(&bda->bdaddr, BDADDR_BCM2076B1) || !bacmp(&bda->bdaddr, BDADDR_BCM2076B1) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4324B3) || !bacmp(&bda->bdaddr, BDADDR_BCM4324B3) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4330B1) || !bacmp(&bda->bdaddr, BDADDR_BCM4330B1) ||
!bacmp(&bda->bdaddr, BDADDR_BCM4345C5) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A0) || !bacmp(&bda->bdaddr, BDADDR_BCM43430A0) ||
!bacmp(&bda->bdaddr, BDADDR_BCM43341B)) { !bacmp(&bda->bdaddr, BDADDR_BCM43341B)) {
bt_dev_info(hdev, "BCM: Using default device address (%pMR)", bt_dev_info(hdev, "BCM: Using default device address (%pMR)",
...@@ -332,6 +334,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { ...@@ -332,6 +334,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
{ 0x2122, "BCM4343A0" }, /* 001.001.034 */ { 0x2122, "BCM4343A0" }, /* 001.001.034 */
{ 0x2209, "BCM43430A1" }, /* 001.002.009 */ { 0x2209, "BCM43430A1" }, /* 001.002.009 */
{ 0x6119, "BCM4345C0" }, /* 003.001.025 */ { 0x6119, "BCM4345C0" }, /* 003.001.025 */
{ 0x6606, "BCM4345C5" }, /* 003.006.006 */
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */ { 0x230f, "BCM4356A2" }, /* 001.003.015 */
{ 0x220e, "BCM20702A1" }, /* 001.002.014 */ { 0x220e, "BCM20702A1" }, /* 001.002.014 */
{ 0x4217, "BCM4329B1" }, /* 002.002.023 */ { 0x4217, "BCM4329B1" }, /* 002.002.023 */
......
...@@ -106,8 +106,9 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) ...@@ -106,8 +106,9 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
bt_dev_dbg(hdev, "QCA pre shutdown cmd"); bt_dev_dbg(hdev, "QCA pre shutdown cmd");
skb = __hci_cmd_sync(hdev, QCA_PRE_SHUTDOWN_CMD, 0, skb = __hci_cmd_sync_ev(hdev, QCA_PRE_SHUTDOWN_CMD, 0,
NULL, HCI_INIT_TIMEOUT); NULL, HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
err = PTR_ERR(skb); err = PTR_ERR(skb);
bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err); bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err);
......
This diff is collapsed.
...@@ -435,6 +435,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = { ...@@ -435,6 +435,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
#define BTUSB_OOB_WAKE_ENABLED 11 #define BTUSB_OOB_WAKE_ENABLED 11
#define BTUSB_HW_RESET_ACTIVE 12 #define BTUSB_HW_RESET_ACTIVE 12
#define BTUSB_TX_WAIT_VND_EVT 13 #define BTUSB_TX_WAIT_VND_EVT 13
#define BTUSB_WAKEUP_DISABLE 14
struct btusb_data { struct btusb_data {
struct hci_dev *hdev; struct hci_dev *hdev;
...@@ -523,6 +524,36 @@ static void btusb_intel_cmd_timeout(struct hci_dev *hdev) ...@@ -523,6 +524,36 @@ static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
gpiod_set_value_cansleep(reset_gpio, 0); gpiod_set_value_cansleep(reset_gpio, 0);
} }
static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct gpio_desc *reset_gpio = data->reset_gpio;
if (++data->cmd_timeout_cnt < 5)
return;
if (!reset_gpio) {
bt_dev_err(hdev, "No gpio to reset Realtek device, ignoring");
return;
}
/* Toggle the hard reset line. The Realtek device is going to
* yank itself off the USB and then replug. The cleanup is handled
* correctly on the way out (standard USB disconnect), and the new
* device is detected cleanly and bound to the driver again like
* it should be.
*/
if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
bt_dev_err(hdev, "last reset failed? Not resetting again");
return;
}
bt_dev_err(hdev, "Reset Realtek device via gpio");
gpiod_set_value_cansleep(reset_gpio, 0);
msleep(200);
gpiod_set_value_cansleep(reset_gpio, 1);
}
static inline void btusb_free_frags(struct btusb_data *data) static inline void btusb_free_frags(struct btusb_data *data)
{ {
unsigned long flags; unsigned long flags;
...@@ -1175,6 +1206,13 @@ static int btusb_open(struct hci_dev *hdev) ...@@ -1175,6 +1206,13 @@ static int btusb_open(struct hci_dev *hdev)
*/ */
device_wakeup_enable(&data->udev->dev); device_wakeup_enable(&data->udev->dev);
/* Disable device remote wakeup when host is suspended
* For Realtek chips, global suspend without
* SET_FEATURE (DEVICE_REMOTE_WAKEUP) can save more power in device.
*/
if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags))
device_wakeup_disable(&data->udev->dev);
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
goto done; goto done;
...@@ -1238,6 +1276,11 @@ static int btusb_close(struct hci_dev *hdev) ...@@ -1238,6 +1276,11 @@ static int btusb_close(struct hci_dev *hdev)
goto failed; goto failed;
data->intf->needs_remote_wakeup = 0; data->intf->needs_remote_wakeup = 0;
/* Enable remote wake up for auto-suspend */
if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags))
data->intf->needs_remote_wakeup = 1;
device_wakeup_disable(&data->udev->dev); device_wakeup_disable(&data->udev->dev);
usb_autopm_put_interface(data->intf); usb_autopm_put_interface(data->intf);
...@@ -3770,12 +3813,13 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -3770,12 +3813,13 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_REALTEK) { if (id->driver_info & BTUSB_REALTEK) {
hdev->setup = btrtl_setup_realtek; hdev->setup = btrtl_setup_realtek;
hdev->shutdown = btrtl_shutdown_realtek; hdev->shutdown = btrtl_shutdown_realtek;
hdev->cmd_timeout = btusb_rtl_cmd_timeout;
/* Realtek devices lose their updated firmware over suspend, /* Realtek devices lose their updated firmware over global
* but the USB hub doesn't notice any status change. * suspend that means host doesn't send SET_FEATURE
* Explicitly request a device reset on resume. * (DEVICE_REMOTE_WAKEUP)
*/ */
interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; set_bit(BTUSB_WAKEUP_DISABLE, &data->flags);
} }
#endif #endif
...@@ -3949,6 +3993,19 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -3949,6 +3993,19 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
enable_irq(data->oob_wake_irq); enable_irq(data->oob_wake_irq);
} }
/* For global suspend, Realtek devices lose the loaded fw
* in them. But for autosuspend, firmware should remain.
* Actually, it depends on whether the usb host sends
* set feature (enable wakeup) or not.
*/
if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags)) {
if (PMSG_IS_AUTO(message) &&
device_can_wakeup(&data->udev->dev))
data->udev->do_remote_wakeup = 1;
else if (!PMSG_IS_AUTO(message))
data->udev->reset_resume = 1;
}
return 0; return 0;
} }
......
...@@ -260,7 +260,7 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) ...@@ -260,7 +260,7 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
} }
/* wait for device to power on and come out of reset */ /* wait for device to power on and come out of reset */
usleep_range(10000, 20000); usleep_range(100000, 120000);
dev->res_enabled = powered; dev->res_enabled = powered;
...@@ -824,6 +824,21 @@ static int bcm_resume(struct device *dev) ...@@ -824,6 +824,21 @@ static int bcm_resume(struct device *dev)
} }
#endif #endif
/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */
static const struct dmi_system_id bcm_broken_irq_dmi_table[] = {
{
.ident = "Meegopad T08",
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR,
"To be filled by OEM."),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "T3 MRD"),
DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V1.1"),
},
},
{ }
};
#ifdef CONFIG_ACPI
static const struct acpi_gpio_params first_gpio = { 0, 0, false }; static const struct acpi_gpio_params first_gpio = { 0, 0, false };
static const struct acpi_gpio_params second_gpio = { 1, 0, false }; static const struct acpi_gpio_params second_gpio = { 1, 0, false };
static const struct acpi_gpio_params third_gpio = { 2, 0, false }; static const struct acpi_gpio_params third_gpio = { 2, 0, false };
...@@ -842,21 +857,6 @@ static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = { ...@@ -842,21 +857,6 @@ static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = {
{ }, { },
}; };
/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */
static const struct dmi_system_id bcm_broken_irq_dmi_table[] = {
{
.ident = "Meegopad T08",
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR,
"To be filled by OEM."),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "T3 MRD"),
DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V1.1"),
},
},
{ }
};
#ifdef CONFIG_ACPI
static int bcm_resource(struct acpi_resource *ares, void *data) static int bcm_resource(struct acpi_resource *ares, void *data)
{ {
struct bcm_device *dev = data; struct bcm_device *dev = data;
...@@ -1419,6 +1419,7 @@ static void bcm_serdev_remove(struct serdev_device *serdev) ...@@ -1419,6 +1419,7 @@ static void bcm_serdev_remove(struct serdev_device *serdev)
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id bcm_bluetooth_of_match[] = { static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm20702a1" }, { .compatible = "brcm,bcm20702a1" },
{ .compatible = "brcm,bcm4345c5" },
{ .compatible = "brcm,bcm4330-bt" }, { .compatible = "brcm,bcm4330-bt" },
{ .compatible = "brcm,bcm43438-bt" }, { .compatible = "brcm,bcm43438-bt" },
{ }, { },
......
...@@ -502,26 +502,7 @@ static int qca_open(struct hci_uart *hu) ...@@ -502,26 +502,7 @@ static int qca_open(struct hci_uart *hu)
qca->tx_ibs_state = HCI_IBS_TX_ASLEEP; qca->tx_ibs_state = HCI_IBS_TX_ASLEEP;
qca->rx_ibs_state = HCI_IBS_RX_ASLEEP; qca->rx_ibs_state = HCI_IBS_RX_ASLEEP;
/* clocks actually on, but we start votes off */
qca->tx_vote = false;
qca->rx_vote = false;
qca->flags = 0;
qca->ibs_sent_wacks = 0;
qca->ibs_sent_slps = 0;
qca->ibs_sent_wakes = 0;
qca->ibs_recv_wacks = 0;
qca->ibs_recv_slps = 0;
qca->ibs_recv_wakes = 0;
qca->vote_last_jif = jiffies; qca->vote_last_jif = jiffies;
qca->vote_on_ms = 0;
qca->vote_off_ms = 0;
qca->votes_on = 0;
qca->votes_off = 0;
qca->tx_votes_on = 0;
qca->tx_votes_off = 0;
qca->rx_votes_on = 0;
qca->rx_votes_off = 0;
hu->priv = qca; hu->priv = qca;
...@@ -1261,6 +1242,11 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1261,6 +1242,11 @@ static int qca_setup(struct hci_uart *hu)
/* Patch downloading has to be done without IBS mode */ /* Patch downloading has to be done without IBS mode */
clear_bit(QCA_IBS_ENABLED, &qca->flags); clear_bit(QCA_IBS_ENABLED, &qca->flags);
/* Enable controller to do both LE scan and BR/EDR inquiry
* simultaneously.
*/
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
if (qca_is_wcn399x(soc_type)) { if (qca_is_wcn399x(soc_type)) {
bt_dev_info(hdev, "setting up wcn3990"); bt_dev_info(hdev, "setting up wcn3990");
...@@ -1326,7 +1312,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1326,7 +1312,7 @@ static int qca_setup(struct hci_uart *hu)
return ret; return ret;
} }
static struct hci_uart_proto qca_proto = { static const struct hci_uart_proto qca_proto = {
.id = HCI_UART_QCA, .id = HCI_UART_QCA,
.name = "QCA", .name = "QCA",
.manufacturer = 29, .manufacturer = 29,
...@@ -1389,6 +1375,8 @@ static int qca_power_off(struct hci_dev *hdev) ...@@ -1389,6 +1375,8 @@ static int qca_power_off(struct hci_dev *hdev)
/* Perform pre shutdown command */ /* Perform pre shutdown command */
qca_send_pre_shutdown_cmd(hdev); qca_send_pre_shutdown_cmd(hdev);
usleep_range(8000, 10000);
qca_power_shutdown(hu); qca_power_shutdown(hu);
return 0; return 0;
} }
......
...@@ -303,7 +303,7 @@ static void ms_ff_worker(struct work_struct *work) ...@@ -303,7 +303,7 @@ static void ms_ff_worker(struct work_struct *work)
r->magnitude[MAGNITUDE_WEAK] = ms->weak; /* right actuator */ r->magnitude[MAGNITUDE_WEAK] = ms->weak; /* right actuator */
ret = hid_hw_output_report(hdev, (__u8 *)r, sizeof(*r)); ret = hid_hw_output_report(hdev, (__u8 *)r, sizeof(*r));
if (ret) if (ret < 0)
hid_warn(hdev, "failed to send FF report\n"); hid_warn(hdev, "failed to send FF report\n");
} }
......
...@@ -1517,6 +1517,8 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c); ...@@ -1517,6 +1517,8 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c);
#define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04 #define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04
#define DISCOV_BREDR_INQUIRY_LEN 0x08 #define DISCOV_BREDR_INQUIRY_LEN 0x08
#define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */
#define DISCOV_LE_FAST_ADV_INT_MIN 100 /* msec */
#define DISCOV_LE_FAST_ADV_INT_MAX 150 /* msec */
void mgmt_fill_version_info(void *ver); void mgmt_fill_version_info(void *ver);
int mgmt_new_settings(struct hci_dev *hdev); int mgmt_new_settings(struct hci_dev *hdev);
......
...@@ -583,7 +583,7 @@ static const struct net_device_ops netdev_ops = { ...@@ -583,7 +583,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_start_xmit = bt_xmit, .ndo_start_xmit = bt_xmit,
}; };
static struct header_ops header_ops = { static const struct header_ops header_ops = {
.create = header_create, .create = header_create,
}; };
......
...@@ -1054,6 +1054,7 @@ void __hci_req_enable_advertising(struct hci_request *req) ...@@ -1054,6 +1054,7 @@ void __hci_req_enable_advertising(struct hci_request *req)
struct hci_cp_le_set_adv_param cp; struct hci_cp_le_set_adv_param cp;
u8 own_addr_type, enable = 0x01; u8 own_addr_type, enable = 0x01;
bool connectable; bool connectable;
u16 adv_min_interval, adv_max_interval;
u32 flags; u32 flags;
flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance); flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance);
...@@ -1087,16 +1088,30 @@ void __hci_req_enable_advertising(struct hci_request *req) ...@@ -1087,16 +1088,30 @@ void __hci_req_enable_advertising(struct hci_request *req)
return; return;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
if (connectable) if (connectable) {
cp.type = LE_ADV_IND; cp.type = LE_ADV_IND;
else if (get_cur_adv_instance_scan_rsp_len(hdev))
adv_min_interval = hdev->le_adv_min_interval;
adv_max_interval = hdev->le_adv_max_interval;
} else {
if (get_cur_adv_instance_scan_rsp_len(hdev))
cp.type = LE_ADV_SCAN_IND; cp.type = LE_ADV_SCAN_IND;
else else
cp.type = LE_ADV_NONCONN_IND; cp.type = LE_ADV_NONCONN_IND;
if (!hci_dev_test_flag(hdev, HCI_DISCOVERABLE) ||
hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) {
adv_min_interval = DISCOV_LE_FAST_ADV_INT_MIN;
adv_max_interval = DISCOV_LE_FAST_ADV_INT_MAX;
} else {
adv_min_interval = hdev->le_adv_min_interval;
adv_max_interval = hdev->le_adv_max_interval;
}
}
cp.min_interval = cpu_to_le16(adv_min_interval);
cp.max_interval = cpu_to_le16(adv_max_interval);
cp.own_address_type = own_addr_type; cp.own_address_type = own_addr_type;
cp.channel_map = hdev->le_adv_channel_map; cp.channel_map = hdev->le_adv_channel_map;
......
...@@ -267,7 +267,7 @@ static int hidp_get_raw_report(struct hid_device *hid, ...@@ -267,7 +267,7 @@ static int hidp_get_raw_report(struct hid_device *hid,
set_bit(HIDP_WAITING_FOR_RETURN, &session->flags); set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
data[0] = report_number; data[0] = report_number;
ret = hidp_send_ctrl_message(session, report_type, data, 1); ret = hidp_send_ctrl_message(session, report_type, data, 1);
if (ret) if (ret < 0)
goto err; goto err;
/* Wait for the return of the report. The returned report /* Wait for the return of the report. The returned report
...@@ -343,7 +343,7 @@ static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum, ...@@ -343,7 +343,7 @@ static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum,
data[0] = reportnum; data[0] = reportnum;
set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
ret = hidp_send_ctrl_message(session, report_type, data, count); ret = hidp_send_ctrl_message(session, report_type, data, count);
if (ret) if (ret < 0)
goto err; goto err;
/* Wait for the ACK from the device. */ /* Wait for the ACK from the device. */
......
...@@ -2588,7 +2588,6 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2588,7 +2588,6 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
{ {
struct mgmt_rp_get_connections *rp; struct mgmt_rp_get_connections *rp;
struct hci_conn *c; struct hci_conn *c;
size_t rp_len;
int err; int err;
u16 i; u16 i;
...@@ -2608,8 +2607,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2608,8 +2607,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
i++; i++;
} }
rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info)); rp = kmalloc(struct_size(rp, addr, i), GFP_KERNEL);
rp = kmalloc(rp_len, GFP_KERNEL);
if (!rp) { if (!rp) {
err = -ENOMEM; err = -ENOMEM;
goto unlock; goto unlock;
...@@ -2629,10 +2627,8 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2629,10 +2627,8 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
rp->conn_count = cpu_to_le16(i); rp->conn_count = cpu_to_le16(i);
/* Recalculate length in case of filtered SCO connections, etc */ /* Recalculate length in case of filtered SCO connections, etc */
rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp, err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
rp_len); struct_size(rp, addr, i));
kfree(rp); kfree(rp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment