]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 29 Apr 2013 19:31:57 +0000 (15:31 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 29 Apr 2013 19:31:57 +0000 (15:31 -0400)
29 files changed:
drivers/bluetooth/btmrvl_debugfs.c
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btusb.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/iwlwifi/dvm/agn.h
drivers/net/wireless/iwlwifi/dvm/debugfs.c
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/dvm/sta.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
drivers/net/wireless/iwlwifi/mvm/power.c
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/rtlwifi/usb.c
drivers/ssb/driver_chipcommon_pmu.c
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/bluetooth/l2cap_core.c
net/bluetooth/mgmt.c
net/nfc/Kconfig
net/nfc/Makefile
net/nfc/llcp.h [moved from net/nfc/llcp/llcp.h with 100% similarity]
net/nfc/llcp/Kconfig [deleted file]
net/nfc/llcp_commands.c [moved from net/nfc/llcp/commands.c with 99% similarity]
net/nfc/llcp_core.c [moved from net/nfc/llcp/llcp.c with 99% similarity]
net/nfc/llcp_sock.c [moved from net/nfc/llcp/sock.c with 99% similarity]
net/nfc/netlink.c
net/nfc/nfc.h

index 428dbb7574bd75aa43d84ba5af353a134d1abfd3..db2c3c305df8ea183d499861089e7e446d2beabe 100644 (file)
 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);
 }
index 1cb51839912d0e791254349a64f171ec2a9754a2..c63488c54f4aa5e465f774a16f2f44f360723dc1 100644 (file)
@@ -228,24 +228,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)
@@ -874,7 +874,7 @@ exit:
 
 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);
index 3d684d20b58476b1edf7ae6e744c6620a459a82e..7a7e5f8ecadcffef990eaea6c2fafdcf94ff4c4b 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/firmware.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -47,6 +48,7 @@ static struct usb_driver btusb_driver;
 #define BTUSB_BROKEN_ISOC      0x20
 #define BTUSB_WRONG_SCO_MTU    0x40
 #define BTUSB_ATH3012          0x80
+#define BTUSB_INTEL            0x100
 
 static struct usb_device_id btusb_table[] = {
        /* Generic Bluetooth USB device */
@@ -207,6 +209,9 @@ 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 },
+
        { }     /* Terminating entry */
 };
 
@@ -943,6 +948,375 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev)
        return 0;
 }
 
+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_probe(struct usb_interface *intf,
                                const struct usb_device_id *id)
 {
@@ -1048,6 +1422,9 @@ static int btusb_probe(struct usb_interface *intf,
        if (id->driver_info & BTUSB_BCM92035)
                hdev->setup = btusb_setup_bcm92035;
 
+       if (id->driver_info & BTUSB_INTEL)
+               hdev->setup = btusb_setup_intel;
+
        /* Interface numbers are hardcoded in the specification */
        data->isoc = usb_ifnum_to_if(data->udev, 1);
 
index 2346821667e6a715b7d2c8d62b8fb97977dfd2b9..3a6544710c8ab222cc126ef53d5f19143498cc9e 100644 (file)
@@ -336,6 +336,7 @@ static void brcms_remove(struct bcma_device *pdev)
        struct brcms_info *wl = hw->priv;
 
        if (wl->wlc) {
+               brcms_led_unregister(wl);
                wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
                wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
                ieee80211_unregister_hw(hw);
index e575b9b0cda8542c24693ce591272cd99ca1f486..48545ab003110559f4c5d097024c1066afbcd530 100644 (file)
@@ -172,7 +172,7 @@ int iwl_calib_set(struct iwl_priv *priv,
                  const struct iwl_calib_hdr *cmd, int len);
 void iwl_calib_free_results(struct iwl_priv *priv);
 int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-                           char **buf, bool display);
+                           char **buf);
 int iwlagn_hw_valid_rtc_data_addr(u32 addr);
 
 /* lib */
index 7b8178be119f4d0a110a2beaae3a91165df45bf1..d5329489245a74ccb5cac363e3831e36648c1ce3 100644 (file)
@@ -2237,15 +2237,13 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file,
                                         size_t count, loff_t *ppos)
 {
        struct iwl_priv *priv = file->private_data;
-       char *buf;
-       int pos = 0;
-       ssize_t ret = -ENOMEM;
+       char *buf = NULL;
+       ssize_t ret;
 
-       ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true);
-       if (buf) {
-               ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-               kfree(buf);
-       }
+       ret = iwl_dump_nic_event_log(priv, true, &buf);
+       if (ret > 0)
+               ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+       kfree(buf);
        return ret;
 }
 
@@ -2269,7 +2267,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
        if (sscanf(buf, "%d", &event_log_flag) != 1)
                return -EFAULT;
        if (event_log_flag == 1)
-               iwl_dump_nic_event_log(priv, true, NULL, false);
+               iwl_dump_nic_event_log(priv, true, NULL);
 
        return count;
 }
index b9e3517652d649f4514ea9b3608f479cc5c81991..74d7572e709125160f0a0db02b8e337d23d96cc5 100644 (file)
@@ -1795,7 +1795,7 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
 #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
 
 int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-                           char **buf, bool display)
+                           char **buf)
 {
        u32 base;       /* SRAM byte address of event log header */
        u32 capacity;   /* event log capacity in # entries */
@@ -1866,7 +1866,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
                size);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
-       if (display) {
+       if (buf) {
                if (full_log)
                        bufsz = capacity * 48;
                else
@@ -1962,7 +1962,7 @@ static void iwl_nic_error(struct iwl_op_mode *op_mode)
                priv->fw->fw_version);
 
        iwl_dump_nic_error_log(priv);
-       iwl_dump_nic_event_log(priv, false, NULL, false);
+       iwl_dump_nic_event_log(priv, false, NULL);
 
        iwlagn_fw_error(priv, false);
 }
index b775769f8322c437558712af955332296e95db89..db183b44e038ba7f1ed5a63f31bf7497e3599428 100644 (file)
@@ -695,6 +695,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
 void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
        struct iwl_addsta_cmd sta_cmd;
+       static const struct iwl_link_quality_cmd zero_lq = {};
        struct iwl_link_quality_cmd lq;
        int i;
        bool found = false;
@@ -733,7 +734,9 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
                                else
                                        memcpy(&lq, priv->stations[i].lq,
                                               sizeof(struct iwl_link_quality_cmd));
-                               send_lq = true;
+
+                               if (!memcmp(&lq, &zero_lq, sizeof(lq)))
+                                       send_lq = true;
                        }
                        spin_unlock_bh(&priv->sta_lock);
                        ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
index fe031608fd912ce67201358a187031a09c8cb549..dd158ec571fbb183374858e20ffd80325206db9d 100644 (file)
@@ -207,7 +207,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 
        hw->wiphy->hw_version = mvm->trans->hw_id;
 
-       if (iwlwifi_mod_params.power_save)
+       if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
                hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
        else
                hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
index 0f0b44eabd937a88ce615e3f6a5fe5ada0fe805f..a28a1d1f23eb8caba29ff4501c1962a527f6e50d 100644 (file)
@@ -153,11 +153,6 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
        cmd->ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef);
 
        /* Set rx the chains */
-
-       /* TODO:
-        * Need to add on chain noise calibration limitations, and
-        * BT coex considerations.
-        */
        idle_cnt = chains_static;
        active_cnt = chains_dynamic;
 
index 9395ab2a1af2cc60838542eb312428e9c31aa0c7..ed77e437aac49d513525b12725f3d70baad461e9 100644 (file)
@@ -111,8 +111,7 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
         */
        cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
 
-       if ((iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) ||
-           !iwlwifi_mod_params.power_save)
+       if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
                return;
 
        cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
@@ -146,14 +145,8 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
        cmd->keep_alive_seconds = keep_alive;
 
-       if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP) {
-               /* TODO: Also for D3 (device sleep / WoWLAN) */
-               cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
-               cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
-       } else {
-               cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
-               cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
-       }
+       cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
+       cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
 }
 
 int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -177,8 +170,7 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
        if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
                return 0;
 
-       if ((iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) &&
-           iwlwifi_mod_params.power_save)
+       if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
                cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
 
        iwl_mvm_power_log(mvm, &cmd);
index 0cc8d8c0d39372f22752130dea146fc8b8e5ffd8..687b34e387ac325b0b5b5a3cf869625d31341ad4 100644 (file)
@@ -253,8 +253,9 @@ int iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 u8 first_antenna(u8 mask)
 {
        BUILD_BUG_ON(ANT_A != BIT(0)); /* using ffs is wrong if not */
-       WARN_ON_ONCE(!mask); /* ffs will return 0 if mask is zeroed */
-       return (u8)(BIT(ffs(mask)));
+       if (WARN_ON_ONCE(!mask)) /* ffs will return 0 if mask is zeroed */
+               return BIT(0);
+       return BIT(ffs(mask) - 1);
 }
 
 /*
index 0016bb24b3d7c874cd7da3fcb32a23d64190d6a2..8cb53ec2b77bc6534faf95efaf64377e80ceb798 100644 (file)
@@ -256,6 +256,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 
 /* 7000 Series */
        {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_ac_cfg)},
index 80f282c0bd4d0a4dcf9f159f6c831b91a0003f8d..20c9c4c7b0b2eb64fa75bd4180fd85015d77b33e 100644 (file)
@@ -861,9 +861,8 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
 
        if (card && card->cmd_buf) {
                MWIFIEX_SKB_PACB(card->cmd_buf, &buf_pa);
-               pci_unmap_single(card->dev, buf_pa, MWIFIEX_SIZE_OF_CMD_BUFFER,
+               pci_unmap_single(card->dev, buf_pa, card->cmd_buf->len,
                                 PCI_DMA_TODEVICE);
-               dev_kfree_skb_any(card->cmd_buf);
        }
        return 0;
 }
@@ -1573,7 +1572,7 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
        skb_tmp = card->cmd_buf;
        if (skb_tmp) {
                MWIFIEX_SKB_PACB(skb_tmp, &buf_pa);
-               pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
+               pci_unmap_single(card->dev, buf_pa, skb_tmp->len,
                                 PCI_DMA_FROMDEVICE);
                card->cmd_buf = NULL;
        }
@@ -2294,9 +2293,9 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
        if (pdev) {
                pci_iounmap(pdev, card->pci_mmap);
                pci_iounmap(pdev, card->pci_mmap1);
-
-               pci_release_regions(pdev);
                pci_disable_device(pdev);
+               pci_release_region(pdev, 2);
+               pci_release_region(pdev, 0);
                pci_set_drvdata(pdev, NULL);
        }
 }
index 83915dcd0e58505ca8970352e2fbac35dd1d48a8..76732b0cd221f13d937297f8fd1e4c08fd0c2d89 100644 (file)
@@ -521,6 +521,9 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
                                rtlpriv->link_info.num_rx_inperiod++;
                }
 
+               /* static bcn for roaming */
+               rtl_beacon_statistic(hw, skb);
+
                if (likely(rtl_action_proc(hw, skb, false)))
                        ieee80211_rx(hw, skb);
                else
index 23c5dbfea115acdf9a2272c365fcc0ecbf89d14c..1173a091b402e1b73984d945cce2c2358cbc638f 100644 (file)
@@ -687,8 +687,23 @@ void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
                pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
                break;
        case 43222:
-               /* TODO: BCM43222 requires updating PLLs too */
-               return;
+               if (spuravoid == 1) {
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11500008);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0C000C06);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x0F600a08);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x2001E920);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888815);
+               } else {
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100008);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x0c000c06);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x03000a08);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, 0x00000000);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL4, 0x200005c0);
+                       ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888855);
+               }
+               pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
+               break;
        default:
                ssb_printk(KERN_ERR PFX
                           "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
index 80d718a9b31f349df529674c15ac29c04e93bb98..35a57cd1704c30576a76fb9758855f6ba333abcc 100644 (file)
@@ -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);
 
index ce82265f56190af81092fe0fe8a0e0426b486051..33843c5c49398f0e2a373de8919cde67a840451a 100644 (file)
@@ -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 @@ failed:
 }
 
 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);
 }
index eae1d9f90b68adab6dc9cf3de035c86219be1309..a76d1ac0321b40f48f6de231f31ff14e2af363df 100644 (file)
@@ -6314,12 +6314,13 @@ drop:
        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:
index 4c830c62ef7412a8b4888b7a775b68117591240a..35fef22703e9dc3661c88d3adb5b5abc9532c463 100644 (file)
@@ -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;
index 60c3bbb63e8efaf1ea9de16e32641de804235829..5948b2fc72f63d3a9994e962b1366f8913c61ed7 100644 (file)
@@ -4,6 +4,7 @@
 
 menuconfig NFC
        depends on NET
+       depends on RFKILL || !RFKILL
        tristate "NFC subsystem support"
        default n
        help
@@ -15,6 +16,5 @@ menuconfig NFC
 
 source "net/nfc/nci/Kconfig"
 source "net/nfc/hci/Kconfig"
-source "net/nfc/llcp/Kconfig"
 
 source "drivers/nfc/Kconfig"
index d1a117c2c401720864b0566bd4fca0ef82bf6fbf..fb799deaed4f9d5b130e88ed5402190b33fea1f6 100644 (file)
@@ -5,6 +5,8 @@
 obj-$(CONFIG_NFC) += nfc.o
 obj-$(CONFIG_NFC_NCI) += nci/
 obj-$(CONFIG_NFC_HCI) += hci/
+#obj-$(CONFIG_NFC_LLCP) += llcp/
+
+nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \
+               llcp_sock.o
 
-nfc-objs := core.o netlink.o af_nfc.o rawsock.o
-nfc-$(CONFIG_NFC_LLCP) += llcp/llcp.o llcp/commands.o llcp/sock.o
similarity index 100%
rename from net/nfc/llcp/llcp.h
rename to net/nfc/llcp.h
diff --git a/net/nfc/llcp/Kconfig b/net/nfc/llcp/Kconfig
deleted file mode 100644 (file)
index a1a41cd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-config NFC_LLCP
-       depends on NFC
-       bool "NFC LLCP support"
-       default n
-       help
-        Say Y here if you want to build support for a kernel NFC LLCP
-        implementation.
\ No newline at end of file
similarity index 99%
rename from net/nfc/llcp/commands.c
rename to net/nfc/llcp_commands.c
index 094f7e27e91061200c184501b327ce1dded316f8..c1b23eef83ca9180bb65cf0406e5424a8a558ada 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <net/nfc/nfc.h>
 
-#include "../nfc.h"
+#include "nfc.h"
 #include "llcp.h"
 
 static u8 llcp_tlv_length[LLCP_TLV_MAX] = {
similarity index 99%
rename from net/nfc/llcp/llcp.c
rename to net/nfc/llcp_core.c
index 9e483c8e52f8d81d2319ef0e1832c88b9a38928c..158bdbf668ccf91fb211f49107d6b770d2fe98e4 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/list.h>
 #include <linux/nfc.h>
 
-#include "../nfc.h"
+#include "nfc.h"
 #include "llcp.h"
 
 static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
similarity index 99%
rename from net/nfc/llcp/sock.c
rename to net/nfc/llcp_sock.c
index d6faa47c9bbab217df079d7b39be613bc8a05061..38f08c31cdd878dea45df5dd8d01d2c21d90911f 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/module.h>
 #include <linux/nfc.h>
 
-#include "../nfc.h"
+#include "nfc.h"
 #include "llcp.h"
 
 static int sock_wait_state(struct sock *sk, int state, unsigned long timeo)
index 73fd51098f4dc1250ecc89fe160f56055b635987..f0c4d61f37c0f623df3eb40a1222a87f9c875f69 100644 (file)
@@ -28,8 +28,7 @@
 #include <linux/slab.h>
 
 #include "nfc.h"
-
-#include "llcp/llcp.h"
+#include "llcp.h"
 
 static struct genl_multicast_group nfc_genl_event_mcgrp = {
        .name = NFC_GENL_MCAST_EVENT_NAME,
index 94bfe19ba678186cb7467ae03213f07e638046dd..afa1f84ba0406c6bb7622043302a2a6d9bb04703 100644 (file)
@@ -48,8 +48,6 @@ struct nfc_rawsock {
 
 struct nfc_llcp_sdp_tlv;
 
-#ifdef CONFIG_NFC_LLCP
-
 void nfc_llcp_mac_is_down(struct nfc_dev *dev);
 void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
                        u8 comm_mode, u8 rf_mode);
@@ -64,68 +62,6 @@ void nfc_llcp_exit(void);
 void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);
 void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head);
 
-#else
-
-static inline void nfc_llcp_mac_is_down(struct nfc_dev *dev)
-{
-}
-
-static inline void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
-                                     u8 comm_mode, u8 rf_mode)
-{
-}
-
-static inline int nfc_llcp_register_device(struct nfc_dev *dev)
-{
-       return 0;
-}
-
-static inline void nfc_llcp_unregister_device(struct nfc_dev *dev)
-{
-}
-
-static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev,
-                                        u8 *gb, u8 gb_len)
-{
-       return 0;
-}
-
-static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len)
-{
-       *gb_len = 0;
-       return NULL;
-}
-
-static inline int nfc_llcp_data_received(struct nfc_dev *dev,
-                                        struct sk_buff *skb)
-{
-       return 0;
-}
-
-static inline struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
-{
-       return NULL;
-}
-
-static inline int nfc_llcp_init(void)
-{
-       return 0;
-}
-
-static inline void nfc_llcp_exit(void)
-{
-}
-
-static inline void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp)
-{
-}
-
-static inline void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head)
-{
-}
-
-#endif
-
 int __init rawsock_init(void);
 void rawsock_exit(void);