Commit 375e875c authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents b006ed54 69676b1c
......@@ -29,20 +29,6 @@
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 ssize_t btmrvl_hscfgcmd_write(struct file *file,
......@@ -91,47 +77,6 @@ static const struct file_operations btmrvl_hscfgcmd_fops = {
.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);
if (ret)
return ret;
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 = simple_open,
.llseek = default_llseek,
};
static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
......@@ -178,47 +123,6 @@ static const struct file_operations btmrvl_pscmd_fops = {
.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);
if (ret)
return ret;
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 = simple_open,
.llseek = default_llseek,
};
static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
......@@ -263,119 +167,6 @@ static const struct file_operations btmrvl_hscmd_fops = {
.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);
if (ret)
return ret;
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 = simple_open,
.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 = simple_open,
.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 = simple_open,
.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 = simple_open,
.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 = simple_open,
.llseek = default_llseek,
};
void btmrvl_debugfs_init(struct hci_dev *hdev)
{
struct btmrvl_private *priv = hci_get_drvdata(hdev);
......@@ -394,30 +185,28 @@ 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,
priv, &btmrvl_psmode_fops);
dbg->pscmd = debugfs_create_file("pscmd", 0644, dbg->config_dir,
priv, &btmrvl_pscmd_fops);
dbg->gpiogap = debugfs_create_file("gpiogap", 0644, dbg->config_dir,
priv, &btmrvl_gpiogap_fops);
dbg->hsmode = debugfs_create_file("hsmode", 0644, dbg->config_dir,
priv, &btmrvl_hsmode_fops);
dbg->hscmd = debugfs_create_file("hscmd", 0644, dbg->config_dir,
priv, &btmrvl_hscmd_fops);
dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
priv, &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, priv,
&btmrvl_curpsmode_fops);
dbg->psstate = debugfs_create_file("psstate", 0444, dbg->status_dir,
priv, &btmrvl_psstate_fops);
dbg->hsstate = debugfs_create_file("hsstate", 0444, dbg->status_dir,
priv, &btmrvl_hsstate_fops);
dbg->txdnldready = debugfs_create_file("txdnldready", 0444,
dbg->status_dir, priv,
&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)
......@@ -428,19 +217,8 @@ void btmrvl_debugfs_remove(struct hci_dev *hdev)
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);
}
......@@ -228,24 +228,24 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
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)
......@@ -874,7 +874,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
{
int ret = 0;
int ret;
u8 fws0;
int pollnum = MAX_POLL_TRIES;
......@@ -882,13 +882,14 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
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;
}
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) {
......@@ -918,15 +919,21 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
}
}
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;
}
......@@ -989,8 +996,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);
......
This diff is collapsed.
......@@ -1081,17 +1081,19 @@ struct hci_request {
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param);
void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
u8 event);
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
const void *param);
void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
const void *param, u8 event);
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
void *param, u32 timeout);
const void *param, u32 timeout);
struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
void *param, u8 event, u32 timeout);
const void *param, u8 event, u32 timeout);
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
const void *param);
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
......
......@@ -79,7 +79,8 @@ static void hci_req_cancel(struct hci_dev *hdev, int err)
}
}
struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 event)
static struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
u8 event)
{
struct hci_ev_cmd_complete *ev;
struct hci_event_hdr *hdr;
......@@ -134,7 +135,7 @@ struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 event)
}
struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
void *param, u8 event, u32 timeout)
const void *param, u8 event, u32 timeout)
{
DECLARE_WAITQUEUE(wait, current);
struct hci_request req;
......@@ -188,7 +189,7 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
EXPORT_SYMBOL(__hci_cmd_sync_ev);
struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
void *param, u32 timeout)
const void *param, u32 timeout)
{
return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout);
}
......@@ -377,6 +378,8 @@ static void bredr_setup(struct hci_request *req)
static void le_setup(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
/* Read LE Buffer Size */
hci_req_add(req, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
......@@ -391,6 +394,10 @@ static void le_setup(struct hci_request *req)
/* Read LE Supported States */
hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
/* LE-only controllers have LE implicitly enabled */
if (!lmp_bredr_capable(hdev))
set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
}
static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
......@@ -574,6 +581,10 @@ static void hci_set_le_support(struct hci_request *req)
struct hci_dev *hdev = req->hdev;
struct hci_cp_write_le_host_supported cp;
/* LE-only devices do not support explicit enablement */
if (!lmp_bredr_capable(hdev))
return;
memset(&cp, 0, sizeof(cp));
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
......@@ -2602,7 +2613,7 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
}
static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
u32 plen, void *param)
u32 plen, const void *param)
{
int len = HCI_COMMAND_HDR_SIZE + plen;
struct hci_command_hdr *hdr;
......@@ -2628,7 +2639,8 @@ static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
}
/* Send HCI command */
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
const void *param)
{
struct sk_buff *skb;
......@@ -2652,8 +2664,8 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
}
/* Queue a command to an asynchronous HCI request */
void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
u8 event)
void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
const void *param, u8 event)
{
struct hci_dev *hdev = req->hdev;
struct sk_buff *skb;
......@@ -2682,7 +2694,8 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
skb_queue_tail(&req->cmd_q, skb);
}
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
const void *param)
{
hci_req_add_ev(req, opcode, plen, param, 0);
}
......
......@@ -6314,12 +6314,13 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
kfree_skb(skb);
}
static void l2cap_att_channel(struct l2cap_conn *conn, u16 cid,
static void l2cap_att_channel(struct l2cap_conn *conn,
struct sk_buff *skb)
{
struct l2cap_chan *chan;
chan = l2cap_global_chan_by_scid(0, cid, conn->src, conn->dst);
chan = l2cap_global_chan_by_scid(0, L2CAP_CID_LE_DATA,
conn->src, conn->dst);
if (!chan)
goto drop;
......@@ -6368,7 +6369,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
break;
case L2CAP_CID_LE_DATA:
l2cap_att_channel(conn, cid, skb);
l2cap_att_channel(conn, skb);
break;
case L2CAP_CID_SMP:
......
......@@ -1351,6 +1351,11 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_INVALID_PARAMS);
/* LE-only devices do not allow toggling LE on/off */
if (!lmp_bredr_capable(hdev))
return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_REJECTED);
hci_dev_lock(hdev);
val = !!cp->val;
......@@ -3347,7 +3352,8 @@ static int powered_update_hci(struct hci_dev *hdev)
hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
}
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
lmp_bredr_capable(hdev)) {
struct hci_cp_write_le_host_supported cp;
cp.le = 1;
......
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