netem: fix classful handling
[cascardo/linux.git] / net / nfc / core.c
index 47e02c1..3ddf6e6 100644 (file)
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/nfc.h>
 
 #include "nfc.h"
 
 int nfc_devlist_generation;
 DEFINE_MUTEX(nfc_devlist_mutex);
 
-int nfc_printk(const char *level, const char *format, ...)
-{
-       struct va_format vaf;
-       va_list args;
-       int r;
-
-       va_start(args, format);
-
-       vaf.fmt = format;
-       vaf.va = &args;
-
-       r = printk("%sNFC: %pV\n", level, &vaf);
-
-       va_end(args);
-
-       return r;
-}
-EXPORT_SYMBOL(nfc_printk);
-
 /**
  * nfc_dev_up - turn on the NFC device
  *
@@ -63,7 +47,7 @@ int nfc_dev_up(struct nfc_dev *dev)
 {
        int rc = 0;
 
-       nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+       pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
        device_lock(&dev->dev);
 
@@ -97,7 +81,7 @@ int nfc_dev_down(struct nfc_dev *dev)
 {
        int rc = 0;
 
-       nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+       pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
        device_lock(&dev->dev);
 
@@ -139,7 +123,8 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
 {
        int rc;
 
-       nfc_dbg("dev_name=%s protocols=0x%x", dev_name(&dev->dev), protocols);
+       pr_debug("dev_name=%s protocols=0x%x\n",
+                dev_name(&dev->dev), protocols);
 
        if (!protocols)
                return -EINVAL;
@@ -174,7 +159,7 @@ int nfc_stop_poll(struct nfc_dev *dev)
 {
        int rc = 0;
 
-       nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+       pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
        device_lock(&dev->dev);
 
@@ -196,6 +181,86 @@ error:
        return rc;
 }
 
+int nfc_dep_link_up(struct nfc_dev *dev, int target_index,
+                                       u8 comm_mode, u8 rf_mode)
+{
+       int rc = 0;
+
+       pr_debug("dev_name=%s comm:%d rf:%d\n",
+                       dev_name(&dev->dev), comm_mode, rf_mode);
+
+       if (!dev->ops->dep_link_up)
+               return -EOPNOTSUPP;
+
+       device_lock(&dev->dev);
+
+       if (!device_is_registered(&dev->dev)) {
+               rc = -ENODEV;
+               goto error;
+       }
+
+       if (dev->dep_link_up == true) {
+               rc = -EALREADY;
+               goto error;
+       }
+
+       rc = dev->ops->dep_link_up(dev, target_index, comm_mode, rf_mode);
+
+error:
+       device_unlock(&dev->dev);
+       return rc;
+}
+
+int nfc_dep_link_down(struct nfc_dev *dev)
+{
+       int rc = 0;
+
+       pr_debug("dev_name=%s\n", dev_name(&dev->dev));
+
+       if (!dev->ops->dep_link_down)
+               return -EOPNOTSUPP;
+
+       device_lock(&dev->dev);
+
+       if (!device_is_registered(&dev->dev)) {
+               rc = -ENODEV;
+               goto error;
+       }
+
+       if (dev->dep_link_up == false) {
+               rc = -EALREADY;
+               goto error;
+       }
+
+       if (dev->dep_rf_mode == NFC_RF_TARGET) {
+               rc = -EOPNOTSUPP;
+               goto error;
+       }
+
+       rc = dev->ops->dep_link_down(dev);
+       if (!rc) {
+               dev->dep_link_up = false;
+               nfc_llcp_mac_is_down(dev);
+               nfc_genl_dep_link_down_event(dev);
+       }
+
+error:
+       device_unlock(&dev->dev);
+       return rc;
+}
+
+int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
+                                       u8 comm_mode, u8 rf_mode)
+{
+       dev->dep_link_up = true;
+       dev->dep_rf_mode = rf_mode;
+
+       nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode);
+
+       return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode);
+}
+EXPORT_SYMBOL(nfc_dep_link_is_up);
+
 /**
  * nfc_activate_target - prepare the target for data exchange
  *
@@ -207,8 +272,8 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
 {
        int rc;
 
-       nfc_dbg("dev_name=%s target_idx=%u protocol=%u", dev_name(&dev->dev),
-                                                       target_idx, protocol);
+       pr_debug("dev_name=%s target_idx=%u protocol=%u\n",
+                dev_name(&dev->dev), target_idx, protocol);
 
        device_lock(&dev->dev);
 
@@ -236,7 +301,8 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
 {
        int rc = 0;
 
-       nfc_dbg("dev_name=%s target_idx=%u", dev_name(&dev->dev), target_idx);
+       pr_debug("dev_name=%s target_idx=%u\n",
+                dev_name(&dev->dev), target_idx);
 
        device_lock(&dev->dev);
 
@@ -271,8 +337,8 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
 {
        int rc;
 
-       nfc_dbg("dev_name=%s target_idx=%u skb->len=%u", dev_name(&dev->dev),
-                                                       target_idx, skb->len);
+       pr_debug("dev_name=%s target_idx=%u skb->len=%u\n",
+                dev_name(&dev->dev), target_idx, skb->len);
 
        device_lock(&dev->dev);
 
@@ -289,13 +355,54 @@ error:
        return rc;
 }
 
+int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
+{
+       pr_debug("dev_name=%s gb_len=%d\n",
+                       dev_name(&dev->dev), gb_len);
+
+       if (gb_len > NFC_MAX_GT_LEN)
+               return -EINVAL;
+
+       return nfc_llcp_set_remote_gb(dev, gb, gb_len);
+}
+EXPORT_SYMBOL(nfc_set_remote_general_bytes);
+
+u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len)
+{
+       return nfc_llcp_general_bytes(dev, gt_len);
+}
+EXPORT_SYMBOL(nfc_get_local_general_bytes);
+
 /**
- * nfc_alloc_skb - allocate a skb for data exchange responses
+ * nfc_alloc_send_skb - allocate a skb for data exchange responses
  *
  * @size: size to allocate
  * @gfp: gfp flags
  */
-struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
+struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
+                                       unsigned int flags, unsigned int size,
+                                       unsigned int *err)
+{
+       struct sk_buff *skb;
+       unsigned int total_size;
+
+       total_size = size +
+               dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
+
+       skb = sock_alloc_send_skb(sk, total_size, flags & MSG_DONTWAIT, err);
+       if (skb)
+               skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
+
+       return skb;
+}
+
+/**
+ * nfc_alloc_recv_skb - allocate a skb for data exchange responses
+ *
+ * @size: size to allocate
+ * @gfp: gfp flags
+ */
+struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp)
 {
        struct sk_buff *skb;
        unsigned int total_size;
@@ -308,7 +415,7 @@ struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
 
        return skb;
 }
-EXPORT_SYMBOL(nfc_alloc_skb);
+EXPORT_SYMBOL(nfc_alloc_recv_skb);
 
 /**
  * nfc_targets_found - inform that targets were found
@@ -326,7 +433,7 @@ int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
 {
        int i;
 
-       nfc_dbg("dev_name=%s n_targets=%d", dev_name(&dev->dev), n_targets);
+       pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets);
 
        dev->polling = false;
 
@@ -360,7 +467,7 @@ static void nfc_release(struct device *d)
 {
        struct nfc_dev *dev = to_nfc_dev(d);
 
-       nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+       pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
        nfc_genl_data_exit(&dev->genl_data);
        kfree(dev->targets);
@@ -446,7 +553,7 @@ int nfc_register_device(struct nfc_dev *dev)
 {
        int rc;
 
-       nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+       pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
        mutex_lock(&nfc_devlist_mutex);
        nfc_devlist_generation++;
@@ -456,11 +563,14 @@ int nfc_register_device(struct nfc_dev *dev)
        if (rc < 0)
                return rc;
 
-       rc = nfc_genl_device_added(dev);
+       rc = nfc_llcp_register_device(dev);
        if (rc)
-               nfc_dbg("The userspace won't be notified that the device %s was"
-                                               " added", dev_name(&dev->dev));
+               pr_err("Could not register llcp device\n");
 
+       rc = nfc_genl_device_added(dev);
+       if (rc)
+               pr_debug("The userspace won't be notified that the device %s was added\n",
+                        dev_name(&dev->dev));
 
        return 0;
 }
@@ -475,7 +585,7 @@ void nfc_unregister_device(struct nfc_dev *dev)
 {
        int rc;
 
-       nfc_dbg("dev_name=%s", dev_name(&dev->dev));
+       pr_debug("dev_name=%s\n", dev_name(&dev->dev));
 
        mutex_lock(&nfc_devlist_mutex);
        nfc_devlist_generation++;
@@ -488,10 +598,12 @@ void nfc_unregister_device(struct nfc_dev *dev)
 
        mutex_unlock(&nfc_devlist_mutex);
 
+       nfc_llcp_unregister_device(dev);
+
        rc = nfc_genl_device_removed(dev);
        if (rc)
-               nfc_dbg("The userspace won't be notified that the device %s"
-                                       " was removed", dev_name(&dev->dev));
+               pr_debug("The userspace won't be notified that the device %s was removed\n",
+                        dev_name(&dev->dev));
 
 }
 EXPORT_SYMBOL(nfc_unregister_device);
@@ -500,7 +612,7 @@ static int __init nfc_init(void)
 {
        int rc;
 
-       nfc_info("NFC Core ver %s", VERSION);
+       pr_info("NFC Core ver %s\n", VERSION);
 
        rc = class_register(&nfc_class);
        if (rc)
@@ -517,6 +629,10 @@ static int __init nfc_init(void)
        if (rc)
                goto err_rawsock;
 
+       rc = nfc_llcp_init();
+       if (rc)
+               goto err_llcp_sock;
+
        rc = af_nfc_init();
        if (rc)
                goto err_af_nfc;
@@ -524,6 +640,8 @@ static int __init nfc_init(void)
        return 0;
 
 err_af_nfc:
+       nfc_llcp_exit();
+err_llcp_sock:
        rawsock_exit();
 err_rawsock:
        nfc_genl_exit();
@@ -535,6 +653,7 @@ err_genl:
 static void __exit nfc_exit(void)
 {
        af_nfc_exit();
+       nfc_llcp_exit();
        rawsock_exit();
        nfc_genl_exit();
        class_unregister(&nfc_class);